From 539bae6c9c5f1e64308cfafddf07e12e8230cf6f Mon Sep 17 00:00:00 2001 From: ratkosrb Date: Sun, 5 May 2019 16:02:36 +0300 Subject: [PATCH] Make SpellEntry related functions into class members. --- src/game/AI/CreatureAI.cpp | 4 +- src/game/AI/GenericSpellAI.cpp | 4 +- src/game/AI/PetAI.cpp | 14 +- src/game/AI/PlayerAI.cpp | 8 +- src/game/AI/TotemAI.cpp | 6 +- src/game/Commands/DebugCommands.cpp | 10 +- src/game/Commands/LookupCommands.cpp | 2 +- src/game/Commands/UnitCommands.cpp | 12 +- src/game/Handlers/PetHandler.cpp | 6 +- src/game/Handlers/SpellHandler.cpp | 16 +- src/game/Objects/Creature.cpp | 16 +- src/game/Objects/DynamicObject.cpp | 4 +- src/game/Objects/GameObject.cpp | 2 +- src/game/Objects/Pet.cpp | 22 +- src/game/Objects/Player.cpp | 30 +- src/game/Objects/Totem.cpp | 8 +- src/game/Objects/Unit.cpp | 134 +-- src/game/ScriptMgr.cpp | 4 +- src/game/SharedDefines.h | 2 +- src/game/Spells/Spell.cpp | 144 ++-- src/game/Spells/SpellAuras.cpp | 88 +- src/game/Spells/SpellEffects.cpp | 49 +- src/game/Spells/SpellEntry.cpp | 939 +++++++++++++++++++-- src/game/Spells/SpellEntry.h | 727 ++++++++++++++++- src/game/Spells/SpellMgr.cpp | 1079 +------------------------ src/game/Spells/SpellMgr.h | 568 ------------- src/game/Threat/HostileRefManager.cpp | 2 +- src/game/UnitAuraProcHandler.cpp | 14 +- src/shared/Util.h | 6 +- 29 files changed, 1919 insertions(+), 2001 deletions(-) diff --git a/src/game/AI/CreatureAI.cpp b/src/game/AI/CreatureAI.cpp index 358e698a6..78731619e 100644 --- a/src/game/AI/CreatureAI.cpp +++ b/src/game/AI/CreatureAI.cpp @@ -72,11 +72,11 @@ CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, return CAST_FAIL_OTHER; // If the spell requires the target having a specific power type - if (!IsAreaOfEffectSpell(pSpell) && !IsTargetPowerTypeValid(pSpell, pTarget->getPowerType())) + if (!pSpell->IsAreaOfEffectSpell() && !pSpell->IsTargetPowerTypeValid(pTarget->getPowerType())) return CAST_FAIL_OTHER; // Mind control abilities can't be used with just 1 attacker or mob will reset. - if ((m_creature->getThreatManager().getThreatList().size() == 1) && IsCharmSpell(pSpell)) + if ((m_creature->getThreatManager().getThreatList().size() == 1) && pSpell->IsCharmSpell()) return CAST_FAIL_OTHER; // If the unit is disarmed and the skill requires a weapon, it cannot be cast diff --git a/src/game/AI/GenericSpellAI.cpp b/src/game/AI/GenericSpellAI.cpp index c7406c93d..5e563955e 100644 --- a/src/game/AI/GenericSpellAI.cpp +++ b/src/game/AI/GenericSpellAI.cpp @@ -444,7 +444,7 @@ void LoadSpellCacheData(GenericAISpell* spellToModify, SpellEntry const* spellIn if (spellToModify->healValue != 0) spellToModify->target = GENERIC_TARGET_FRIEND_NEED_HEAL; // Autres sorts positifs - else if (IsPositiveSpell(spellToModify->spellId)) + else if (Spells::IsPositiveSpell(spellToModify->spellId)) spellToModify->target = GENERIC_TARGET_SELF; /* 2 : Sorts negatifs*/ // Attaque a distance @@ -503,7 +503,7 @@ void LoadSpellCacheData(GenericAISpell* spellToModify, SpellEntry const* spellIn } case SPELL_EFFECT_SUMMON_GUARDIAN: { - int32 duration = GetSpellDuration(spellInfos); + int32 duration = spellInfos->GetDuration(); if (duration > 0) { spellToModify->minCD = duration; diff --git a/src/game/AI/PetAI.cpp b/src/game/AI/PetAI.cpp index f452c6e91..c5977f371 100644 --- a/src/game/AI/PetAI.cpp +++ b/src/game/AI/PetAI.cpp @@ -207,9 +207,9 @@ void PetAI::UpdateAI(const uint32 diff) if (m_creature->HasSpellCooldown(spellInfo->Id)) continue; - if (IsPositiveSpell(spellInfo->Id)) + if (spellInfo->IsPositiveSpell()) { - if (!IsNonCombatSpell(spellInfo)) // Can be used in combat. + if (!spellInfo->IsNonCombatSpell()) // Can be used in combat. { /* Spells handled here: @@ -219,12 +219,12 @@ void PetAI::UpdateAI(const uint32 diff) */ // Warlock Sacrifice: do not auto cast if not in combat - bool castOnlyInCombat = IsSpellHaveEffect(spellInfo, SPELL_EFFECT_INSTAKILL); + bool castOnlyInCombat = spellInfo->HasEffect(SPELL_EFFECT_INSTAKILL); if (!castOnlyInCombat) { - int32 duration = GetSpellDuration(spellInfo); - int32 cooldown = GetSpellRecoveryTime(spellInfo); + int32 duration = spellInfo->GetDuration(); + int32 cooldown = spellInfo->GetRecoveryTime(); // Keep this spell for when we will be in combat. if (cooldown >= 0 && duration >= 0 && cooldown > duration) castOnlyInCombat = true; @@ -237,7 +237,7 @@ void PetAI::UpdateAI(const uint32 diff) if (spellInfo->IsFitToFamily() && spellInfo->SpellVisual == 289) castOnlyInCombat = false; // Furious Howl: in combat only - if (IsSpellHaveAura(spellInfo, SPELL_AURA_MOD_DAMAGE_DONE)) + if (spellInfo->HasAura(SPELL_AURA_MOD_DAMAGE_DONE)) castOnlyInCombat = true; if (castOnlyInCombat && !m_creature->getVictim()) continue; @@ -285,7 +285,7 @@ void PetAI::UpdateAI(const uint32 diff) if (!spellUsed) spell->Delete(); } - else if (m_creature->getVictim() && CanAttack(m_creature->getVictim()) && !IsNonCombatSpell(spellInfo)) + else if (m_creature->getVictim() && CanAttack(m_creature->getVictim()) && !spellInfo->IsNonCombatSpell()) { Spell *spell = new Spell(m_creature, spellInfo, false); if (spell->CanAutoCast(m_creature->getVictim())) diff --git a/src/game/AI/PlayerAI.cpp b/src/game/AI/PlayerAI.cpp index 399a50004..cdc603281 100644 --- a/src/game/AI/PlayerAI.cpp +++ b/src/game/AI/PlayerAI.cpp @@ -135,7 +135,7 @@ PlayerControlledAI::PlayerControlledAI(Player* pPlayer, Unit* caster) : uiGlobal continue; if (spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_DAMAGE) continue; - if (IsPositiveSpell(itr->first) && !enablePositiveSpells) + if (Spells::IsPositiveSpell(itr->first) && !enablePositiveSpells) continue; switch (pPlayer->getClass()) { @@ -168,7 +168,7 @@ PlayerControlledAI::PlayerControlledAI(Player* pPlayer, Unit* caster) : uiGlobal SpellEntry const *pCurrSpell_2 = sSpellMgr.GetSpellEntry(*(it2)); if (pCurrSpell_2->SpellFamilyName == pCurrSpell_1->SpellFamilyName && pCurrSpell_2->SpellIconID == pCurrSpell_1->SpellIconID && pCurrSpell_2->SpellVisual == pCurrSpell_1->SpellVisual) // Meme sort, rangs differents { - if (CompareAuraRanks(pCurrSpell_1->Id, pCurrSpell_2->Id) < 0) // pCurrSpell_1 < pCurrSpell_2 + if (Spells::CompareAuraRanks(pCurrSpell_1->Id, pCurrSpell_2->Id) < 0) // pCurrSpell_1 < pCurrSpell_2 { // Donc on supprime pCurrSpell_1 foundSupRank = true; @@ -384,9 +384,9 @@ void PlayerControlledAI::UpdateAI(const uint32 uiDiff) // If its a positive spell we prioritize controller, if he's out of range, // ourself, otherwise it will probably not be cast. Unit* spellTarget = victim; - if (controller && IsPositiveSpell(spellInfo, me, controller)) + if (controller && spellInfo->IsPositiveSpell(me, controller)) spellTarget = controller; - else if (IsPositiveSpell(spellInfo, me, me)) + else if (spellInfo->IsPositiveSpell(me, me)) spellTarget = me; if (spellInfo) diff --git a/src/game/AI/TotemAI.cpp b/src/game/AI/TotemAI.cpp index a57dfe443..3ae5f919a 100644 --- a/src/game/AI/TotemAI.cpp +++ b/src/game/AI/TotemAI.cpp @@ -50,13 +50,13 @@ TotemAI::TotemAI(Creature *pCreature) : CreatureAI(pCreature) { m_spellId = m_creature->GetCreatureInfo()->spells[0]; SpellEntry const* totemSpell = sSpellMgr.GetSpellEntry(m_spellId); - if (totemSpell && GetSpellCastTime(totemSpell)) + if (totemSpell && totemSpell->GetCastTime()) m_totemType = TOTEM_ACTIVE; else { m_totemType = TOTEM_PASSIVE; - if (totemSpell && IsSpellAppliesAura(totemSpell)) + if (totemSpell && totemSpell->IsSpellAppliesAura()) pCreature->CastSpell(pCreature, totemSpell, true); } @@ -76,7 +76,7 @@ void TotemAI::UpdateAI(const uint32 /*diff*/) return; SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - float max_range = GetSpellMaxRange(srange); + float max_range = Spells::GetSpellMaxRange(srange); Unit* victim = m_creature->GetMap()->GetUnit(m_victimGuid); Unit* owner = m_creature->GetCharmerOrOwner(); diff --git a/src/game/Commands/DebugCommands.cpp b/src/game/Commands/DebugCommands.cpp index 414fab587..ef9793204 100644 --- a/src/game/Commands/DebugCommands.cpp +++ b/src/game/Commands/DebugCommands.cpp @@ -140,7 +140,7 @@ bool ChatHandler::HandleSpellInfosCommand(char *args) PSendSysMessage("MaxTargetLevel%u:DmgClass%u:rangeIndex%u", pSpell->MaxTargetLevel, pSpell->DmgClass, pSpell->rangeIndex); PSendSysMessage("procChance%u:procFlags0x%x:procCharges%u", pSpell->procChance, pSpell->procFlags, pSpell->procCharges); PSendSysMessage("InterruptFlags0x%x:AuraInterruptFlags0x%x:PreventionType%x:spellLevel%u", pSpell->InterruptFlags, pSpell->AuraInterruptFlags, pSpell->PreventionType, pSpell->spellLevel); - PSendSysMessage("SpellSpecific%u:Binaire%s:spellPriority%u:Positive%u", GetSpellSpecific(pSpell->Id), pSpell->IsBinary() ? "OUI" : "NON", pSpell->spellPriority, IsPositiveSpell(pSpell->Id)); + PSendSysMessage("SpellSpecific%u:Binaire%s:spellPriority%u:Positive%u", Spells::GetSpellSpecific(pSpell->Id), pSpell->IsBinary() ? "OUI" : "NON", pSpell->spellPriority, pSpell->IsPositiveSpell()); PSendSysMessage("RecoveryTime%u:CategoryRecoveryTime%u:PvEHeartBeat%s", pSpell->RecoveryTime, pSpell->CategoryRecoveryTime, pSpell->IsPvEHeartBeat() ? "OUI" : "NON"); return true; } @@ -234,7 +234,7 @@ bool ChatHandler::HandleDebugSendNextChannelSpellVisualCommand(char *args) for (id = uiPlayId + 1; id <= sSpellMgr.GetMaxSpellId(); id++) { spellInfo = sSpellMgr.GetSpellEntry(id); - if (!spellInfo || uiPlayId >= spellInfo->Id || !spellInfo->SpellVisual || !IsChanneledSpell(spellInfo)) + if (!spellInfo || uiPlayId >= spellInfo->Id || !spellInfo->SpellVisual || !spellInfo->IsChanneledSpell()) continue; else break; @@ -1348,8 +1348,8 @@ bool ChatHandler::HandleDebugSpellCoefsCommand(char* args) SpellBonusEntry const* bonus = sSpellMgr.GetSpellBonusData(spellid); - float direct_calc = CalculateDefaultCoefficient(spellEntry, SPELL_DIRECT_DAMAGE); - float dot_calc = CalculateDefaultCoefficient(spellEntry, DOT); + float direct_calc = spellEntry->CalculateDefaultCoefficient(SPELL_DIRECT_DAMAGE); + float dot_calc = spellEntry->CalculateDefaultCoefficient(DOT); bool isDirectHeal = false; for (int i = 0; i < 3; ++i) @@ -1534,7 +1534,7 @@ bool ChatHandler::HandleSendSpellVisualCommand(char *args) m_session->GetPlayer()->SendSpellGo(pTarget, uiPlayId); // Channeled case - if (IsChanneledSpell(proto)) + if (proto->IsChanneledSpell()) { m_session->GetPlayer()->SetUInt32Value(UNIT_CHANNEL_SPELL, uiPlayId); m_session->GetPlayer()->SetChannelObjectGuid(pTarget->GetObjectGuid()); diff --git a/src/game/Commands/LookupCommands.cpp b/src/game/Commands/LookupCommands.cpp index aada1a781..270d3915e 100644 --- a/src/game/Commands/LookupCommands.cpp +++ b/src/game/Commands/LookupCommands.cpp @@ -411,7 +411,7 @@ void ChatHandler::ShowSpellListHelper(Player* target, SpellEntry const* spellInf uint32 talentCost = GetTalentSpellCost(id); bool talent = (talentCost > 0); - bool passive = IsPassiveSpell(spellInfo); + bool passive = spellInfo->IsPassiveSpell(); bool active = target && target->HasAura(id); // unit32 used to prevent interpreting uint8 as char at output diff --git a/src/game/Commands/UnitCommands.cpp b/src/game/Commands/UnitCommands.cpp index 90abb55b7..01b1cb8f1 100644 --- a/src/game/Commands/UnitCommands.cpp +++ b/src/game/Commands/UnitCommands.cpp @@ -279,8 +279,8 @@ bool ChatHandler::HandleAuraCommand(char* args) if (!spellInfo) return false; - if (!IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && - !IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (!spellInfo->IsSpellAppliesAura((1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && + !spellInfo->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { PSendSysMessage(LANG_SPELL_NO_HAVE_AURAS, spellID); SetSentErrorMessage(true); @@ -300,7 +300,7 @@ bool ChatHandler::HandleAuraCommand(char* args) uint8 eff = spellInfo->Effect[i]; if (eff >= TOTAL_SPELL_EFFECTS) continue; - if (IsAreaAuraEffect(eff) || + if (Spells::IsAreaAuraEffect(eff) || eff == SPELL_EFFECT_APPLY_AURA || eff == SPELL_EFFECT_PERSISTENT_AREA_AURA) { @@ -1845,8 +1845,8 @@ bool ChatHandler::HandleFearCommand(char* /*args*/) if (!spellInfo) return false; - if (!IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && - !IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (!spellInfo->IsSpellAppliesAura((1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && + !spellInfo->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { PSendSysMessage(LANG_SPELL_NO_HAVE_AURAS, fearID); SetSentErrorMessage(true); @@ -1860,7 +1860,7 @@ bool ChatHandler::HandleFearCommand(char* /*args*/) uint8 eff = spellInfo->Effect[i]; if (eff >= TOTAL_SPELL_EFFECTS) continue; - if (IsAreaAuraEffect(eff) || + if (Spells::IsAreaAuraEffect(eff) || eff == SPELL_EFFECT_APPLY_AURA || eff == SPELL_EFFECT_PERSISTENT_AREA_AURA) { diff --git a/src/game/Handlers/PetHandler.cpp b/src/game/Handlers/PetHandler.cpp index 3411cbd3d..95223ed8d 100644 --- a/src/game/Handlers/PetHandler.cpp +++ b/src/game/Handlers/PetHandler.cpp @@ -238,7 +238,7 @@ void WorldSession::HandlePetAction(WorldPacket& recv_data) } // do not cast not learned spells - if (!pCharmedUnit->HasSpell(spellid) || IsPassiveSpell(spellInfo)) + if (!pCharmedUnit->HasSpell(spellid) || spellInfo->IsPassiveSpell()) return; pCharmedUnit->clearUnitState(UNIT_STAT_MOVING); @@ -639,7 +639,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) } // do not add not learned spells/ passive spells - if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) + if (!pet->HasSpell(spellid) || Spells::IsPassiveSpell(spellid)) return; CharmInfo* charmInfo = pet->GetCharmInfo(); @@ -688,7 +688,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) return; // do not cast not learned spells - if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) + if (!pet->HasSpell(spellid) || spellInfo->IsPassiveSpell()) return; SpellCastTargets targets; diff --git a/src/game/Handlers/SpellHandler.cpp b/src/game/Handlers/SpellHandler.cpp index 040664bb6..9637a2e91 100644 --- a/src/game/Handlers/SpellHandler.cpp +++ b/src/game/Handlers/SpellHandler.cpp @@ -32,6 +32,8 @@ #include "Totem.h" #include "SpellAuras.h" +using namespace Spells; + void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { uint8 bagIndex, slot; @@ -97,7 +99,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { if (SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(proto->Spells[i].SpellId)) { - if (IsNonCombatSpell(spellInfo)) + if (spellInfo->IsNonCombatSpell()) { recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT, pItem, NULL); @@ -295,7 +297,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) if (_player->GetTypeId() == TYPEID_PLAYER) { // not have spell in spellbook or spell passive and not casted by client - if (!_player->HasActiveSpell(spellId) || IsPassiveSpell(spellInfo)) + if (!_player->HasActiveSpell(spellId) || spellInfo->IsPassiveSpell()) { sLog.outError("World: Player %u casts spell %u which he shouldn't have", _player->GetGUIDLow(), spellId); //cheater? kick? ban? @@ -306,7 +308,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) else if (_player->GetTypeId() == TYPEID_UNIT) { // not have spell in spellbook or spell passive and not casted by client - if (!_player->HasSpell(spellId) || IsPassiveSpell(spellInfo)) + if (!_player->HasSpell(spellId) || spellInfo->IsPassiveSpell()) { //cheater? kick? ban? recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet @@ -324,7 +326,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { // Cannot cast negative spells on yourself. Handle it here since casting negative // spells on yourself is frequently used within the core itself for certain mechanics. - if (target == _player && IsExplicitlySelectedUnitTarget(spellInfo->EffectImplicitTargetA[0]) && !IsPositiveSpell(spellInfo, _player, target)) + if (target == _player && IsExplicitlySelectedUnitTarget(spellInfo->EffectImplicitTargetA[0]) && !spellInfo->IsPositiveSpell(_player, target)) { WorldPacket data(SMSG_CAST_RESULT, (4 + 1 + 1)); data << uint32(spellId); @@ -394,7 +396,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) if (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL) return; - if (IsPassiveSpell(spellInfo)) + if (spellInfo->IsPassiveSpell()) return; if (!IsPositiveSpell(spellId)) @@ -435,7 +437,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) } // channeled spell case (it currently casted then) - if (IsChanneledSpell(spellInfo)) + if (spellInfo->IsChanneledSpell()) { if (Spell* curSpell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) if (curSpell->m_spellInfo->Id == spellId) @@ -446,7 +448,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) SpellAuraHolder *holder = _player->GetSpellAuraHolder(spellId); // not own area auras can't be cancelled (note: maybe need to check for aura on holder and not general on spell) - if (holder && holder->GetCasterGuid() != _player->GetObjectGuid() && HasAreaAuraEffect(holder->GetSpellProto())) + if (holder && holder->GetCasterGuid() != _player->GetObjectGuid() && holder->GetSpellProto()->HasAreaAuraEffect()) return; // non channeled case diff --git a/src/game/Objects/Creature.cpp b/src/game/Objects/Creature.cpp index 88cc0aad4..5933bed1b 100644 --- a/src/game/Objects/Creature.cpp +++ b/src/game/Objects/Creature.cpp @@ -2523,8 +2523,8 @@ bool Creature::MeetsSelectAttackingRequirement(Unit* pTarget, SpellEntry const* } SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(pSpellInfo->rangeIndex); - float max_range = GetSpellMaxRange(srange); - float min_range = GetSpellMinRange(srange); + float max_range = Spells::GetSpellMaxRange(srange); + float min_range = Spells::GetSpellMinRange(srange); float dist = GetCombatDistance(pTarget); return dist < max_range && dist >= min_range; @@ -3475,23 +3475,23 @@ SpellCastResult Creature::TryToCast(Unit* pTarget, const SpellEntry* pSpellInfo, if (pSpellInfo->Custom & SPELL_CUSTOM_FROM_BEHIND && pTarget->HasInArc(M_PI_F, this)) return SPELL_FAILED_UNIT_NOT_BEHIND; - if (!IsAreaOfEffectSpell(pSpellInfo)) + if (!pSpellInfo->IsAreaOfEffectSpell()) { // If the spell requires the target having a specific power type. - if (!IsTargetPowerTypeValid(pSpellInfo, pTarget->getPowerType())) + if (!pSpellInfo->IsTargetPowerTypeValid(pTarget->getPowerType())) return SPELL_FAILED_UNKNOWN; // No point in casting if target is immune. - if (pTarget->IsImmuneToDamage(GetSpellSchoolMask(pSpellInfo), pSpellInfo)) + if (pTarget->IsImmuneToDamage(pSpellInfo->GetSpellSchoolMask(), pSpellInfo)) return SPELL_FAILED_IMMUNE; } // Mind control abilities can't be used with just 1 attacker or mob will reset. - if ((getThreatManager().getThreatList().size() == 1) && IsCharmSpell(pSpellInfo)) + if ((getThreatManager().getThreatList().size() == 1) && pSpellInfo->IsCharmSpell()) return SPELL_FAILED_UNKNOWN; // Do not use dismounting spells when target is not mounted (there are 4 such spells). - if (!pTarget->IsMounted() && IsDismountSpell(pSpellInfo)) + if (!pTarget->IsMounted() && pSpellInfo->IsDismountSpell()) return SPELL_FAILED_ONLY_MOUNTED; } @@ -3639,7 +3639,7 @@ void Creature::ApplyGameEventSpells(GameEventCreatureData const* eventData, bool if (remove_spell) if (SpellEntry const* spellEntry = sSpellMgr.GetSpellEntry(remove_spell)) - if (IsSpellAppliesAura(spellEntry)) + if (spellEntry->IsSpellAppliesAura()) RemoveAurasDueToSpell(remove_spell); if (cast_spell) diff --git a/src/game/Objects/DynamicObject.cpp b/src/game/Objects/DynamicObject.cpp index 954ea63e1..c60810bf4 100644 --- a/src/game/Objects/DynamicObject.cpp +++ b/src/game/Objects/DynamicObject.cpp @@ -117,8 +117,8 @@ bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, SpellEf m_radius = radius; m_effIndex = effIndex; m_spellId = spellId; - m_positive = IsPositiveEffect(spellProto, m_effIndex); - m_channeled = IsChanneledSpell(spellProto); + m_positive = spellProto->IsPositiveEffect(m_effIndex); + m_channeled = spellProto->IsChanneledSpell(); return true; } diff --git a/src/game/Objects/GameObject.cpp b/src/game/Objects/GameObject.cpp index b7838cf6b..4db8a37ed 100644 --- a/src/game/Objects/GameObject.cpp +++ b/src/game/Objects/GameObject.cpp @@ -1161,7 +1161,7 @@ void GameObject::TriggerLinkedGameObject(Unit* target) float range = 0.5f; if (trapSpell) // checked at load already - range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(trapSpell->rangeIndex)); + range = Spells::GetSpellMaxRange(sSpellRangeStore.LookupEntry(trapSpell->rangeIndex)); // search nearest linked GO GameObject* trapGO = NULL; diff --git a/src/game/Objects/Pet.cpp b/src/game/Objects/Pet.cpp index 1d54a6eb5..a2922cbf7 100644 --- a/src/game/Objects/Pet.cpp +++ b/src/game/Objects/Pet.cpp @@ -188,7 +188,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c uint32 summon_spell_id = m_pTmpCache->CreatedBySpell; SpellEntry const* spellInfo = sSpellMgr.GetSpellEntry(summon_spell_id); - bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; + bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; // check temporary summoned pets like mage water elemental if (current && is_temporary_summoned) @@ -896,7 +896,7 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid) uint8 activecount = 1; uint32 chainstartstore[ACTIVE_SPELLS_MAX]; - if (IsPassiveSpell(spellid)) + if (Spells::IsPassiveSpell(spellid)) return true; chainstartstore[0] = sSpellMgr.GetFirstSpellInChain(spellid); @@ -906,7 +906,7 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid) if (itr->second.state == PETSPELL_REMOVED) continue; - if (IsPassiveSpell(itr->first)) + if (Spells::IsPassiveSpell(itr->first)) continue; uint32 chainstart = sSpellMgr.GetFirstSpellInChain(itr->first); @@ -1512,7 +1512,7 @@ void Pet::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) if (spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) continue; - if ((idSchoolMask & GetSpellSchoolMask(spellInfo)) && GetSpellCooldownDelay(unSpellId) < unTimeMs) + if ((idSchoolMask & spellInfo->GetSpellSchoolMask()) && GetSpellCooldownDelay(unSpellId) < unTimeMs) { data << uint32(unSpellId); data << uint32(unTimeMs); // in m.secs @@ -1723,10 +1723,10 @@ void Pet::_LoadAuras(uint32 timediff) } // do not load single target auras (unless they were cast by the player) - if (casterGuid != GetObjectGuid() && HasSingleTargetAura(spellproto)) + if (casterGuid != GetObjectGuid() && spellproto->HasSingleTargetAura()) continue; - if (remaintime != -1 && !IsPositiveSpell(spellproto)) + if (remaintime != -1 && !spellproto->IsPositiveSpell()) { if (remaintime / IN_MILLISECONDS <= int32(timediff)) continue; @@ -1814,7 +1814,7 @@ void Pet::_SaveAuras() //skip all holders from spells that are passive or channeled //do not save single target holders (unless they were cast by the player) - if (save && !holder->IsPassive() && !IsChanneledSpell(holder->GetSpellProto()) && (holder->GetCasterGuid() == GetObjectGuid() || !holder->IsSingleTarget())) + if (save && !holder->IsPassive() && !holder->GetSpellProto()->IsChanneledSpell() && (holder->GetCasterGuid() == GetObjectGuid() || !holder->IsSingleTarget())) { int32 damage[MAX_EFFECT_INDEX]; uint32 periodicTime[MAX_EFFECT_INDEX]; @@ -1929,7 +1929,7 @@ bool Pet::AddSpell(uint32 spell_id, ActiveStates active /*= ACT_DECIDE*/, PetSpe if (active == ACT_DECIDE) //active was not used before, so we save it's autocast/passive state here { - if (IsPassiveSpell(spellInfo)) + if (spellInfo->IsPassiveSpell()) newspell.active = ACT_PASSIVE; else newspell.active = ACT_DISABLED; @@ -1966,7 +1966,7 @@ bool Pet::AddSpell(uint32 spell_id, ActiveStates active /*= ACT_DECIDE*/, PetSpe m_petSpells[spell_id] = newspell; - if (IsPassiveSpell(spellInfo)) + if (spellInfo->IsPassiveSpell()) CastSpell(this, spell_id, true); else m_charmInfo->AddSpellToActionBar(spell_id, ActiveStates(newspell.active)); @@ -2075,7 +2075,7 @@ void Pet::InitPetCreateSpells() petspellid = learn_spellproto->EffectTriggerSpell[0]; if (p_owner && !p_owner->HasSpell(learn_spellproto->Id)) { - if (IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right + if (Spells::IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right p_owner->LearnSpell(learn_spellproto->Id, false); else AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id); @@ -2145,7 +2145,7 @@ uint32 Pet::GetResetTalentsCost() const void Pet::ToggleAutocast(uint32 spellid, bool apply) { - if (IsPassiveSpell(spellid)) + if (Spells::IsPassiveSpell(spellid)) return; PetSpellMap::iterator itr = m_petSpells.find(spellid); diff --git a/src/game/Objects/Player.cpp b/src/game/Objects/Player.cpp index b2e0f2cf9..1e2659f72 100644 --- a/src/game/Objects/Player.cpp +++ b/src/game/Objects/Player.cpp @@ -3396,7 +3396,7 @@ bool Player::AddSpell(uint32 spell_id, bool active, bool learning, bool dependen // cast talents with SPELL_EFFECT_LEARN_SPELL (other dependent spells will learned later as not auto-learned) // note: all spells with SPELL_EFFECT_LEARN_SPELL isn't passive - if (talentPos && IsSpellHaveEffect(spellInfo, SPELL_EFFECT_LEARN_SPELL)) + if (talentPos && spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL)) { // ignore stance requirement for talent learn spell (stance set for spell only for client spell description show) CastSpell(this, spell_id, true); @@ -3404,7 +3404,7 @@ bool Player::AddSpell(uint32 spell_id, bool active, bool learning, bool dependen // also cast passive (and passive like) spells (including all talents without SPELL_EFFECT_LEARN_SPELL) with additional checks else if (IsNeedCastPassiveLikeSpellAtLearn(spellInfo)) CastSpell(this, spell_id, true); - else if (IsSpellHaveEffect(spellInfo, SPELL_EFFECT_SKILL_STEP)) + else if (spellInfo->HasEffect(SPELL_EFFECT_SKILL_STEP)) { CastSpell(this, spell_id, true); return false; @@ -3435,7 +3435,7 @@ bool Player::IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) cons { ShapeshiftForm form = GetShapeshiftForm(); - if (IsNeedCastSpellAtFormApply(spellInfo, form)) // SPELL_ATTR_PASSIVE | SPELL_ATTR_UNK7 spells + if (spellInfo->IsNeedCastSpellAtFormApply(form)) // SPELL_ATTR_PASSIVE | SPELL_ATTR_UNK7 spells return true; // all stance req. cases, not have auarastate cases if (!(spellInfo->Attributes & SPELL_ATTR_PASSIVE)) @@ -3488,7 +3488,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) // Always try to remove all dependent spells if present (needed to reset some talents properly) SpellLearnSpellMapBounds spell_bounds = sSpellMgr.GetSpellLearnSpellMapBounds(spell_id); for (SpellLearnSpellMap::const_iterator child_itr = spell_bounds.first; child_itr != spell_bounds.second; ++child_itr) - RemoveSpell(child_itr->second.spell, !IsPassiveSpell(child_itr->second.spell), !IsPassiveSpell(child_itr->second.spell)); + RemoveSpell(child_itr->second.spell, !Spells::IsPassiveSpell(child_itr->second.spell), !Spells::IsPassiveSpell(child_itr->second.spell)); // search again just in case itr = m_spells.find(spell_id); @@ -3506,7 +3506,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) SpellChainMapNext const& nextMap = sSpellMgr.GetSpellChainNext(); for (SpellChainMapNext::const_iterator itr2 = nextMap.lower_bound(spell_id); itr2 != nextMap.upper_bound(spell_id); ++itr2) if (HasSpell(itr2->second) && !GetTalentSpellPos(itr2->second)) - RemoveSpell(itr2->second, !IsPassiveSpell(itr2->second), false); + RemoveSpell(itr2->second, !Spells::IsPassiveSpell(itr2->second), false); // re-search, it can be corrupted in prev loop itr = m_spells.find(spell_id); @@ -3633,7 +3633,7 @@ void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) if (spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) continue; - if ((idSchoolMask & GetSpellSchoolMask(spellInfo)) && GetSpellCooldownDelay(unSpellId) < unTimeMs) + if ((idSchoolMask & spellInfo->GetSpellSchoolMask()) && GetSpellCooldownDelay(unSpellId) < unTimeMs) { data << uint32(unSpellId); data << uint32(unTimeMs); // in m.secs @@ -3824,7 +3824,7 @@ bool Player::ResetTalents(bool no_cost) RemoveAurasDueToSpell(pInfos->EffectTriggerSpell[eff]); if (talentInfo->RankID[j]) - RemoveSpell(talentInfo->RankID[j], !IsPassiveSpell(talentInfo->RankID[j]), false); + RemoveSpell(talentInfo->RankID[j], !Spells::IsPassiveSpell(talentInfo->RankID[j]), false); } } @@ -5931,7 +5931,7 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type, Pl { if (!player->HasSpell(spellProto->Id)) return false; - else if (IsPassiveSpell(spellProto)) + else if (spellProto->IsPassiveSpell()) return false; } break; @@ -6093,7 +6093,7 @@ void Player::CheckAreaExploreAndOutdoor() if (itr->second.state == PLAYERSPELL_REMOVED) continue; SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(itr->first); - if (!spellInfo || !IsNeedCastSpellAtFormApply(spellInfo, GetShapeshiftForm()) || + if (!spellInfo || !spellInfo->IsNeedCastSpellAtFormApply(GetShapeshiftForm()) || !(spellInfo->Attributes & SPELL_ATTR_OUTDOORS_ONLY) || HasAura(spellInfo->Id)) continue; @@ -7067,7 +7067,7 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply if (apply) { // Cannot be used in this stance/form - if (GetErrorAtShapeshiftedCast(spellInfo, GetShapeshiftForm()) != SPELL_CAST_OK) + if (spellInfo->GetErrorAtShapeshiftedCast(GetShapeshiftForm()) != SPELL_CAST_OK) return; if (form_change) // check aura active state from other form @@ -7101,7 +7101,7 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply if (form_change) // check aura compatibility { // Cannot be used in this stance/form - if (GetErrorAtShapeshiftedCast(spellInfo, GetShapeshiftForm()) == SPELL_CAST_OK) + if (spellInfo->GetErrorAtShapeshiftedCast(GetShapeshiftForm()) == SPELL_CAST_OK) return; // and remove only not compatible at form change } @@ -7177,7 +7177,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) } // not allow proc extra attack spell at extra attack - if (GetExtraAttacks() && IsSpellHaveEffect(spellInfo, SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) + if (GetExtraAttacks() && spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) return; float chance = (float)spellInfo->procChance; @@ -7229,7 +7229,7 @@ void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType) uint32 charges = item->GetEnchantmentCharges(EnchantmentSlot(e_slot)); // PMonsterSay("Casted spell %u with %u charges.", proc_spell_id, charges); - if (IsPositiveSpell(spellInfo->Id)) + if (spellInfo->IsPositiveSpell()) CastSpell(this, spellInfo->Id, true, item); else CastSpell(Target, spellInfo->Id, true, item); @@ -15110,7 +15110,7 @@ void Player::LoadAura(AuraSaveStruct& s, uint32 timediff) return; } - if (s.remaintime != -1 && HasRealTimeDuration(spellproto)) + if (s.remaintime != -1 && spellproto->HasRealTimeDuration()) { if (timediff > (INT_MAX / IN_MILLISECONDS)) return; @@ -16199,7 +16199,7 @@ bool Player::SaveAura(SpellAuraHolder* holder, AuraSaveStruct& saveStruct) //skip all holders from spells that are passive or channeled //do not save single target holders (unless they were cast by the player) - if (!holder->IsPassive() && !IsChanneledSpell(holder->GetSpellProto()) && (holder->GetCasterGuid() == GetObjectGuid() || !holder->IsSingleTarget())) + if (!holder->IsPassive() && !holder->GetSpellProto()->IsChanneledSpell() && (holder->GetCasterGuid() == GetObjectGuid() || !holder->IsSingleTarget())) { saveStruct.effIndexMask = 0; diff --git a/src/game/Objects/Totem.cpp b/src/game/Objects/Totem.cpp index 67222012a..715c98d4a 100644 --- a/src/game/Objects/Totem.cpp +++ b/src/game/Objects/Totem.cpp @@ -179,7 +179,7 @@ void Totem::SetTypeBySummonSpell(SpellEntry const * spellProto) if (totemSpell) { // If spell have cast time -> so its active totem - if (GetSpellCastTime(totemSpell)) + if (totemSpell->GetCastTime()) m_type = TOTEM_ACTIVE; } if (spellProto->SpellIconID == 2056) @@ -218,16 +218,16 @@ bool Totem::IsImmuneToSpellEffect(SpellEntry const *spellInfo, SpellEffectIndex break; } - if (!IsPositiveSpell(spellInfo)) + if (!spellInfo->IsPositiveSpell()) { // immune to all negative auras - if (IsSpellAppliesAura(spellInfo, 1 << index)) + if (spellInfo->IsSpellAppliesAura(1 << index)) return true; } else { // immune to any type of regeneration auras hp/mana etc. - if (IsPeriodicRegenerateEffect(spellInfo, index)) + if (spellInfo->IsPeriodicRegenerateEffect(index)) return true; } return Creature::IsImmuneToSpellEffect(spellInfo, index, castOnSelf); diff --git a/src/game/Objects/Unit.cpp b/src/game/Objects/Unit.cpp index 3369eb8d5..8c8a1d795 100644 --- a/src/game/Objects/Unit.cpp +++ b/src/game/Objects/Unit.cpp @@ -957,13 +957,13 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa // polymorphed, hex and other negative transformed cases uint32 morphSpell = pVictim->getTransForm(); - if (morphSpell && !IsPositiveSpell(morphSpell)) + if (morphSpell && !Spells::IsPositiveSpell(morphSpell)) { if (SpellEntry const* morphEntry = sSpellMgr.GetSpellEntry(morphSpell)) { - if (IsSpellHaveAura(morphEntry, SPELL_AURA_MOD_CONFUSE)) + if (morphEntry->HasAura(SPELL_AURA_MOD_CONFUSE)) pVictim->RemoveAurasDueToSpell(morphSpell); - else if (IsSpellHaveAura(morphEntry, SPELL_AURA_MOD_PACIFY_SILENCE)) + else if (morphEntry->HasAura(SPELL_AURA_MOD_PACIFY_SILENCE)) pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_PACIFY_SILENCE, damage); } } @@ -1007,7 +1007,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa // Prevent item procs from breaking the CC that caused them bool isProcSpell = false; if (spell && spell->m_triggeredBySpellInfo && spell->m_triggeredByParentSpellInfo) - isProcSpell = HasAuraWithSpellTriggerEffect(spell->m_triggeredBySpellInfo); + isProcSpell = spell->m_triggeredBySpellInfo->HasAuraWithSpellTriggerEffect(); if (isProcSpell) pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DAMAGE, spell->m_triggeredByParentSpellInfo->Id); @@ -2127,7 +2127,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) AuraList const& mModDamagePercentDone = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) { - if (((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(i_spellProto)) && + if (((*i)->GetModifier()->m_miscvalue & i_spellProto->GetSpellSchoolMask()) && (*i)->GetSpellProto()->EquippedItemClass == -1 && (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0) { @@ -2140,7 +2140,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) // for example, Death Talon Seethers with Aura of Flames reflect 1200 damage to tanks with Mark of Flame if (pVictim->GetTypeId() == TYPEID_UNIT) { - int32 spellDmgTakenBonus = this->SpellBaseDamageBonusTaken(GetSpellSchoolMask(i_spellProto)); + int32 spellDmgTakenBonus = this->SpellBaseDamageBonusTaken(i_spellProto->GetSpellSchoolMask()); // don't allow damage shields to be reduced by Blessing of Sanctuary, etc. if (spellDmgTakenBonus > 0) damage += spellDmgTakenBonus; } @@ -2160,7 +2160,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) data << uint32(i_spellProto->School); pVictim->SendObjectMessageToSet(&data, true); - pVictim->DealDamage(this, damage, nullptr, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(i_spellProto), i_spellProto, true); + pVictim->DealDamage(this, damage, nullptr, SPELL_DIRECT_DAMAGE, i_spellProto->GetSpellSchoolMask(), i_spellProto, true); i = vDamageShields.begin(); } @@ -2487,7 +2487,7 @@ void Unit::CalculateAbsorbResistBlock(Unit *pCaster, SpellNonMeleeDamage *damage damageInfo->damage -= damageInfo->blocked; } - CalculateDamageAbsorbAndResist(pCaster, GetSpellSchoolMask(spellProto), SPELL_DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist, spellProto, spell); + CalculateDamageAbsorbAndResist(pCaster, spellProto->GetSpellSchoolMask(), SPELL_DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist, spellProto, spell); const uint32 bonus = (damageInfo->resist < 0 ? uint32(std::abs(damageInfo->resist)) : 0); damageInfo->damage += bonus; const uint32 malus = (damageInfo->resist > 0 ? (damageInfo->absorb + uint32(damageInfo->resist)) : damageInfo->absorb); @@ -3161,7 +3161,7 @@ int32 Unit::MagicSpellHitChance(Unit *pVictim, SpellEntry const *spell, Spell* s if (spell->AttributesEx3 & SPELL_ATTR_EX3_CANT_MISS) return 10000; - SpellSchoolMask schoolMask = GetSpellSchoolMask(spell); + SpellSchoolMask schoolMask = spell->GetSpellSchoolMask(); // PvP - PvE spell misschances per leveldif > 2 int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 7 : 11; int32 leveldif = int32(pVictim->GetLevelForTarget(this)) - int32(GetLevelForTarget(pVictim)); @@ -3186,7 +3186,7 @@ int32 Unit::MagicSpellHitChance(Unit *pVictim, SpellEntry const *spell, Spell* s DEBUG_UNIT(this, DEBUG_SPELL_COMPUTE_RESISTS, "SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE (+ %i) : %f", pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask), modHitChance); // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura - if (IsAreaOfEffectSpell(spell)) + if (spell->IsAreaOfEffectSpell()) { modHitChance -= pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE); DEBUG_UNIT(this, DEBUG_SPELL_COMPUTE_RESISTS, "SPELL_AURA_MOD_AOE_AVOIDANCE (- %i) : %f", pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE), modHitChance); @@ -3242,7 +3242,7 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, Spell // All positive spells can`t miss // TODO: client not show miss log for this spells - so need find info for this in dbc and use it! - if (IsPositiveSpell(spell->Id, this, pVictim) || IsPositiveEffect(spell, effIndex, this, pVictim)) + if (spell->IsPositiveSpell(this, pVictim) || spell->IsPositiveEffect(effIndex, this, pVictim)) return SPELL_MISS_NONE; // Check for immune (use charges) @@ -3250,7 +3250,7 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, Spell if (spellPtr) schoolMask = spellPtr->m_spellSchoolMask; else - schoolMask = GetSpellSchoolMask(spell); + schoolMask = spell->GetSpellSchoolMask(); if (pVictim != this && pVictim->IsImmuneToDamage(schoolMask, spell)) return SPELL_MISS_IMMUNE; @@ -3261,7 +3261,7 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, Spell int32 reflectchance = pVictim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS); Unit::AuraList const& mReflectSpellsSchool = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); for (Unit::AuraList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) - if ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spell)) + if ((*i)->GetModifier()->m_miscvalue & spell->GetSpellSchoolMask()) reflectchance += (*i)->GetModifier()->m_amount; if (reflectchance > 0 && roll_chance_i(reflectchance)) { @@ -3312,7 +3312,7 @@ float Unit::MeleeMissChanceCalc(const Unit *pVictim, WeaponAttackType attType) c bool isNormal = false; for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) { - if (m_currentSpells[i] && (GetSpellSchoolMask(m_currentSpells[i]->m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL)) + if (m_currentSpells[i] && (m_currentSpells[i]->m_spellInfo->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_NORMAL)) { isNormal = true; break; @@ -4052,8 +4052,8 @@ bool Unit::AddSpellAuraHolder(SpellAuraHolder *holder) SpellEntry const* aurSpellInfo = holder->GetSpellProto(); // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) - if (!isAlive() && !IsDeathPersistentSpell(aurSpellInfo) && - !IsDeathOnlySpell(aurSpellInfo) && + if (!isAlive() && !aurSpellInfo->IsDeathPersistentSpell() && + !aurSpellInfo->IsDeathOnlySpell() && (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading())) { delete holder; @@ -4111,7 +4111,7 @@ bool Unit::AddSpellAuraHolder(SpellAuraHolder *holder) } // Skip channeled spells (Arcane missile, ...) so two casters can channel at the same time - if (IsChanneledSpell(aurSpellInfo)) + if (aurSpellInfo->IsChanneledSpell()) continue; bool stop = false; @@ -4159,7 +4159,7 @@ bool Unit::AddSpellAuraHolder(SpellAuraHolder *holder) } // passive auras not stackable with other ranks - if (!IsPassiveSpellStackableWithRanks(aurSpellInfo) && !holder->IsPersistent()) + if (!aurSpellInfo->IsPassiveSpellStackableWithRanks() && !holder->IsPersistent()) { if (!RemoveNoStackAurasDueToAuraHolder(holder)) { @@ -4181,7 +4181,7 @@ bool Unit::AddSpellAuraHolder(SpellAuraHolder *holder) ObjectGuid itr_targetGuid = itr->second; if (itr_targetGuid != GetObjectGuid() && - IsSingleTargetSpells(itr_spellEntry, aurSpellInfo)) + Spells::IsSingleTargetSpells(itr_spellEntry, aurSpellInfo)) { scTargets.erase(itr); // remove for caster in any case @@ -4322,7 +4322,7 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder) // passive spell special case (only non stackable with ranks) if (spellProto->Attributes & (SPELL_ATTR_PASSIVE | 0x80)) { - if (IsPassiveSpellStackableWithRanks(spellProto)) + if (spellProto->IsPassiveSpellStackableWithRanks()) return true; } @@ -4356,9 +4356,9 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder) break; } - SpellSpecific spellId_spec = GetSpellSpecific(spellId); + SpellSpecific spellId_spec = Spells::GetSpellSpecific(spellId); - bool isAreaAura = IsSpellHaveEffect(spellProto, SPELL_EFFECT_APPLY_AREA_AURA_PARTY); + bool isAreaAura = spellProto->HasEffect(SPELL_EFFECT_APPLY_AREA_AURA_PARTY); SpellAuraHolderMap::iterator i, next; for (i = m_spellAuraHolders.begin(); i != m_spellAuraHolders.end(); i = next) { @@ -4392,13 +4392,13 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder) { // passive non-stackable spells not stackable only for same caster // -> Sauf si 2 AreaAuras - if (holder->GetCasterGuid() != i->second->GetCasterGuid() && !isAreaAura && !IsSpellHaveEffect(i_spellProto, SPELL_EFFECT_APPLY_AREA_AURA_PARTY)) + if (holder->GetCasterGuid() != i->second->GetCasterGuid() && !isAreaAura && !i_spellProto->HasEffect(SPELL_EFFECT_APPLY_AREA_AURA_PARTY)) continue; // passive non-stackable spells not stackable only with another rank of same spell if (sSpellMgr.IsRankSpellDueToSpell(spellProto, i_spellId)) { - if (CompareAuraRanks(spellId, i_spellId) < 0) // Le sort actuel est plus puissant. + if (Spells::CompareAuraRanks(spellId, i_spellId) < 0) // Le sort actuel est plus puissant. { DETAIL_LOG("[STACK] [%u/%u] Le sort actuel est plus puissant.", spellId, i_spellId); // On empeche la pose de l'aura. @@ -4442,15 +4442,15 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder) continue; } - if (IsSpellHaveAura(i_spellProto, SPELL_AURA_CHANNEL_DEATH_ITEM)) // Plusieurs demo par exemple peuvent mettre un siphon d'ame. + if (i_spellProto->HasAura(SPELL_AURA_CHANNEL_DEATH_ITEM)) // Plusieurs demo par exemple peuvent mettre un siphon d'ame. continue; - SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId); + SpellSpecific i_spellId_spec = Spells::GetSpellSpecific(i_spellId); // single allowed spell specific from same caster or from any caster at target - bool is_spellSpecPerTargetPerCaster = IsSingleFromSpellSpecificPerTargetPerCaster(spellId_spec, i_spellId_spec); + bool is_spellSpecPerTargetPerCaster = Spells::IsSingleFromSpellSpecificPerTargetPerCaster(spellId_spec, i_spellId_spec); - bool is_spellSpecPerTarget = IsSingleFromSpellSpecificPerTarget(spellId_spec, i_spellId_spec); + bool is_spellSpecPerTarget = Spells::IsSingleFromSpellSpecificPerTarget(spellId_spec, i_spellId_spec); // HoTs in 1.x must be per target also if (!is_spellSpecPerTarget && firstInChain && firstInChain == sSpellMgr.GetFirstSpellInChain(i_spellId)) @@ -4460,12 +4460,12 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder) { // cannot remove stronger snare / haste debuff if (spellId_spec == SPELL_SNARE || spellId_spec == SPELL_NEGATIVE_HASTE) - if (!CompareSpellSpecificAuras(spellProto, i_spellProto)) + if (!Spells::CompareSpellSpecificAuras(spellProto, i_spellProto)) return false; // cannot remove higher rank if (sSpellMgr.IsRankSpellDueToSpell(spellProto, i_spellId)) - if (CompareAuraRanks(spellId, i_spellId) < 0) + if (Spells::CompareAuraRanks(spellId, i_spellId) < 0) return false; // Its a parent aura (create this aura in ApplyModifier) @@ -4487,11 +4487,11 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder) // spell with spell specific that allow single ranks for spell from diff caster // same caster case processed or early or later - bool is_spellPerTarget = IsSingleFromSpellSpecificSpellRanksPerTarget(spellId_spec, i_spellId_spec); + bool is_spellPerTarget = Spells::IsSingleFromSpellSpecificSpellRanksPerTarget(spellId_spec, i_spellId_spec); if (is_spellPerTarget && holder->GetCasterGuid() != (*i).second->GetCasterGuid() && sSpellMgr.IsRankSpellDueToSpell(spellProto, i_spellId)) { // cannot remove higher rank - if (CompareAuraRanks(spellId, i_spellId) < 0) + if (Spells::CompareAuraRanks(spellId, i_spellId) < 0) { DETAIL_LOG("[STACK] [%u/%u] Rang plus haut.", spellId, i_spellId); return false; @@ -4524,7 +4524,7 @@ bool Unit::RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder) if (!is_spellSpecPerTargetPerCaster && !is_spellSpecPerTarget && sSpellMgr.IsNoStackSpellDueToSpell(spellId, i_spellId)) { // Prevent replacing higher ranks with lesser ranks - if (sSpellMgr.IsRankSpellDueToSpell(spellProto, i_spellId) && CompareAuraRanks(spellId, i_spellId) < 0) + if (sSpellMgr.IsRankSpellDueToSpell(spellProto, i_spellId) && Spells::CompareAuraRanks(spellId, i_spellId) < 0) { return false; } @@ -4668,7 +4668,7 @@ void Unit::RemoveAurasDueToSpellByCancel(uint32 spellId) void Unit::RemoveAurasWithDispelType(DispelType type, ObjectGuid casterGuid) { // Create dispel mask by dispel type - uint32 dispelMask = GetDispellMask(type); + uint32 dispelMask = Spells::GetDispellMask(type); // Dispel all existing auras vs current dispel type SpellAuraHolderMap& auras = GetSpellAuraHolderMap(); for (SpellAuraHolderMap::iterator itr = auras.begin(); itr != auras.end();) @@ -4884,7 +4884,7 @@ void Unit::RemoveSpellAuraHolder(SpellAuraHolder *holder, AuraRemoveMode mode) { // If single target, interrupt cast. If not, notify the spell caster so we // can stop processing this holder - if (!IsAreaOfEffectSpell(channeled->m_spellInfo) && mode != AURA_REMOVE_BY_CHANNEL && (mode != AURA_REMOVE_BY_EXPIRE || caster->IsControlledByPlayer())) + if (!channeled->m_spellInfo->IsAreaOfEffectSpell() && mode != AURA_REMOVE_BY_CHANNEL && (mode != AURA_REMOVE_BY_EXPIRE || caster->IsControlledByPlayer())) caster->InterruptSpell(CURRENT_CHANNELED_SPELL); else channeled->RemoveChanneledAuraHolder(holder, mode); @@ -6051,7 +6051,7 @@ void Unit::ModifyAuraState(AuraState flag, bool apply) { if (itr->second.state == PLAYERSPELL_REMOVED) continue; SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(itr->first); - if (!spellInfo || !IsPassiveSpell(spellInfo)) continue; + if (!spellInfo || !spellInfo->IsPassiveSpell()) continue; if (AuraState(spellInfo->CasterAuraState) == flag) CastSpell(this, itr->first, true, nullptr); } @@ -6527,12 +6527,12 @@ int32 Unit::SpellBonusWithCoeffs(SpellEntry const *spellProto, int32 total, int3 { float ap_bonus = damagetype == DOT ? bonus->ap_dot_bonus : bonus->ap_bonus; - total += int32(ap_bonus * (GetTotalAttackPowerValue(IsSpellRequiresRangedAP(spellProto) ? RANGED_ATTACK : BASE_ATTACK) + ap_benefit)); + total += int32(ap_bonus * (GetTotalAttackPowerValue(spellProto->IsSpellRequiresRangedAP() ? RANGED_ATTACK : BASE_ATTACK) + ap_benefit)); } } // Calculate default coefficient else if (benefit) - coeff = CalculateDefaultCoefficient(spellProto, damagetype); + coeff = spellProto->CalculateDefaultCoefficient(damagetype); if (benefit) { @@ -6540,7 +6540,7 @@ int32 Unit::SpellBonusWithCoeffs(SpellEntry const *spellProto, int32 total, int3 float LvlPenalty = CalculateLevelPenalty(spellProto); // Calculate custom coefficient - coeff = CalculateCustomCoefficient(spellProto, pCaster, damagetype, coeff, spell, donePart); + coeff = spellProto->CalculateCustomCoefficient(pCaster, damagetype, coeff, spell, donePart); // Spellmod SpellDamage if (Player* modOwner = GetSpellModOwner()) @@ -6607,7 +6607,7 @@ uint32 Unit::SpellDamageBonusDone(Unit *pVictim, SpellEntry const *spellProto, u AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) { - if (((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) && + if (((*i)->GetModifier()->m_miscvalue & spellProto->GetSpellSchoolMask()) && (*i)->GetSpellProto()->EquippedItemClass == -1 && spellProto->EquippedItemClass == -1 && // -1 == any item class (not wand then) @@ -6669,7 +6669,7 @@ uint32 Unit::SpellDamageBonusDone(Unit *pVictim, SpellEntry const *spellProto, u } // Done fixed damage bonus auras - int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(GetSpellSchoolMask(spellProto)); + int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSpellSchoolMask()); // Add flat bonus from spell damage versus DoneAdvertisedBenefit += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask); @@ -6700,7 +6700,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit *pCaster, SpellEntry const *spellProto, if (!spellProto || !pCaster || damagetype == DIRECT_DAMAGE) return pdamage; - uint32 schoolMask = spell ? spell->m_spellSchoolMask : GetSpellSchoolMask(spellProto); + uint32 schoolMask = spell ? spell->m_spellSchoolMask : spellProto->GetSpellSchoolMask(); // Taken total percent damage auras float TakenTotalMod = 1.0f; @@ -6710,7 +6710,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit *pCaster, SpellEntry const *spellProto, TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, schoolMask); // Taken fixed damage bonus auras - int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(GetSpellSchoolMask(spellProto)); + int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSpellSchoolMask()); // apply benefit affected by spell power implicit coeffs and spell level penalties TakenTotal = SpellBonusWithCoeffs(spellProto, TakenTotal, TakenAdvertisedBenefit, 0, damagetype, false, pCaster, spell); @@ -6804,7 +6804,7 @@ bool Unit::IsSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask); } // taken - if (!IsPositiveSpell(spellProto->Id)) + if (!spellProto->IsPositiveSpell()) { // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE crit_chance += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask); @@ -6980,7 +6980,7 @@ uint32 Unit::SpellHealingBonusDone(Unit *pVictim, SpellEntry const *spellProto, } // Done fixed damage bonus auras - int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(GetSpellSchoolMask(spellProto)); + int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSpellSchoolMask()); // apply ap bonus and benefit affected by spell power implicit coeffs and spell level penalties DoneTotal = SpellBonusWithCoeffs(spellProto, DoneTotal, DoneAdvertisedBenefit, 0, damagetype, true, this, spell); @@ -7024,7 +7024,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit *pCaster, SpellEntry const *spellProto, int32 TakenTotal = 0; // Taken fixed damage bonus auras - int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(GetSpellSchoolMask(spellProto)); + int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(spellProto->GetSpellSchoolMask()); // Blessing of Light dummy effects healing taken from Holy Light and Flash of Light if (spellProto->IsFitToFamily()) @@ -7141,8 +7141,8 @@ bool Unit::IsImmuneToSpell(SpellEntry const *spellInfo, bool /*castOnSelf*/) { SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr) - if (!(IsPositiveSpell(itr->spellId) && IsPositiveSpell(spellInfo->Id)) && - (itr->type & GetSpellSchoolMask(spellInfo))) + if (!(Spells::IsPositiveSpell(itr->spellId) && spellInfo->IsPositiveSpell()) && + (itr->type & spellInfo->GetSpellSchoolMask())) return true; } @@ -7213,10 +7213,10 @@ uint32 Unit::MeleeDamageBonusDone(Unit* pVictim, uint32 pdamage, WeaponAttackTyp return pdamage; // differentiate for weapon damage based spells - bool isWeaponDamageBasedSpell = !(spellProto && (damagetype == DOT || IsSpellHaveEffect(spellProto, SPELL_EFFECT_SCHOOL_DAMAGE))); + bool isWeaponDamageBasedSpell = !(spellProto && (damagetype == DOT || spellProto->HasEffect(SPELL_EFFECT_SCHOOL_DAMAGE))); Item* pWeapon = GetTypeId() == TYPEID_PLAYER ? ((Player*)this)->GetWeaponForAttack(attType, true, false) : NULL; uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); - uint32 schoolMask = spellProto ? GetSpellSchoolMask(spellProto) : GetMeleeDamageSchoolMask(); + uint32 schoolMask = spellProto ? spellProto->GetSpellSchoolMask() : GetMeleeDamageSchoolMask(); // FLAT damage bonus auras // ======================= @@ -7315,7 +7315,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* pVictim, uint32 pdamage, WeaponAttackTyp // weapon damage based spells else if (APbonus || DoneFlat) { - bool normalized = spellProto ? IsSpellHaveEffect(spellProto, SPELL_EFFECT_NORMALIZED_WEAPON_DMG) : false; + bool normalized = spellProto ? spellProto->HasEffect(SPELL_EFFECT_NORMALIZED_WEAPON_DMG) : false; DoneTotal += int32(APbonus / 14.0f * GetAPMultiplier(attType, normalized)); // for weapon damage based spells we still have to apply damage done percent mods @@ -7376,8 +7376,8 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* pCaster, uint32 pdamage, WeaponAttackTy return pdamage; // differentiate for weapon damage based spells - bool isWeaponDamageBasedSpell = !(spellProto && (damagetype == DOT || IsSpellHaveEffect(spellProto, SPELL_EFFECT_SCHOOL_DAMAGE))); - uint32 schoolMask = spellProto ? GetSpellSchoolMask(spellProto) : uint32(pCaster->GetMeleeDamageSchoolMask()); + bool isWeaponDamageBasedSpell = !(spellProto && (damagetype == DOT || spellProto->HasEffect(SPELL_EFFECT_SCHOOL_DAMAGE))); + uint32 schoolMask = spellProto ? spellProto->GetSpellSchoolMask() : uint32(pCaster->GetMeleeDamageSchoolMask()); // FLAT damage bonus auras // ======================= @@ -7553,7 +7553,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy) for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) if (Spell* spell = GetCurrentSpell(CurrentSpellTypes(i))) if (spell->getState() == SPELL_STATE_PREPARING && spell->GetCastedTime()) - if (IsNonCombatSpell(spell->m_spellInfo)) + if (spell->m_spellInfo->IsNonCombatSpell()) InterruptSpell(CurrentSpellTypes(i), false); if (creatureNotInCombat) @@ -8755,9 +8755,9 @@ void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, U // Some diminishings applies to mobs too (for example, Stun) // Nostalrius: fix DR sur les pets. bool pvp = (IsLikePlayer() && caster->IsLikePlayer()); - if ((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && pvp) || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) + if ((Spells::GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && pvp) || Spells::GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) { - mod = GetDiminishingRate(Level); + mod = Spells::GetDiminishingRate(Level); } duration = int32(duration * mod); @@ -9422,7 +9422,7 @@ void CharmInfo::InitPossessCreateSpells() for (uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x) { - if (IsPassiveSpell(pCreature->m_spells[x])) + if (Spells::IsPassiveSpell(pCreature->m_spells[x])) m_unit->CastSpell(m_unit, pCreature->m_spells[x], true); else if (SpellEntry const* pSpellEntry = sSpellMgr.GetSpellEntry(pCreature->m_spells[x])) @@ -9430,7 +9430,7 @@ void CharmInfo::InitPossessCreateSpells() // - Charm spells on charmed creatures are no longer available to the // players that charm them. #if SUPPORTED_CLIENT_BUILD > CLIENT_BUILD_1_9_4 - if (!IsCharmSpell(pSpellEntry)) + if (!pSpellEntry->IsCharmSpell()) #endif AddSpellToActionBar(pCreature->m_spells[x], ACT_PASSIVE); @@ -9458,7 +9458,7 @@ void CharmInfo::InitCharmCreateSpells() continue; } - if (IsPassiveSpell(spellId)) + if (Spells::IsPassiveSpell(spellId)) { m_unit->CastSpell(m_unit, spellId, true); m_charmspells[x].SetActionAndType(spellId, ACT_PASSIVE); @@ -9478,7 +9478,7 @@ void CharmInfo::InitCharmCreateSpells() // - Charm spells on charmed creatures are no longer available to the // players that charm them. #if SUPPORTED_CLIENT_BUILD > CLIENT_BUILD_1_9_4 - else if (IsCharmSpell(pSpellEntry)) + else if (pSpellEntry->IsCharmSpell()) continue; #endif @@ -9488,7 +9488,7 @@ void CharmInfo::InitCharmCreateSpells() onlyselfcast = false; } - if (onlyselfcast || !IsPositiveSpell(spellId)) // only self cast and spells versus enemies are autocastable + if (onlyselfcast || !Spells::IsPositiveSpell(spellId)) // only self cast and spells versus enemies are autocastable newstate = ACT_DISABLED; else newstate = ACT_PASSIVE; @@ -9548,7 +9548,7 @@ bool CharmInfo::RemoveSpellFromActionBar(uint32 spell_id) void CharmInfo::ToggleCreatureAutocast(uint32 spellid, bool apply) { - if (IsPassiveSpell(spellid)) + if (Spells::IsPassiveSpell(spellid)) return; for (uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x) @@ -10153,7 +10153,7 @@ void Unit::SetStandState(uint8 state) bool Unit::IsPolymorphed() const { - return GetSpellSpecific(getTransForm()) == SPELL_MAGE_POLYMORPH; + return Spells::GetSpellSpecific(getTransForm()) == SPELL_MAGE_POLYMORPH; } bool Unit::isAttackReady(WeaponAttackType type) const @@ -11379,7 +11379,7 @@ void Unit::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) bool Unit::IsSpellProhibited(SpellEntry const* pSpell) { - uint32 spellSchoolMask = GetSpellSchoolMask(pSpell); + uint32 spellSchoolMask = pSpell->GetSpellSchoolMask(); for (ProhibitSpellList::const_iterator it = m_prohibitSpell.begin(); it != m_prohibitSpell.end(); ++it) { if (it->SchoolMask & spellSchoolMask) @@ -11407,8 +11407,8 @@ SpellAuraHolder* Unit::AddAura(uint32 spellId, uint32 addAuraFlags, Unit* pCaste if (!spellInfo) return nullptr; - if (!IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && - !IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (!spellInfo->IsSpellAppliesAura((1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && + !spellInfo->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { sLog.outError("Cannot apply aura with Id %u : spell does not have auras!", spellInfo->Id); return nullptr; @@ -11432,7 +11432,7 @@ SpellAuraHolder* Unit::AddAura(uint32 spellId, uint32 addAuraFlags, Unit* pCaste if (eff >= TOTAL_SPELL_EFFECTS) continue; - if (IsAreaAuraEffect(eff) || + if (Spells::IsAreaAuraEffect(eff) || eff == SPELL_EFFECT_APPLY_AURA || eff == SPELL_EFFECT_PERSISTENT_AREA_AURA) { diff --git a/src/game/ScriptMgr.cpp b/src/game/ScriptMgr.cpp index e036315a0..69e7b1755 100644 --- a/src/game/ScriptMgr.cpp +++ b/src/game/ScriptMgr.cpp @@ -1160,8 +1160,8 @@ void ScriptMgr::LoadScripts(ScriptMapMap& scripts, const char* tablename) { if (auto pSpellEntry = sSpellMgr.GetSpellEntry(tmp.addAura.spellId)) { - if (!IsSpellAppliesAura(pSpellEntry, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && - !IsSpellHaveEffect(pSpellEntry, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (!pSpellEntry->IsSpellAppliesAura((1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) && + !pSpellEntry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { sLog.outErrorDb("Table `%s` has a spell that does not apply any auras (id: %u) in SCRIPT_COMMAND_ADD_AURA for script id %u", tablename, tmp.addAura.spellId, tmp.id); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index ffe9ea05a..6f6992f3a 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -917,7 +917,7 @@ enum WeaponAttackType // The different wea #define MAX_ATTACK 3 -enum Targets +enum SpellTarget { TARGET_NONE = 0, TARGET_SELF = 1, diff --git a/src/game/Spells/Spell.cpp b/src/game/Spells/Spell.cpp index 74bd3c0ed..d0b80158d 100644 --- a/src/game/Spells/Spell.cpp +++ b/src/game/Spells/Spell.cpp @@ -52,6 +52,8 @@ #include "GameObjectAI.h" #include "ZoneScript.h" +using namespace Spells; + #define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS) extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; @@ -312,9 +314,9 @@ Spell::Spell(Unit* caster, SpellEntry const *info, bool triggered, ObjectGuid or m_absorbed = 0; // Get data for type of attack - m_attackType = GetWeaponAttackType(m_spellInfo); + m_attackType = m_spellInfo->GetWeaponAttackType(); - m_spellSchoolMask = GetSpellSchoolMask(info); // Can be override for some spell (wand shoot for example) + m_spellSchoolMask = info->GetSpellSchoolMask(); // Can be override for some spell (wand shoot for example) // wand case if (m_attackType == RANGED_ATTACK) @@ -350,19 +352,19 @@ Spell::Spell(Unit* caster, SpellEntry const *info, bool triggered, ObjectGuid or m_triggeredByAuraBasePoints = 0; //Auto Shot & Shoot - m_autoRepeat = IsAutoRepeatRangedSpell(m_spellInfo); + m_autoRepeat = m_spellInfo->IsAutoRepeatRangedSpell(); m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before. m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before. m_timer = 0; // will set to cast time in prepare m_duration = 0; - m_channeled = IsChanneledSpell(info); + m_channeled = info->IsChanneledSpell(); m_needAliveTargetMask = 0; // determine reflection - m_canReflect = victim ? IsReflectableSpell(m_spellInfo, caster, victim) : IsReflectableSpell(m_spellInfo); + m_canReflect = victim ? m_spellInfo->IsReflectableSpell(caster, victim) : m_spellInfo->IsReflectableSpell(); m_isClientStarted = false; @@ -783,14 +785,14 @@ void Spell::prepareDataForTriggerSystem() m_procVictim = PROC_FLAG_TAKEN_RANGED_SPELL_HIT; } - if (IsAreaOfEffectSpell(m_spellInfo)) + if (m_spellInfo->IsAreaOfEffectSpell()) m_procAttacker |= PROC_FLAG_SUCCESSFUL_AOE; } break; default: { - bool aoe = IsAreaOfEffectSpell(m_spellInfo); - bool positive = IsPositiveSpell(m_spellInfo); + bool aoe = m_spellInfo->IsAreaOfEffectSpell(); + bool positive = m_spellInfo->IsPositiveSpell(); // Some spells should be categorized as AoE // Hellfire regularly triggers an AoE spell. if (m_spellInfo->IsFitToFamily() && m_spellInfo->SpellIconID == 937) @@ -801,7 +803,7 @@ void Spell::prepareDataForTriggerSystem() // with SPELL_EFFECT_DISPEL are negative, such as Purge. if (positive) { - if (IsHealSpell(m_spellInfo)) + if (m_spellInfo->IsHealSpell()) { m_procAttacker = PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL; m_procVictim = PROC_FLAG_TAKEN_POSITIVE_SPELL; @@ -818,7 +820,7 @@ void Spell::prepareDataForTriggerSystem() if (aoe) m_procAttacker |= PROC_FLAG_SUCCESSFUL_AOE; - if (IsSpellAppliesPeriodicAura(m_spellInfo)) + if (m_spellInfo->IsSpellAppliesPeriodicAura()) { m_procAttacker |= PROC_FLAG_SUCCESSFUL_PERIODIC_SPELL_HIT; m_procVictim |= PROC_FLAG_TAKEN_PERIODIC_SPELL_HIT; @@ -854,7 +856,7 @@ void Spell::prepareDataForTriggerSystem() if (aoe) m_procAttacker |= PROC_FLAG_SUCCESSFUL_AOE; - if (IsSpellAppliesPeriodicAura(m_spellInfo)) + if (m_spellInfo->IsSpellAppliesPeriodicAura()) { m_procAttacker |= PROC_FLAG_SUCCESSFUL_PERIODIC_SPELL_HIT; m_procVictim |= PROC_FLAG_TAKEN_PERIODIC_SPELL_HIT; @@ -876,7 +878,7 @@ void Spell::prepareDataForTriggerSystem() m_negativeEffectMask = 0x0; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { - if (!IsPositiveEffect(m_spellInfo, SpellEffectIndex(i))) + if (!m_spellInfo->IsPositiveEffect(SpellEffectIndex(i))) m_negativeEffectMask |= (1 << i); // Self damage is a positive effect but should still trigger negative proc flags @@ -1005,7 +1007,7 @@ void Spell::CheckAtDelay(TargetInfo* pInf) } } if (pTarget != m_caster && - (pTarget->IsImmuneToDamage(GetSpellSchoolMask(m_spellInfo), m_spellInfo) || pTarget->IsImmuneToSpell(m_spellInfo, pTarget == m_caster))) + (pTarget->IsImmuneToDamage(m_spellInfo->GetSpellSchoolMask(), m_spellInfo) || pTarget->IsImmuneToSpell(m_spellInfo, pTarget == m_caster))) pInf->missCondition = SPELL_MISS_IMMUNE; if (pTarget->GetTypeId() == TYPEID_UNIT && ((Creature*)pTarget)->IsInEvadeMode()) @@ -1113,7 +1115,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (!unit) return; - if (getState() == SPELL_STATE_DELAYED && (WorldTimer::getMSTime() - target->timeDelay) <= unit->m_lastSanctuaryTime && !IsPositiveSpell(m_spellInfo)) + if (getState() == SPELL_STATE_DELAYED && (WorldTimer::getMSTime() - target->timeDelay) <= unit->m_lastSanctuaryTime && !m_spellInfo->IsPositiveSpell()) return; // Get original caster (if exist) and calculate damage/healing from him data @@ -1178,7 +1180,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) { // mark effects that were already handled in Spell::HandleDelayedSpellLaunch on spell launch as processed for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) - if (IsEffectHandledOnDelayedSpellLaunch(m_spellInfo, SpellEffectIndex(i))) + if (m_spellInfo->IsEffectHandledOnDelayedSpellLaunch(SpellEffectIndex(i))) mask &= ~(1 << i); // maybe used in effects that are handled on hit @@ -1202,7 +1204,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) { if (real_caster && real_caster != unit) { - if (!IsPositiveSpell(m_spellInfo) && (m_caster->isVisibleForOrDetect(unit, unit, false) || m_spellInfo->HasAttribute(SPELL_ATTR_EX_IS_PICKPOCKET))) + if (!m_spellInfo->IsPositiveSpell() && (m_caster->isVisibleForOrDetect(unit, unit, false) || m_spellInfo->HasAttribute(SPELL_ATTR_EX_IS_PICKPOCKET))) { bool combat = (m_spellInfo->Id != 3600) && !m_spellInfo->HasAttribute(SPELL_ATTR_EX3_NO_INITIAL_AGGRO); @@ -1215,7 +1217,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (combat) { - if (!IsSpellHaveAura(m_spellInfo, SPELL_AURA_MOD_POSSESS)) + if (!m_spellInfo->HasAura(SPELL_AURA_MOD_POSSESS)) { if (!unit->isInCombat()) unit->AttackedBy(real_caster); @@ -1446,7 +1448,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) // m_spellAuraHolder is null for non-stacking periodic effects that are already // on the target - they simply refresh. However, they should still proc on // cast! - if (IsSpellAppliesAura(m_spellInfo, target->effectMask)) + if (m_spellInfo->IsSpellAppliesAura(target->effectMask)) { for (int i = 0; i < MAX_EFFECT_INDEX && !foundDamageOrHealAura; ++i) { @@ -1565,7 +1567,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask) // Recheck immune (only for delayed spells) if (m_caster != unit && m_spellInfo->speed && ( - unit->IsImmuneToDamage(GetSpellSchoolMask(m_spellInfo), m_spellInfo) || + unit->IsImmuneToDamage(m_spellInfo->GetSpellSchoolMask(), m_spellInfo) || unit->IsImmuneToSpell(m_spellInfo, unit == realCaster))) { if (realCaster) @@ -1608,7 +1610,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask) } // can cause back attack (if detected), stealth removed at Spell::cast if spell break it - if ((!IsPositiveSpell(m_spellInfo) || IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_DISPEL)) && + if ((!m_spellInfo->IsPositiveSpell() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && !m_spellInfo->IsFitToFamily() && // Sap handled somewhere else. Without this, sap will remove stealth if the rogue is visible. (m_spellInfo->Id == 6358 || // Exception to fix succubus seduction. m_caster->isVisibleForOrDetect(unit, unit, false))) @@ -1626,7 +1628,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask) m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); m_caster->RemoveNonPassiveSpellsCausingAura(SPELL_AURA_MOD_INVISIBILITY); - if (!IsSpellHaveAura(m_spellInfo, SPELL_AURA_MOD_POSSESS)) + if (!m_spellInfo->HasAura(SPELL_AURA_MOD_POSSESS)) { if (!unit->isInCombat()) unit->AttackedBy(realCaster); @@ -1647,7 +1649,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask) else { // for delayed spells ignore negative spells (after duel end) for friendly targets - if (m_delayed && !IsPositiveSpell(m_spellInfo)) + if (m_delayed && !m_spellInfo->IsPositiveSpell()) { realCaster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); ResetEffectDamageAndHeal(); @@ -1685,7 +1687,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, uint32 effectMask) // Apply additional spell effects to target CastPreCastSpells(unit); - if (IsSpellAppliesAura(m_spellInfo, effectMask)) + if (m_spellInfo->IsSpellAppliesAura(effectMask)) { m_spellAuraHolder = CreateSpellAuraHolder(m_spellInfo, unit, realCaster, m_CastItem); m_spellAuraHolder->SetTriggered(IsTriggered()); @@ -1837,7 +1839,7 @@ void Spell::HandleDelayedSpellLaunch(TargetInfo *target) { for (int32 effectNumber = 0; effectNumber < MAX_EFFECT_INDEX; ++effectNumber) { - if (mask & (1 << effectNumber) && IsEffectHandledOnDelayedSpellLaunch(m_spellInfo, SpellEffectIndex(effectNumber))) + if (mask & (1 << effectNumber) && m_spellInfo->IsEffectHandledOnDelayedSpellLaunch(SpellEffectIndex(effectNumber))) { HandleEffects(unit, nullptr, nullptr, SpellEffectIndex(effectNumber), m_damageMultipliers[effectNumber]); if (m_applyMultiplierMask & (1 << effectNumber)) @@ -1897,7 +1899,7 @@ bool Spell::HasValidUnitPresentInTargetList() // Elle ne s'arrete pas, sauf s'il meurt biensur. if (!needTargetsMask) { - if (m_caster->isAlive() == IsDeathOnlySpell(m_spellInfo)) + if (m_caster->isAlive() == m_spellInfo->IsDeathOnlySpell()) return false; return true; } @@ -1912,7 +1914,7 @@ bool Spell::HasValidUnitPresentInTargetList() Unit *unit = m_caster->GetObjectGuid() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); // either unit is alive and normal spell, or unit dead and deathonly-spell - if (unit && (unit->isAlive() != IsDeathOnlySpell(m_spellInfo))) + if (unit && (unit->isAlive() != m_spellInfo->IsDeathOnlySpell())) foundMask |= ihit->effectMask; } @@ -2371,7 +2373,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE; // Select friendly targets for positive effect - if (IsPositiveEffect(m_spellInfo, effIndex)) + if (m_spellInfo->IsPositiveEffect(effIndex)) targetB = SPELL_TARGETS_FRIENDLY; UnitList tempTargetUnitMap; @@ -3342,7 +3344,7 @@ SpellCastResult Spell::prepare(Aura* triggeredByAura, uint32 chance) // Roll chance to cast from script (must be after cast checks, this is why its here) if (chance) { - if (chance <= urand(0, 100)) + if (roll_chance_u(chance)) { finish(false); return SPELL_FAILED_TRY_AGAIN; @@ -3353,13 +3355,13 @@ SpellCastResult Spell::prepare(Aura* triggeredByAura, uint32 chance) prepareDataForTriggerSystem(); // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail) - m_casttime = GetSpellCastTime(m_spellInfo, this); + m_casttime = m_spellInfo->GetCastTime(this); if (Player* pPlayerCaster = m_caster->ToPlayer()) if (pPlayerCaster->HasOption(PLAYER_CHEAT_NO_CAST_TIME)) m_casttime = 0; - m_duration = CalculateSpellDuration(m_spellInfo, m_caster); + m_duration = m_spellInfo->CalculateDuration(m_caster); // set timer base at cast time ReSetTimer(); @@ -3416,7 +3418,7 @@ SpellCastResult Spell::prepare(Aura* triggeredByAura, uint32 chance) // causing owner to die and pet gets despawned, leading to // deletion of auras on pet and crash when stack unwinds. // An example of this is spell 3584 Volatile Infection. - !(triggeredByAura && IsDamageSpell(m_spellInfo) && m_caster->IsCreature())) + !(triggeredByAura && m_spellInfo->IsDamageSpell() && m_caster->IsCreature())) cast(true); // else triggered with cast time will execute at next tick or later @@ -3731,7 +3733,7 @@ void Spell::cast(bool skipCheck) } // Shaman totems. Trigger spell cast procs, but not others - if (IsTotemSummonSpell(m_spellInfo) && m_canTrigger) + if (m_spellInfo->IsTotemSummonSpell() && m_canTrigger) { uint32 procAttackerFlags = PROC_FLAG_SUCCESSFUL_SPELL_CAST | PROC_FLAG_SUCCESSFUL_MANA_SPELL_CAST; m_caster->ProcDamageAndSpell(m_caster, procAttackerFlags, PROC_FLAG_NONE, PROC_EX_NORMAL_HIT, 1, m_attackType, m_spellInfo, this); @@ -3784,7 +3786,7 @@ void Spell::cast(bool skipCheck) void Spell::handle_immediate() { bool sendGoBefore = true; - if (IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_INSTAKILL) || IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_SPAWN)) + if (m_spellInfo->HasEffect(SPELL_EFFECT_INSTAKILL) || m_spellInfo->HasEffect(SPELL_EFFECT_SPAWN)) sendGoBefore = false; if (sendGoBefore) SendSpellGo(); @@ -3814,7 +3816,7 @@ void Spell::handle_immediate() // a channeled spell could be interrupted already because the aura on target // was diminished to duration=0 see Spell::DoSpellHitOnUnit - if (IsChanneledSpell(m_spellInfo) && m_spellState != SPELL_STATE_CASTING) + if (m_spellInfo->IsChanneledSpell() && m_spellState != SPELL_STATE_CASTING) return; } @@ -4286,11 +4288,11 @@ void Spell::finish(bool ok) m_caster->resetAttackTimer(RANGED_ATTACK);*/ // Clear combo at finish state - if (m_caster->GetTypeId() == TYPEID_PLAYER && NeedsComboPoints(m_spellInfo)) + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->NeedsComboPoints()) { // Not drop combopoints if negative spell and if any miss on enemy exist bool needDrop = true; - if (!IsPositiveSpell(m_spellInfo)) + if (!m_spellInfo->IsPositiveSpell()) { for (TargetList::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { @@ -4374,7 +4376,7 @@ void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, SpellCas if (result != SPELL_CAST_OK) { data << uint8(2); // status = fail - data << uint8(IsPassiveSpell(spellInfo) ? SPELL_FAILED_DONT_REPORT : result); // problem + data << uint8(spellInfo->IsPassiveSpell() ? SPELL_FAILED_DONT_REPORT : result); // problem switch (result) { case SPELL_FAILED_REQUIRES_SPELL_FOCUS: @@ -4749,7 +4751,7 @@ void Spell::SendChannelUpdate(uint32 time) { // Reset farsight for some possessing auras of possessed summoned (as they might work with different aura types) if (m_spellInfo->Attributes & SPELL_ATTR_EX_FARSIGHT && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->GetCharmGuid() - && !IsSpellHaveAura(m_spellInfo, SPELL_AURA_MOD_POSSESS) && !IsSpellHaveAura(m_spellInfo, SPELL_AURA_MOD_POSSESS_PET)) + && !m_spellInfo->HasAura(SPELL_AURA_MOD_POSSESS) && !m_spellInfo->HasAura(SPELL_AURA_MOD_POSSESS_PET)) { Player* player = (Player*)m_caster; // These Auras are applied to self, so get the possessed first @@ -5108,7 +5110,7 @@ void Spell::HandleThreatSpells() float threat = threatEntry->threat; if (threatEntry->ap_bonus != 0.0f) - threat += threatEntry->ap_bonus * m_caster->GetTotalAttackPowerValue(GetWeaponAttackType(m_spellInfo)); + threat += threatEntry->ap_bonus * m_caster->GetTotalAttackPowerValue(m_spellInfo->GetWeaponAttackType()); bool positive = true; uint8 effectMask = 0; @@ -5146,7 +5148,7 @@ void Spell::HandleThreatSpells() if (!target->CanHaveThreatList()) continue; - target->AddThreat(m_caster, threat, false, GetSpellSchoolMask(m_spellInfo), m_spellInfo); + target->AddThreat(m_caster, threat, false, m_spellInfo->GetSpellSchoolMask(), m_spellInfo); } } @@ -5341,7 +5343,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (strict) { - if (m_caster->isInCombat() && IsNonCombatSpell(m_spellInfo)) + if (m_caster->isInCombat() && m_spellInfo->IsNonCombatSpell()) return SPELL_FAILED_AFFECTING_COMBAT; // only check at first call, Stealth auras are already removed at second call @@ -5349,7 +5351,7 @@ SpellCastResult Spell::CheckCast(bool strict) //if (strict) //{ // Cannot be used in this stance/form - SpellCastResult shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->GetShapeshiftForm()); + SpellCastResult shapeError = m_spellInfo->GetErrorAtShapeshiftedCast(m_caster->GetShapeshiftForm()); if (shapeError != SPELL_CAST_OK) return shapeError; @@ -5386,7 +5388,7 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_MOVING; } - if (!m_IsTriggeredSpell && NeedsComboPoints(m_spellInfo) && + if (!m_IsTriggeredSpell && m_spellInfo->NeedsComboPoints() && (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetObjectGuid() != ((Player*)m_caster)->GetComboTargetGuid())) // warrior not have real combo-points at client side but use this way for mark allow Overpower use return m_caster->getClass() == CLASS_WARRIOR ? SPELL_FAILED_BAD_TARGETS : SPELL_FAILED_NO_COMBO_POINTS; @@ -5427,7 +5429,7 @@ SpellCastResult Spell::CheckCast(bool strict) m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST || m_spellInfo->SpellFamilyName == SPELLFAMILY_SHAMAN || m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN) && - (IsHealSpell(m_spellInfo) || + (m_spellInfo->IsHealSpell() || m_spellInfo->IsDispel() || // don't really care if the target is non-friendly, there's nothing to purge on Loatheb m_spellInfo->IsFitToFamily() || // prevent holy nova cast (casted spell is damage part, heal is triggered) m_spellInfo->IsFitToFamily())) // prevent PW:Shield cast @@ -5442,7 +5444,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (Unit *target = m_targets.getUnitTarget()) { // Nostalrius - Un sort plus puissant est deja actif - if (IsSpellAppliesAura(m_spellInfo) && !IsAreaOfEffectSpell(m_spellInfo) && IsPositiveSpell(m_spellInfo) && target->HasMorePowerfullSpellActive(m_spellInfo)) + if (m_spellInfo->IsSpellAppliesAura() && !m_spellInfo->IsAreaOfEffectSpell() && m_spellInfo->IsPositiveSpell() && target->HasMorePowerfullSpellActive(m_spellInfo)) return SPELL_FAILED_AURA_BOUNCED; #if SUPPORTED_CLIENT_BUILD > CLIENT_BUILD_1_10_2 @@ -5453,7 +5455,7 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_TARGET_AURASTATE; } #endif - if (!m_IsTriggeredSpell && IsDeathOnlySpell(m_spellInfo) && target->isAlive()) + if (!m_IsTriggeredSpell && m_spellInfo->IsDeathOnlySpell() && target->isAlive()) return SPELL_FAILED_TARGET_NOT_DEAD; // Check spell min target level @@ -5471,7 +5473,7 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_TARGET_IN_COMBAT; #endif - bool non_caster_target = target != m_caster && !IsSpellWithCasterSourceTargetsOnly(m_spellInfo); + bool non_caster_target = target != m_caster && !m_spellInfo->IsSpellWithCasterSourceTargetsOnly(); if (non_caster_target) { @@ -5497,11 +5499,11 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_LOWLEVEL; } - if (strict && m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_TARGET_ONLY_PLAYER && target->GetTypeId() != TYPEID_PLAYER && !IsAreaOfEffectSpell(m_spellInfo)) + if (strict && m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_TARGET_ONLY_PLAYER && target->GetTypeId() != TYPEID_PLAYER && !m_spellInfo->IsAreaOfEffectSpell()) return SPELL_FAILED_BAD_TARGETS; } // Can't help a friend in duel | sorry, not enough time to figure out why this is necessary - if (IsPositiveSpell(m_spellInfo) && m_spellInfo->Id != 28697) + if (m_spellInfo->IsPositiveSpell() && m_spellInfo->Id != 28697) { Player* casterOwner = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself(); Player* targetOwner = target->GetCharmerOrOwnerPlayerOrPlayerItself(); @@ -5616,10 +5618,10 @@ SpellCastResult Spell::CheckCast(bool strict) // TODO: this check can be applied and for player to prevent cheating when IsPositiveSpell will return always correct result. // check target for pet/charmed casts (not self targeted), self targeted cast used for area effects and etc // Nostalrius : pas de status positif / negatif pour les sorts de dispel (marche en offensif comme defensif) - if (!explicit_target_mode && m_caster->GetTypeId() == TYPEID_UNIT && m_caster->GetCharmerOrOwnerGuid() && !IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_DISPEL)) + if (!explicit_target_mode && m_caster->GetTypeId() == TYPEID_UNIT && m_caster->GetCharmerOrOwnerGuid() && !m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) { // check correctness positive/negative cast target (pet cast real check and cheating check) - if (IsPositiveSpell(m_spellInfo)) + if (m_spellInfo->IsPositiveSpell()) { if (!target_hostile_checked) target_hostile = m_caster->IsHostileTo(target); @@ -5635,12 +5637,12 @@ SpellCastResult Spell::CheckCast(bool strict) } } - if (IsPositiveSpell(m_spellInfo->Id, m_caster, target)) + if (m_spellInfo->IsPositiveSpell(m_caster, target)) if (target->IsImmuneToSpell(m_spellInfo, target == m_caster)) return SPELL_FAILED_TARGET_AURASTATE; //Must be behind the target. - if (IsFromBehindOnlySpell(m_spellInfo) && target->HasInArc(M_PI_F, m_caster)) + if (m_spellInfo->IsFromBehindOnlySpell() && target->HasInArc(M_PI_F, m_caster)) { SendInterrupted(2); return SPELL_FAILED_NOT_BEHIND; @@ -5692,7 +5694,7 @@ SpellCastResult Spell::CheckCast(bool strict) // Except divine shields, pvp trinkets for example // Stoneform is explicitly excluded, it should be allowed to cast always // TODO: This condition allows an antifear item to be used while stuned for example. - if (!m_IsTriggeredSpell && !IsSpellAppliesAura(m_spellInfo, SPELL_AURA_SCHOOL_IMMUNITY) && !IsSpellAppliesAura(m_spellInfo, SPELL_AURA_MECHANIC_IMMUNITY) && + if (!m_IsTriggeredSpell && !m_spellInfo->HasAura(SPELL_AURA_SCHOOL_IMMUNITY) && !m_spellInfo->HasAura(SPELL_AURA_MECHANIC_IMMUNITY) && m_spellInfo->Id != 20594 && // Stoneform m_caster->hasUnitState(UNIT_STAT_ISOLATED | UNIT_STAT_STUNNED | UNIT_STAT_PENDING_STUNNED | UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING)) return SPELL_FAILED_DONT_REPORT; @@ -5704,7 +5706,7 @@ SpellCastResult Spell::CheckCast(bool strict) // not let players cast spells at mount (and let do it to creatures) if (m_caster->IsMounted() && m_caster->GetTypeId() == TYPEID_PLAYER && !m_IsTriggeredSpell && - !IsPassiveSpell(m_spellInfo) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED)) + !m_spellInfo->IsPassiveSpell() && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED)) { if (m_caster->IsTaxiFlying()) return SPELL_FAILED_NOT_ON_TAXI; @@ -5718,7 +5720,7 @@ SpellCastResult Spell::CheckCast(bool strict) } // always (except passive spells) check items (focus object can be required for any type casts) - if (!IsPassiveSpell(m_spellInfo)) + if (!m_spellInfo->IsPassiveSpell()) { SpellCastResult castResult = CheckItems(); if (castResult != SPELL_CAST_OK) @@ -6483,7 +6485,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (unit_target && // Check immune for offensive dispel - (!unit_target->IsImmuneToSchoolMask(GetSpellSchoolMask(m_spellInfo)) || + (!unit_target->IsImmuneToSchoolMask(m_spellInfo->GetSpellSchoolMask()) || friendly_dispel)) { if (!friendly_dispel && !m_caster->IsValidAttackTarget(unit_target)) @@ -6502,7 +6504,7 @@ SpellCastResult Spell::CheckCast(bool strict) // do not remove positive auras if friendly target // do not remove negative auras if non-friendly target // when removing charm auras ignore hostile reaction from the charm - if (!friendly_dispel && !positive && IsCharmSpell(holder->GetSpellProto())) + if (!friendly_dispel && !positive && holder->GetSpellProto()->IsCharmSpell()) if (CharmInfo *charm = unit_target->GetCharmInfo()) if (FactionTemplateEntry const* ft = charm->GetOriginalFactionTemplate()) if (charm->GetOriginalFactionTemplate()->IsFriendlyTo(*m_caster->getFactionTemplateEntry())) @@ -6711,8 +6713,8 @@ SpellCastResult Spell::CheckCast(bool strict) case SPELL_AURA_PERIODIC_MANA_LEECH: { if (!m_targets.getUnitTarget() && - !IsAreaEffectTarget(Targets(m_spellInfo->EffectImplicitTargetA[i])) && - !IsAreaEffectTarget(Targets(m_spellInfo->EffectImplicitTargetB[i]))) + !IsAreaEffectTarget(SpellTarget(m_spellInfo->EffectImplicitTargetA[i])) && + !IsAreaEffectTarget(SpellTarget(m_spellInfo->EffectImplicitTargetB[i]))) return SPELL_FAILED_BAD_IMPLICIT_TARGETS; if (m_caster->GetTypeId() != TYPEID_PLAYER || m_CastItem) @@ -6781,7 +6783,7 @@ SpellCastResult Spell::CheckPetCast(Unit* target) if (m_caster->IsNonMeleeSpellCasted(false)) //prevent spellcast interruption by another spellcast return SPELL_FAILED_SPELL_IN_PROGRESS; - if (m_caster->isInCombat() && IsNonCombatSpell(m_spellInfo)) + if (m_caster->isInCombat() && m_spellInfo->IsNonCombatSpell()) return SPELL_FAILED_AFFECTING_COMBAT; if (m_caster->GetTypeId() == TYPEID_UNIT && (((Creature*)m_caster)->IsPet() || m_caster->isCharmed())) @@ -6820,7 +6822,7 @@ SpellCastResult Spell::CheckPetCast(Unit* target) return SPELL_FAILED_BAD_TARGETS; // guessed error // SPELL_EFFECT_DISPEL -> Positive or negative depending on the target - if (IsPositiveSpell(m_spellInfo) && !IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_DISPEL)) + if (m_spellInfo->IsPositiveSpell() && !m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) { if (m_caster->IsHostileTo(_target)) return SPELL_FAILED_BAD_TARGETS; @@ -6906,7 +6908,7 @@ SpellCastResult Spell::CheckCasterAuras() const SpellAuraHolder *holder = itr->second; SpellEntry const * pEntry = holder->GetSpellProto(); - if ((GetSpellSchoolMask(pEntry) & school_immune) && !(pEntry->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE)) + if ((pEntry->GetSpellSchoolMask() & school_immune) && !(pEntry->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE)) continue; if ((1 << (pEntry->Dispel)) & dispel_immune) continue; @@ -6917,7 +6919,7 @@ SpellCastResult Spell::CheckCasterAuras() const if (!aura) continue; - if (GetSpellMechanicMask(pEntry, 1 << i) & mechanic_immune) + if (pEntry->GetSpellMechanicMask(1 << i) & mechanic_immune) continue; // Make a second check for spell failed so the right SPELL_FAILED message is returned. // That is needed when your casting is prevented by multiple states and you are only immune to some of them. @@ -6972,7 +6974,7 @@ bool Spell::CanAutoCast(Unit* target) if (!target->getAttackerForHelper()) return false; - if (!IsSpellHaveEffect(m_spellInfo, SPELL_EFFECT_SCHOOL_DAMAGE)) + if (!m_spellInfo->HasEffect(SPELL_EFFECT_SCHOOL_DAMAGE)) { for (int j = 0; j < MAX_EFFECT_INDEX; ++j) { @@ -6993,7 +6995,7 @@ bool Spell::CanAutoCast(Unit* target) } // Dont waste mana to heal someone already full life. - if (IsHealSpell(m_spellInfo) && target->GetMaxHealth() == target->GetHealth()) + if (m_spellInfo->IsHealSpell() && target->GetMaxHealth() == target->GetHealth()) return false; SpellCastResult result = CheckPetCast(target); @@ -7141,7 +7143,7 @@ uint32 Spell::CalculatePowerCost(SpellEntry const* spellInfo, Unit* caster, Spel return 0; } } - SpellSchools school = GetFirstSchoolInMask(spell ? spell->m_spellSchoolMask : GetSpellSchoolMask(spellInfo)); + SpellSchools school = GetFirstSchoolInMask(spell ? spell->m_spellSchoolMask : spellInfo->GetSpellSchoolMask()); // Flat mod from caster auras by spell school powerCost += caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school); // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost) @@ -7785,7 +7787,7 @@ CurrentSpellTypes Spell::GetCurrentContainer() const bool Spell::CheckTarget(Unit* target, SpellEffectIndex eff) { - if (target != m_caster && IsPositiveSpell(m_spellInfo)) + if (target != m_caster && m_spellInfo->IsPositiveSpell()) { Player* casterOwner = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself(); Player* targetOwner = target->GetCharmerOrOwnerPlayerOrPlayerItself(); @@ -7826,7 +7828,7 @@ bool Spell::CheckTarget(Unit* target, SpellEffectIndex eff) if (((Player*)target)->GetVisibility() == VISIBILITY_OFF) return false; - if (((Player*)target)->IsGameMaster() && !IsPositiveSpell(m_spellInfo)) + if (((Player*)target)->IsGameMaster() && !m_spellInfo->IsPositiveSpell()) return false; } @@ -7954,7 +7956,7 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) { // no, we aren't, do the typical update // check, if we have channeled spell on our hands - if (IsChanneledSpell(m_Spell->m_spellInfo)) + if (m_Spell->m_spellInfo->IsChanneledSpell()) { // evented channeled spell is processed separately, casted once after delay, and not destroyed till finish // check, if we have casting anything else except this channeled spell and autorepeat @@ -8478,7 +8480,7 @@ void Spell::OnSpellLaunch() m_caster->setAttackTimer(OFF_ATTACK, m_caster->getAttackTimer(OFF_ATTACK) + 200 + 40 * m_caster->GetDistance(unitTarget)); } - bool triggerAutoAttack = unitTarget != m_caster && !IsPositiveSpell(m_spellInfo) && !(m_spellInfo->Attributes & SPELL_ATTR_STOP_ATTACK_TARGET); + bool triggerAutoAttack = unitTarget != m_caster && !m_spellInfo->IsPositiveSpell() && !(m_spellInfo->Attributes & SPELL_ATTR_STOP_ATTACK_TARGET); m_caster->GetMotionMaster()->MoveCharge(unitTarget, sWorld.getConfig(CONFIG_UINT32_SPELLS_CCDELAY), triggerAutoAttack); } diff --git a/src/game/Spells/SpellAuras.cpp b/src/game/Spells/SpellAuras.cpp index 33f6d3bce..60b167816 100644 --- a/src/game/Spells/SpellAuras.cpp +++ b/src/game/Spells/SpellAuras.cpp @@ -54,6 +54,8 @@ #include "PlayerAI.h" #include "Anticheat.h" +using namespace Spells; + #define NULL_AURA_SLOT 0xFF /** @@ -273,7 +275,7 @@ Aura::Aura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBas m_currentBasePoints = currentBasePoints ? *currentBasePoints : spellproto->CalculateSimpleValue(eff); - m_positive = IsPositiveEffect(spellproto, m_effIndex); + m_positive = spellproto->IsPositiveEffect(m_effIndex); m_applyTime = time(nullptr); int32 damage; @@ -2616,7 +2618,7 @@ void Aura::HandleAuraTransform(bool apply, bool Real) for (Unit::AuraList::const_reverse_iterator i = otherTransforms.rbegin(); i != otherTransforms.rend(); ++i) { // negative auras are preferred - if (!IsPositiveSpell((*i)->GetSpellProto()->Id)) + if (!(*i)->GetSpellProto()->IsPositiveSpell()) { handledAura = *i; break; @@ -2837,7 +2839,7 @@ void Aura::HandleModPossess(bool apply, bool Real) return; caster->ModPossess(target, apply, m_removeMode); - target->AddThreat(caster,target->GetHealth(), false, GetSpellSchoolMask(GetSpellProto())); + target->AddThreat(caster,target->GetHealth(), false, GetSpellProto()->GetSpellSchoolMask()); if (!apply && GetId() == 24937) // Controlling Steam Tonk { @@ -3370,7 +3372,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real) // Stun/roots effects apply at charge end bool inCharge = target->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHARGE_MOTION_TYPE; // Frost stun aura -> freeze/unfreeze target - if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) + if (GetSpellProto()->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_FROST) target->ModifyAuraState(AURA_STATE_FROZEN, apply); target->addUnitState(inCharge ? UNIT_STAT_PENDING_STUNNED : UNIT_STAT_STUNNED); @@ -3401,7 +3403,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real) else { // Frost stun aura -> freeze/unfreeze target - if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) + if (GetSpellProto()->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_FROST) { bool found_another = false; for (AuraType const* itr = &frozenAuraTypes[0]; *itr != SPELL_AURA_NONE; ++itr) @@ -3409,7 +3411,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real) Unit::AuraList const& auras = target->GetAurasByType(*itr); for (Unit::AuraList::const_iterator i = auras.begin(); i != auras.end(); ++i) { - if (GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) + if ((*i)->GetSpellProto()->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_FROST) { found_another = true; break; @@ -3622,7 +3624,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real) // Stun/roots effects apply at charge end bool inCharge = target->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHARGE_MOTION_TYPE; // Frost root aura -> freeze/unfreeze target - if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) + if (GetSpellProto()->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_FROST) target->ModifyAuraState(AURA_STATE_FROZEN, apply); target->addUnitState(inCharge ? UNIT_STAT_PENDING_ROOT : UNIT_STAT_ROOT); @@ -3639,7 +3641,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real) else { // Frost root aura -> freeze/unfreeze target - if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) + if (GetSpellProto()->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_FROST) { bool found_another = false; for (AuraType const* itr = &frozenAuraTypes[0]; *itr != SPELL_AURA_NONE; ++itr) @@ -3647,7 +3649,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real) Unit::AuraList const& auras = target->GetAurasByType(*itr); for (Unit::AuraList::const_iterator i = auras.begin(); i != auras.end(); ++i) { - if (GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) + if ((*i)->GetSpellProto()->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_FROST) { found_another = true; break; @@ -3934,7 +3936,7 @@ void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real) next = iter; ++next; SpellEntry const *spell = iter->second->GetSpellProto(); - if ((GetSpellSchoolMask(spell) & school_mask) //Check for school mask + if ((spell->GetSpellSchoolMask() & school_mask) //Check for school mask && !(spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability && !iter->second->IsPositive() //Don't remove positive spells && spell->Id != GetId()) //Don't remove self @@ -4144,7 +4146,7 @@ uint32 Aura::CalculateDotDamage() const // MeleeDamagebonusDone for weapon based spells else { - WeaponAttackType attackType = GetWeaponAttackType(GetSpellProto()); + WeaponAttackType attackType = GetSpellProto()->GetWeaponAttackType(); damage = caster->MeleeDamageBonusDone(target, damage, attackType, GetSpellProto(), DOT, GetStackAmount()); } } @@ -5201,7 +5203,7 @@ void Aura::HandleShapeshiftBoosts(bool apply) if (itr->second.state == PLAYERSPELL_REMOVED) continue; if (itr->first == spellId1 || itr->first == spellId2) continue; SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(itr->first); - if (!spellInfo || !IsNeedCastSpellAtFormApply(spellInfo, form)) + if (!spellInfo || !spellInfo->IsNeedCastSpellAtFormApply(form)) continue; target->CastSpell(target, itr->first, true, nullptr, this); } @@ -5252,7 +5254,7 @@ void Aura::HandleShapeshiftBoosts(bool apply) // Interrupt current shape specific spells for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i))) - if (IsRemovedOnShapeLostSpell(spell->m_spellInfo)) + if (spell->m_spellInfo->IsRemovedOnShapeLostSpell()) target->InterruptSpell(CurrentSpellTypes(i), false); } } @@ -5403,7 +5405,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) if (spellProto->IsFitToFamilyMask()) { //+10% from +healing bonus - DoneActualBenefit = caster->SpellBaseHealingBonusDone(GetSpellSchoolMask(spellProto)) * 0.1f; + DoneActualBenefit = caster->SpellBaseHealingBonusDone(spellProto->GetSpellSchoolMask()) * 0.1f; break; } break; @@ -5412,7 +5414,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) if (spellProto->IsFitToFamilyMask()) { //+10% from +spd bonus - DoneActualBenefit = caster->SpellBaseDamageBonusDone(GetSpellSchoolMask(spellProto)) * 0.1f; + DoneActualBenefit = caster->SpellBaseDamageBonusDone(spellProto->GetSpellSchoolMask()) * 0.1f; break; } break; @@ -5421,7 +5423,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) if (spellProto->SpellIconID == 207 && spellProto->Category == 56) { //+10% from +spd bonus - DoneActualBenefit = caster->SpellBaseDamageBonusDone(GetSpellSchoolMask(spellProto)) * 0.1f; + DoneActualBenefit = caster->SpellBaseDamageBonusDone(spellProto->GetSpellSchoolMask()) * 0.1f; break; } break; @@ -5464,7 +5466,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data return; // Check for immune (not use charges) - if (target->IsImmuneToDamage(GetSpellSchoolMask(spellProto), spellProto)) + if (target->IsImmuneToDamage(spellProto->GetSpellSchoolMask(), spellProto)) return; uint32 absorb = 0; @@ -5501,13 +5503,13 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data // MeleeDamagebonus for weapon based spells else { - WeaponAttackType attackType = GetWeaponAttackType(spellProto); + WeaponAttackType attackType = spellProto->GetWeaponAttackType(); pdamage = target->MeleeDamageBonusTaken(pCaster, pdamage, attackType, spellProto, DOT, GetStackAmount()); } // Calculate armor mitigation if it is a physical spell // But not for bleed mechanic spells - if (GetSpellSchoolMask(spellProto) & SPELL_SCHOOL_MASK_NORMAL && GetEffectMechanic(spellProto, m_effIndex) != MECHANIC_BLEED && !(spellProto->Custom & SPELL_CUSTOM_IGNORE_ARMOR)) + if (spellProto->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_NORMAL && spellProto->GetEffectMechanic(m_effIndex) != MECHANIC_BLEED && !(spellProto->Custom & SPELL_CUSTOM_IGNORE_ARMOR)) { uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(target, pdamage); cleanDamage.damage += pdamage - pdamageReductedArmor; @@ -5539,7 +5541,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data } - target->CalculateDamageAbsorbAndResist(pCaster, GetSpellSchoolMask(spellProto), DOT, pdamage, &absorb, &resist, spellProto); + target->CalculateDamageAbsorbAndResist(pCaster, spellProto->GetSpellSchoolMask(), DOT, pdamage, &absorb, &resist, spellProto); DETAIL_FILTER_LOG(LOG_FILTER_PERIODIC_AFFECTS, "PeriodicTick: %s attacked %s for %u dmg inflicted by %u", GetCasterGuid().GetString().c_str(), target->GetGuidStr().c_str(), pdamage, GetId()); @@ -5565,7 +5567,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data cleanDamage.absorb = absorb; cleanDamage.resist = resist; - pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true); + pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, spellProto->GetSpellSchoolMask(), spellProto, true); // Curse of Doom: If the target dies from this damage, there is a chance that a Doomguard will be summoned. if (spellProto->Id == 603 && !target->isAlive() && !urand(0, 9)) pCaster->CastSpell(pCaster, 18662, true); @@ -5590,7 +5592,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data return; // Check for immune - if (target->IsImmuneToDamage(GetSpellSchoolMask(spellProto), spellProto)) + if (target->IsImmuneToDamage(spellProto->GetSpellSchoolMask(), spellProto)) return; uint32 absorb = 0; @@ -5600,7 +5602,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data uint32 pdamage = (m_modifier.m_amount > 0 ? uint32(m_modifier.m_amount) : 0); //Calculate armor mitigation if it is a physical spell - if (GetSpellSchoolMask(spellProto) & SPELL_SCHOOL_MASK_NORMAL) + if (spellProto->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_NORMAL) { uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(target, pdamage); cleanDamage.damage += pdamage - pdamageReductedArmor; @@ -5609,14 +5611,14 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data pdamage = target->SpellDamageBonusTaken(pCaster, spellProto, pdamage, DOT, GetStackAmount()); - target->CalculateDamageAbsorbAndResist(pCaster, GetSpellSchoolMask(spellProto), DOT, pdamage, &absorb, &resist, spellProto); + target->CalculateDamageAbsorbAndResist(pCaster, spellProto->GetSpellSchoolMask(), DOT, pdamage, &absorb, &resist, spellProto); DETAIL_FILTER_LOG(LOG_FILTER_PERIODIC_AFFECTS, "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u", GetCasterGuid().GetString().c_str(), target->GetGuidStr().c_str(), pdamage, GetId(), absorb); pCaster->DealDamageMods(target, pdamage, &absorb); - pCaster->SendSpellNonMeleeDamageLog(target, GetId(), pdamage, GetSpellSchoolMask(spellProto), absorb, resist, true, 0); + pCaster->SendSpellNonMeleeDamageLog(target, GetId(), pdamage, spellProto->GetSpellSchoolMask(), absorb, resist, true, 0); float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1; @@ -5638,7 +5640,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data cleanDamage.resist = resist; pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto); - int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false); + int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, spellProto->GetSpellSchoolMask(), spellProto, false); if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false)) for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) @@ -5740,10 +5742,10 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data uint32 damage = gain; uint32 absorb = 0; pCaster->DealDamageMods(pCaster, damage, &absorb); - pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), damage, GetSpellSchoolMask(spellProto), absorb, 0, true, 0, false); + pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), damage, spellProto->GetSpellSchoolMask(), absorb, 0, true, 0, false); CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL, absorb, 0); - pCaster->DealDamage(pCaster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(spellProto), spellProto, true); + pCaster->DealDamage(pCaster, damage, &cleanDamage, NODAMAGE, spellProto->GetSpellSchoolMask(), spellProto, true); } } break; @@ -5775,7 +5777,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data return; // Check for immune (not use charges) - if (target->IsImmuneToDamage(GetSpellSchoolMask(spellProto), spellProto)) + if (target->IsImmuneToDamage(spellProto->GetSpellSchoolMask(), spellProto)) return; // ignore non positive values (can be result apply spellmods to aura damage @@ -5807,7 +5809,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data { float threat = pCaster->ModifyPower(power, gain_amount) * sSpellMgr.GetSpellThreatMultiplier(spellProto); threat *= 0.5; // Mana Drain - target->AddThreat(pCaster, threat, false, GetSpellSchoolMask(spellProto), spellProto); + target->AddThreat(pCaster, threat, false, spellProto->GetSpellSchoolMask(), spellProto); } if (target->GetPower(power) == 0) { @@ -5899,7 +5901,7 @@ void Aura::PeriodicTick(SpellEntry const* sProto, AuraType auraType, uint32 data return; // Check for immune (not use charges) - if (target->IsImmuneToDamage(GetSpellSchoolMask(spellProto), spellProto)) + if (target->IsImmuneToDamage(spellProto->GetSpellSchoolMask(), spellProto)) return; int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; @@ -6178,12 +6180,12 @@ SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit *target, Wor m_applyTime = time(nullptr); m_isPassive = IsPassiveSpell(GetId()) || spellproto->Attributes == 0x80; - m_isDeathPersist = IsDeathPersistentSpell(spellproto); - m_isSingleTarget = HasSingleTargetAura(spellproto); + m_isDeathPersist = spellproto->IsDeathPersistentSpell(); + m_isSingleTarget = spellproto->HasSingleTargetAura(); m_procCharges = spellproto->procCharges; - m_isChanneled = IsChanneledSpell(spellproto); + m_isChanneled = spellproto->IsChanneledSpell(); - m_isRemovedOnShapeLost = m_casterGuid == m_target->GetObjectGuid() && IsRemovedOnShapeLostSpell(m_spellProto); + m_isRemovedOnShapeLost = m_casterGuid == m_target->GetObjectGuid() && m_spellProto->IsRemovedOnShapeLostSpell(); // Exceptions // Attaques circulaires @@ -6192,7 +6194,7 @@ SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit *target, Wor Unit* unitCaster = caster && caster->isType(TYPEMASK_UNIT) ? (Unit*)caster : NULL; - m_duration = m_maxDuration = CalculateSpellDuration(spellproto, unitCaster); + m_duration = m_maxDuration = spellproto->CalculateDuration(unitCaster); if (m_maxDuration == -1 || (m_isPassive && spellproto->DurationIndex == 0)) m_permanent = true; @@ -6224,9 +6226,9 @@ SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit *target, Wor for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) m_auras[i] = nullptr; - m_makesTargetSecondaryFocus = !IsPositiveSpell(GetSpellProto()) && (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_DAMAGE - || IsSpellHaveAura(m_spellProto, SPELL_AURA_MOD_CONFUSE) - || IsSpellHaveAura(m_spellProto, SPELL_AURA_MOD_FEAR)); + m_makesTargetSecondaryFocus = !GetSpellProto()->IsPositiveSpell() && (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_DAMAGE + || m_spellProto->HasAura(SPELL_AURA_MOD_CONFUSE) + || m_spellProto->HasAura(SPELL_AURA_MOD_FEAR)); } void SpellAuraHolder::AddAura(Aura *aura, SpellEffectIndex index) @@ -6327,7 +6329,7 @@ void SpellAuraHolder::_AddSpellAuraHolder() m_target->ApplyDiminishingAura(getDiminishGroup(), true); // Update Seals information - if (IsSealSpell(GetSpellProto())) + if (GetSpellProto()->IsSealSpell()) m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); } @@ -6385,7 +6387,7 @@ void SpellAuraHolder::_RemoveSpellAuraHolder() switch (m_spellProto->SpellFamilyName) { case SPELLFAMILY_PALADIN: - if (IsSealSpell(m_spellProto)) + if (m_spellProto->IsSealSpell()) removeState = AURA_STATE_JUDGEMENT; // Update Seals information break; } @@ -6433,13 +6435,13 @@ void SpellAuraHolder::CleanupTriggeredSpells() if (!tProto) continue; - if (GetSpellDuration(tProto) != -1) + if (tProto->GetDuration() != -1) continue; // needed for spell 43680, maybe others // TODO: is there a spell flag, which can solve this in a more sophisticated way? if (m_spellProto->EffectApplyAuraName[i] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && - GetSpellDuration(m_spellProto) == int32(m_spellProto->EffectAmplitude[i])) + m_spellProto->GetDuration() == int32(m_spellProto->EffectAmplitude[i])) continue; m_target->RemoveAurasDueToSpell(tSpellId); diff --git a/src/game/Spells/SpellEffects.cpp b/src/game/Spells/SpellEffects.cpp index ce960d451..5b0ac0a56 100644 --- a/src/game/Spells/SpellEffects.cpp +++ b/src/game/Spells/SpellEffects.cpp @@ -55,10 +55,11 @@ #include "TemporarySummon.h" #include "MoveMapSharedDefines.h" #include "GameEventMgr.h" - #include "InstanceData.h" #include "ScriptMgr.h" +using namespace Spells; + pEffect SpellEffects[TOTAL_SPELL_EFFECTS] = { &Spell::EffectNULL, // 0 @@ -326,9 +327,9 @@ void Spell::EffectEnvironmentalDMG(SpellEffectIndex eff_idx) // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc damage = m_spellInfo->CalculateSimpleValue(eff_idx); - m_caster->CalculateDamageAbsorbAndResist(m_caster, GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo); + m_caster->CalculateDamageAbsorbAndResist(m_caster, m_spellInfo->GetSpellSchoolMask(), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo); - m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false); + m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, m_spellInfo->GetSpellSchoolMask(), absorb, resist, false, 0, false); if (m_caster->GetTypeId() == TYPEID_PLAYER) ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage); } @@ -618,7 +619,7 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(itr->first); if (spellInfo->IsFitToFamily() && - spellInfo->Id != m_spellInfo->Id && GetSpellRecoveryTime(spellInfo) > 0) + spellInfo->Id != m_spellInfo->Id && spellInfo->GetRecoveryTime() > 0) ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true); else ++itr; @@ -1004,7 +1005,7 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(itr->first); if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && - spellInfo->Id != m_spellInfo->Id && GetSpellRecoveryTime(spellInfo) > 0) + spellInfo->Id != m_spellInfo->Id && spellInfo->GetRecoveryTime() > 0) ((Player*)m_caster)->RemoveSpellCooldown(itr->first, true); } return; @@ -1632,8 +1633,8 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(itr->first); if (spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && - (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) && - spellInfo->Id != m_spellInfo->Id && GetSpellRecoveryTime(spellInfo) > 0) + (spellInfo->GetSpellSchoolMask() & SPELL_SCHOOL_MASK_FROST) && + spellInfo->Id != m_spellInfo->Id && spellInfo->GetRecoveryTime() > 0) ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true); else ++itr; @@ -1813,7 +1814,7 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) { SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(itr->first); - if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0) + if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && spellInfo->GetRecoveryTime() > 0) ((Player*)m_caster)->RemoveSpellCooldown((itr++)->first, true); else ++itr; @@ -1957,7 +1958,7 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx) } // found spelldamage coefficients of 0.381% per 0.1 speed and 15.244 per 4.0 speed // but own calculation say 0.385 gives at most one point difference to published values - int32 spellDamage = m_caster->SpellBaseDamageBonusDone(GetSpellSchoolMask(m_spellInfo)); + int32 spellDamage = m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSpellSchoolMask()); float weaponSpeed = (1.0f / IN_MILLISECONDS) * m_CastItem->GetProto()->Delay; int32 totalDamage = int32((damage + 3.85f * spellDamage) * 0.01 * weaponSpeed); @@ -2129,7 +2130,7 @@ void Spell::EffectTriggerSpell(SpellEffectIndex eff_idx) { // Note: not exist spells with weapon req. and IsSpellHaveCasterSourceTargets == true // so this just for speedup places in else - caster = IsSpellWithCasterSourceTargetsOnly(spellInfo) ? unitTarget : m_caster; + caster = spellInfo->IsSpellWithCasterSourceTargetsOnly() ? unitTarget : m_caster; } caster->CastSpell(unitTarget, spellInfo, true, nullptr, nullptr, m_originalCasterGUID); @@ -2242,7 +2243,7 @@ void Spell::EffectApplyAura(SpellEffectIndex eff_idx) return; // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) - if ((!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) && + if ((!unitTarget->isAlive() && !(m_spellInfo->IsDeathOnlySpell() || m_spellInfo->IsDeathPersistentSpell())) && (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading())) return; @@ -3082,7 +3083,7 @@ void Spell::EffectDispel(SpellEffectIndex eff_idx) // do not remove positive auras if friendly target // do not remove negative auras if non-friendly target // when removing charm auras ignore hostile reaction from the charm - if (!friendly && IsCharmSpell(holder->GetSpellProto())) + if (!friendly && holder->GetSpellProto()->IsCharmSpell()) { if (CharmInfo *charm = unitTarget->GetCharmInfo()) if (FactionTemplateEntry const* ft = charm->GetOriginalFactionTemplate()) @@ -3272,7 +3273,7 @@ void Spell::EffectAddFarsight(SpellEffectIndex eff_idx) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - int32 duration = GetSpellDuration(m_spellInfo); + int32 duration = m_spellInfo->GetDuration(); DynamicObject* dynObj = new DynamicObject; // set radius to 0: spell not expected to work as persistent aura @@ -3315,7 +3316,7 @@ void Spell::EffectSummonWild(SpellEffectIndex eff_idx) float center_z = m_targets.m_destZ; float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[eff_idx])); - int32 duration = GetSpellDuration(m_spellInfo); + int32 duration = m_spellInfo->GetDuration(); TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_COMBAT_OR_DEAD_DESPAWN; int32 amount = damage > 0 ? damage : 1; @@ -3440,7 +3441,7 @@ void Spell::EffectSummonGuardian(SpellEffectIndex eff_idx) } // set timer for unsummon - int32 duration = CalculateSpellDuration(m_spellInfo, m_caster); + int32 duration = m_spellInfo->CalculateDuration(m_caster); // second direct cast unsummon guardian(s) (guardians without like functionality have cooldown > spawn time) if (!m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER) @@ -4223,7 +4224,7 @@ void Spell::EffectThreat(SpellEffectIndex eff_idx) if (!unitTarget->CanHaveThreatList()) return; - unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo); + unitTarget->AddThreat(m_caster, float(damage), false, m_spellInfo->GetSpellSchoolMask(), m_spellInfo); AddExecuteLogInfo(eff_idx, ExecuteLogInfo(unitTarget->GetObjectGuid())); } @@ -4293,7 +4294,7 @@ void Spell::EffectInterruptCast(SpellEffectIndex eff_idx) && ((i == CURRENT_GENERIC_SPELL && curSpellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE) || (i == CURRENT_CHANNELED_SPELL && curSpellInfo->ChannelInterruptFlags & CHANNEL_FLAG_INTERRUPT))) { - unitTarget->ProhibitSpellSchool(GetSpellSchoolMask(curSpellInfo), GetSpellDuration(m_spellInfo)); + unitTarget->ProhibitSpellSchool(curSpellInfo->GetSpellSchoolMask(), m_spellInfo->GetDuration()); unitTarget->InterruptSpell(CurrentSpellTypes(i), false); ExecuteLogInfo info(unitTarget->GetObjectGuid()); @@ -4339,7 +4340,7 @@ void Spell::EffectSummonObjectWild(SpellEffectIndex eff_idx) return; } - int32 duration = GetSpellDuration(m_spellInfo); + int32 duration = m_spellInfo->GetDuration(); // Sapphirons summoned iceblocks have a duration *just* long enough to dissapear before the ice bomb. // Since they are despawned by another spell anyway, I make the gobj add slightly longer to avoid any lag @@ -5089,7 +5090,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx) SpellEntry const *spellInfo = (*itr)->GetSpellProto(); // search seal (all seals have judgement's aura dummy spell id in 2 effect - if (!spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2) + if (!spellInfo || !(*itr)->GetSpellProto()->IsSealSpell() || (*itr)->GetEffIndex() != 2) continue; // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE @@ -5282,7 +5283,7 @@ void Spell::EffectDuel(SpellEffectIndex eff_idx) pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction()); pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() + 1); - int32 duration = GetSpellDuration(m_spellInfo); + int32 duration = m_spellInfo->GetDuration(); pGameObj->SetRespawnTime(duration > 0 ? duration / IN_MILLISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); @@ -5614,7 +5615,7 @@ void Spell::EffectEnchantHeldItem(SpellEffectIndex eff_idx) // Try duration index next if (!duration) - duration = GetSpellDuration(m_spellInfo); + duration = m_spellInfo->GetDuration(); // 10 seconds for enchants which don't have listed duration if (!duration) @@ -5783,7 +5784,7 @@ void Spell::EffectSummonObject(SpellEffectIndex eff_idx) } pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); - int32 duration = GetSpellDuration(m_spellInfo); + int32 duration = m_spellInfo->GetDuration(); pGameObj->SetRespawnTime(duration > 0 ? duration / IN_MILLISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(pGameObj); @@ -6062,7 +6063,7 @@ void Spell::EffectSummonCritter(SpellEffectIndex eff_idx) // some mini-pets have quests // set timer for unsummon - int32 duration = GetSpellDuration(m_spellInfo); + int32 duration = m_spellInfo->GetDuration(); if (duration > 0) critter->SetDuration(duration); @@ -6350,7 +6351,7 @@ void Spell::EffectTransmitted(SpellEffectIndex eff_idx) return; } - int32 duration = GetSpellDuration(m_spellInfo); + int32 duration = m_spellInfo->GetDuration(); switch (goinfo->type) { diff --git a/src/game/Spells/SpellEntry.cpp b/src/game/Spells/SpellEntry.cpp index f93774363..df2e82f9e 100644 --- a/src/game/Spells/SpellEntry.cpp +++ b/src/game/Spells/SpellEntry.cpp @@ -2,6 +2,269 @@ #include "SharedDefines.h" #include "SpellAuraDefines.h" #include "SpellMgr.h" +#include "Spell.h" + +using namespace Spells; + +SpellSpecific Spells::GetSpellSpecific(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(spellId); + if (!spellInfo) + return SPELL_NORMAL; + + switch (spellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + // Aspect of the Beast + if (spellInfo->Id == 13161) + return SPELL_ASPECT; + + // Food / Drinks (mostly) + if (spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) + { + bool food = false; + bool drink = false; + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + { + switch (spellInfo->EffectApplyAuraName[i]) + { + // Food + case SPELL_AURA_MOD_REGEN: + case SPELL_AURA_OBS_MOD_HEALTH: + food = true; + break; + // Drink + case SPELL_AURA_MOD_POWER_REGEN: + case SPELL_AURA_OBS_MOD_MANA: + drink = true; + break; + default: + break; + } + } + + if (food && drink) + return SPELL_FOOD_AND_DRINK; + else if (food) + return SPELL_FOOD; + else if (drink) + return SPELL_DRINK; + } + else + { + // Well Fed buffs (must be exclusive with Food / Drink replenishment effects, or else Well Fed will cause them to be removed) + // SpellIcon 2560 is Spell 46687, does not have this flag + if (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) + return SPELL_WELL_FED; + } + break; + } + case SPELLFAMILY_MAGE: + { + // family flags 18(Molten), 25(Frost/Ice), 28(Mage) + if (spellInfo->SpellFamilyFlags & UI64LIT(0x12000000)) + return SPELL_MAGE_ARMOR; + + if (spellInfo->EffectApplyAuraName[EFFECT_INDEX_0] == SPELL_AURA_MOD_CONFUSE && spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + return SPELL_MAGE_POLYMORPH; + + break; + } + case SPELLFAMILY_WARRIOR: + { + if (spellInfo->SpellFamilyFlags & UI64LIT(0x00008000010000)) + return SPELL_POSITIVE_SHOUT; + + break; + } + case SPELLFAMILY_WARLOCK: + { + // only warlock curses have this + if (spellInfo->Dispel == DISPEL_CURSE) + return SPELL_CURSE; + break; + } + case SPELLFAMILY_PRIEST: + { + // "Well Fed" buff from Blessed Sunfruit, Blessed Sunfruit Juice, Alterac Spring Water + if ((spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_SITTING) && + (spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK) && + (spellInfo->SpellIconID == 52 || spellInfo->SpellIconID == 79)) + return SPELL_WELL_FED; + break; + } + case SPELLFAMILY_HUNTER: + { + // only hunter stings have this + if (spellInfo->Dispel == DISPEL_POISON) + return SPELL_STING; + + // only hunter aspects have this (one have generic family), if exclude Auto Shot + if (spellInfo->activeIconID == 122 && spellInfo->Id != 75) + return SPELL_ASPECT; + + break; + } + case SPELLFAMILY_PALADIN: + { + if (spellInfo->IsSealSpell()) + return SPELL_SEAL; + + if (spellInfo->IsFitToFamilyMask(UI64LIT(0x0000000010000100))) + return SPELL_BLESSING; + + if ((spellInfo->IsFitToFamilyMask(UI64LIT(0x0000000020180400))) && spellInfo->baseLevel != 0) + return SPELL_JUDGEMENT; + + // Old Judgement of Command + if (spellInfo->SpellIconID == 561 && spellInfo->SpellVisual == 5652) + return SPELL_JUDGEMENT; + + for (int i = 0; i < 3; ++i) + { + // only paladin auras have this + if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + return SPELL_AURA; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + if (spellInfo->IsElementalShield()) + return SPELL_ELEMENTAL_SHIELD; + + break; + } + + case SPELLFAMILY_POTION: + return sSpellMgr.GetSpellElixirSpecific(spellInfo->Id); + } + + // only warlock armor/skin have this (in additional to family cases) + if (spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89) + return SPELL_WARLOCK_ARMOR; + + // Tracking spells (exclude Well Fed, some other always allowed cases) + if ((spellInfo->HasAura(SPELL_AURA_TRACK_CREATURES) || + spellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES) || + spellInfo->HasAura(SPELL_AURA_TRACK_STEALTHED)) && + ((spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_RESET_AUTO_ACTIONS) || (spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED))) + return SPELL_TRACKER; + + // elixirs can have different families, but potion most ofc. + if (SpellSpecific sp = sSpellMgr.GetSpellElixirSpecific(spellInfo->Id)) + return sp; + + // Attack speed reduction + if (spellInfo->HasSingleAura(SPELL_AURA_MOD_MELEE_HASTE)) + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + if (AuraType(spellInfo->EffectApplyAuraName[i]) == SPELL_AURA_MOD_MELEE_HASTE && spellInfo->EffectBasePoints[i] < 0) + return SPELL_NEGATIVE_HASTE; + + // Movement speed reduction + // Dazes are not affected + if (spellInfo->HasSingleAura(SPELL_AURA_MOD_DECREASE_SPEED) && !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNK18)) + return SPELL_SNARE; + + return SPELL_NORMAL; +} + +int32 Spells::CompareAuraRanks(uint32 spellId_1, uint32 spellId_2) +{ + SpellEntry const*spellInfo_1 = sSpellMgr.GetSpellEntry(spellId_1); + SpellEntry const*spellInfo_2 = sSpellMgr.GetSpellEntry(spellId_2); + if (!spellInfo_1 || !spellInfo_2) return 0; + if (spellId_1 == spellId_2) return 0; + + for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + if (spellInfo_1->Effect[i] != 0 && spellInfo_2->Effect[i] != 0 && spellInfo_1->Effect[i] == spellInfo_2->Effect[i]) + { + int32 diff = spellInfo_1->EffectBasePoints[i] - spellInfo_2->EffectBasePoints[i]; + if (spellInfo_1->CalculateSimpleValue(SpellEffectIndex(i)) < 0 && spellInfo_2->CalculateSimpleValue(SpellEffectIndex(i)) < 0) + return -diff; + else return diff; + } + } + return 0; +} + +bool Spells::CompareSpellSpecificAuras(SpellEntry const* spellInfo_1, SpellEntry const* spellInfo_2) +{ + if (!spellInfo_1 || !spellInfo_2) return 0; + if (spellInfo_1 == spellInfo_2) return 0; + + for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + for (int32 j = 0; j < MAX_EFFECT_INDEX; ++j) + { + if (spellInfo_1->Effect[i] == SPELL_EFFECT_APPLY_AURA + && spellInfo_1->EffectApplyAuraName[i] == spellInfo_2->EffectApplyAuraName[j]) + { + if (spellInfo_1->EffectBasePoints[i] < spellInfo_2->EffectBasePoints[j] && spellInfo_2->EffectBasePoints[j] < 0) + return true; + else if (spellInfo_1->EffectBasePoints[i] > spellInfo_2->EffectBasePoints[j] && spellInfo_2->EffectBasePoints[j] >= 0) + return true; + else if (spellInfo_1->EffectBasePoints[i] == spellInfo_2->EffectBasePoints[j] && spellInfo_1->GetDuration() >= spellInfo_2->GetDuration()) + return true; + } + } + } + + return false; +} + +bool Spells::IsPassiveSpell(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(spellId); + if (!spellInfo) + return false; + return spellInfo->IsPassiveSpell(); +} + +bool Spells::IsPositiveSpell(uint32 spellId) +{ + SpellEntry const *spellproto = sSpellMgr.GetSpellEntry(spellId); + if (!spellproto) + return false; + + return spellproto->IsPositiveSpell(); +} + +bool Spells::IsPositiveSpell(uint32 spellId, Unit* caster, Unit* victim) +{ + SpellEntry const *spellproto = sSpellMgr.GetSpellEntry(spellId); + if (!spellproto) + return false; + + return spellproto->IsPositiveSpell(caster, victim); +} + +bool Spells::IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2) +{ + // TODO - need better check + // Equal icon and spellfamily + if (spellInfo1->SpellFamilyName == spellInfo2->SpellFamilyName && + spellInfo1->SpellIconID == spellInfo2->SpellIconID) + return true; + + // TODO - need found Judgements rule + SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id); + // spell with single target specific types + switch (spec1) + { + case SPELL_JUDGEMENT: + case SPELL_MAGE_POLYMORPH: + if (GetSpellSpecific(spellInfo2->Id) == spec1) + return true; + break; + default: + break; + } + + return false; +} void SpellEntry::InitCachedValues() { @@ -235,79 +498,6 @@ DiminishingGroup SpellEntry::GetDiminishingReturnsGroup(bool triggered) const return DIMINISHING_NONE; } -bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group) -{ - switch (group) - { - case DIMINISHING_CONTROL_STUN: - case DIMINISHING_TRIGGER_STUN: - case DIMINISHING_KIDNEYSHOT: - case DIMINISHING_SLEEP: - case DIMINISHING_CONTROL_ROOT: - case DIMINISHING_TRIGGER_ROOT: - case DIMINISHING_FEAR: - case DIMINISHING_WARLOCK_FEAR: - case DIMINISHING_CHARM: - case DIMINISHING_POLYMORPH: - case DIMINISHING_FREEZE: - case DIMINISHING_KNOCKOUT: - case DIMINISHING_BANISH: - case DIMINISHING_LIMITONLY: - return true; - default: - return false; - } - return false; -} - -DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) -{ - switch (group) - { - case DIMINISHING_CONTROL_STUN: - case DIMINISHING_TRIGGER_STUN: - case DIMINISHING_KIDNEYSHOT: - return DRTYPE_ALL; - case DIMINISHING_SLEEP: - case DIMINISHING_CONTROL_ROOT: - case DIMINISHING_TRIGGER_ROOT: - case DIMINISHING_FEAR: - case DIMINISHING_CHARM: - case DIMINISHING_POLYMORPH: - case DIMINISHING_SILENCE: - case DIMINISHING_DISARM: - case DIMINISHING_DEATHCOIL: - case DIMINISHING_FREEZE: - case DIMINISHING_BANISH: - case DIMINISHING_WARLOCK_FEAR: - case DIMINISHING_KNOCKOUT: - return DRTYPE_PLAYER; - default: - break; - } - - return DRTYPE_NONE; -} - -float GetDiminishingRate(uint32 type) -{ - switch (type) - { - case DIMINISHING_LEVEL_1: - return 1.0f; - case DIMINISHING_LEVEL_2: - return 0.5f; - case DIMINISHING_LEVEL_3: - return 0.25f; - case DIMINISHING_LEVEL_IMMUNE: - return 0.0f; - default: - break; - } - - return 1.0f; -} - bool SpellEntry::IsPvEHeartBeat() const { if (!(Attributes & SPELL_ATTR_DIMINISHING_RETURNS)) @@ -330,9 +520,9 @@ bool SpellEntry::IsPvEHeartBeat() const bool SpellEntry::IsCCSpell() const { - if (IsChanneledSpell(this)) + if (IsChanneledSpell()) return false; - if (IsSpellHaveEffect(this, SPELL_EFFECT_INTERRUPT_CAST)) + if (HasEffect(SPELL_EFFECT_INTERRUPT_CAST)) return false; switch (GetDiminishingReturnsGroup(false)) @@ -343,3 +533,602 @@ bool SpellEntry::IsCCSpell() const } return true; } + +WeaponAttackType SpellEntry::GetWeaponAttackType() const +{ + switch (DmgClass) + { + case SPELL_DAMAGE_CLASS_MELEE: + if (HasAttribute(SPELL_ATTR_EX3_REQ_OFFHAND)) + return OFF_ATTACK; + else + return BASE_ATTACK; + break; + case SPELL_DAMAGE_CLASS_RANGED: + return RANGED_ATTACK; + break; + default: + // Wands + if (HasAttribute(SPELL_ATTR_EX2_AUTOREPEAT_FLAG)) + return RANGED_ATTACK; + else + return BASE_ATTACK; + break; + } +} + +uint32 SpellEntry::GetCastTime(Spell* spell) const +{ + if (spell) + { + // some triggered spells have data only usable for client + if (spell->IsTriggeredSpellWithRedundentData()) + return 0; + + // spell targeted to non-trading trade slot item instant at trade success apply + if (spell->GetCaster()->GetTypeId() == TYPEID_PLAYER) + if (TradeData* my_trade = ((Player*)(spell->GetCaster()))->GetTradeData()) + if (Item* nonTrade = my_trade->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED)) + if (nonTrade == spell->m_targets.getItemTarget()) + return 0; + } + + SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(CastingTimeIndex); + + // not all spells have cast time index and this is all is pasiive abilities + if (!spellCastTimeEntry) + return 0; + + int32 castTime = spellCastTimeEntry->CastTime; + + if (spell) + { + // Nostalrius: ne pas consommer les SpellModifier si 'castTime' = 0 (Eclat lunaire / Grace de la nature 16886) + if (castTime) + if (Player* modOwner = spell->GetCaster()->GetSpellModOwner()) + modOwner->ApplySpellMod(Id, SPELLMOD_CASTING_TIME, castTime, spell); + + if (!(Attributes & (SPELL_ATTR_IS_ABILITY | SPELL_ATTR_TRADESPELL))) +#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_12_1 + castTime = int32(castTime * spell->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED)); +#else + castTime = int32(castTime * (1.0f + spell->GetCaster()->GetInt32Value(UNIT_MOD_CAST_SPEED)/100.0f)); +#endif + else + { + if (spell->IsRangedSpell() && !spell->IsAutoRepeat()) + castTime = int32(castTime * spell->GetCaster()->m_modAttackSpeedPct[RANGED_ATTACK]); + } + } + + if (Attributes & SPELL_ATTR_RANGED && (!spell || !spell->IsAutoRepeat())) + castTime += 500; + + return (castTime > 0) ? uint32(castTime) : 0; +} + +uint32 SpellEntry::GetCastTimeForBonus(DamageEffectType damagetype) const +{ + uint32 CastingTime = !IsChanneledSpell() ? GetCastTime() : GetDuration(); + + if (CastingTime > 7000) CastingTime = 7000; + if (CastingTime < 1500) CastingTime = 1500; + + if (damagetype == DOT && !IsChanneledSpell()) + CastingTime = 3500; + + int32 overTime = 0; + uint8 effects = 0; + bool DirectDamage = false; + bool AreaEffect = false; + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + if (IsAreaEffectTarget(SpellTarget(EffectImplicitTargetA[i])) || IsAreaEffectTarget(SpellTarget(EffectImplicitTargetB[i]))) + AreaEffect = true; + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + switch (Effect[i]) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_POWER_DRAIN: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_HEAL: + DirectDamage = true; + break; + case SPELL_EFFECT_APPLY_AURA: + switch (EffectApplyAuraName[i]) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_LEECH: + if (GetDuration()) + overTime = GetDuration(); + break; + // Penalty for additional effects + case SPELL_AURA_DUMMY: + ++effects; + break; + case SPELL_AURA_MOD_DECREASE_SPEED: + ++effects; + break; + case SPELL_AURA_MOD_CONFUSE: + case SPELL_AURA_MOD_STUN: + case SPELL_AURA_MOD_ROOT: + // -10% per effect + effects += 2; + break; + default: + break; + } + break; + default: + break; + } + } + + // Combined Spells with Both Over Time and Direct Damage + if (overTime > 0 && CastingTime > 0 && DirectDamage) + { + // mainly for DoTs which are 3500 here otherwise + uint32 OriginalCastTime = GetCastTime(); + if (OriginalCastTime > 7000) OriginalCastTime = 7000; + if (OriginalCastTime < 1500) OriginalCastTime = 1500; + // Portion to Over Time + float PtOT = (overTime / 15000.0f) / ((overTime / 15000.0f) + (OriginalCastTime / 3500.0f)); + + if (damagetype == DOT) + CastingTime = uint32(CastingTime * PtOT); + else if (PtOT < 1.0f) + CastingTime = uint32(CastingTime * (1 - PtOT)); + else + CastingTime = 0; + } + + // Area Effect Spells receive only half of bonus + if (AreaEffect) + CastingTime /= 2; + + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for (int j = 0; j < MAX_EFFECT_INDEX; ++j) + { + if (Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + (Effect[j] == SPELL_EFFECT_APPLY_AURA && EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH)) + { + CastingTime /= 2; + break; + } + } + + // -5% of total per any additional effect (multiplicative) + for (int i = 0; i < effects; ++i) + CastingTime *= 0.95f; + + return CastingTime; +} + +float SpellEntry::CalculateDefaultCoefficient(DamageEffectType const damagetype) const +{ + // Damage over Time spells bonus calculation + float DotFactor = 1.0f; + if (damagetype == DOT) + { + if (!IsChanneledSpell()) + DotFactor = GetDuration() / 15000.0f; + + if (uint16 DotTicks = GetAuraMaxTicks()) + DotFactor /= DotTicks; + } + + // Distribute Damage over multiple effects, reduce by AoE + float coeff = GetCastTimeForBonus(damagetype) / 3500.0f; + + return coeff * DotFactor; +} + +float SpellEntry::CalculateCustomCoefficient(Unit const* caster, DamageEffectType const damageType, float coeff, Spell* spell, bool donePart) const +{ + if (!caster) + return coeff; + + switch (SpellFamilyName) + { + case SPELLFAMILY_PALADIN: + { + // Seal of Righteousness + if (IsFitToFamilyMask(UI64LIT(0x0000000008000000)) && SpellIconID == 25) + { + coeff = 0.092f; + float speed = BASE_ATTACK_TIME; + + if (caster->IsPlayer()) + { + if (Item *item = ((Player*)caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) + { + coeff = item->isOneHandedWeapon() ? 0.092f : 0.108f; + speed = item->GetProto()->Delay; + } + } + + speed /= 1000.0f; + + return speed * coeff; + } + // Seal of Command + if (Id == 20424) + { + return donePart ? 0.20f : 0.29f; + } + } + case SPELLFAMILY_SHAMAN: + { + if (!spell) + return coeff; + + // Chain Lightning / Chain Heal / Healing Wave (T1 8/8 bonus) + if (IsFitToFamilyMask(UI64LIT(0x00000000142))) + { + float multiplier = DmgMultiplier[0]; + + if (spell->GetTargetNum() > 1) + { + if (Player* modOwner = caster->GetSpellModOwner()) + { + // Improved Chain Heal (T2 3/8 bonus) / Gift of the Gathering Storm Chain Lightning Bonus + modOwner->ApplySpellMod(spell->m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier, spell); + } + } + + for (uint8 i = 1; i < spell->GetTargetNum(); ++i) + coeff *= multiplier; + return coeff; + } + } + default: + break; + } + + return coeff; +} + +int32 SpellEntry::GetDuration() const +{ + SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(DurationIndex); + if (!du) + return 0; + return (du->Duration[0] == -1) ? -1 : abs(du->Duration[0]); +} + +int32 SpellEntry::GetMaxDuration() const +{ + SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(DurationIndex); + if (!du) + return 0; + return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]); +} + +int32 SpellEntry::CalculateDuration(Unit const* caster) const +{ + int32 duration = GetDuration(); + + if (duration != -1 && caster) + { + int32 maxduration = GetMaxDuration(); + + if (duration != maxduration && caster->GetTypeId() == TYPEID_PLAYER) + duration += int32((maxduration - duration) * ((Player*)caster)->GetComboPoints() / 5); + + if (Player* modOwner = caster->GetSpellModOwner()) + { + modOwner->ApplySpellMod(Id, SPELLMOD_DURATION, duration); + + if (duration < 0) + duration = 0; + } + } + + return duration; +} + +uint16 SpellEntry::GetAuraMaxTicks() const +{ + int32 DotDuration = GetDuration(); + if (DotDuration == 0) + return 1; + + // 200% limit + if (DotDuration > 30000) + DotDuration = 30000; + + for (int j = 0; j < MAX_EFFECT_INDEX; ++j) + { + if (Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || + EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_HEAL || + EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH)) + { + if (EffectAmplitude[j] != 0) + return DotDuration / EffectAmplitude[j]; + break; + } + } + + return 6; +} + +bool SpellEntry::IsPositiveSpell(Unit* caster, Unit* victim) const +{ + if (Attributes & SPELL_ATTR_NEGATIVE) + return false; + // spells with at least one negative effect are considered negative + // some self-applied spells have negative effects but in self casting case negative check ignored. + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + if (Effect[i] && !IsPositiveEffect(SpellEffectIndex(i), caster, victim)) + return false; + return true; +} + +bool SpellEntry::IsPositiveEffect(SpellEffectIndex effIndex, Unit* caster, Unit* victim) const +{ + // Nostalrius (SpellMod) + if (Custom & SPELL_CUSTOM_POSITIVE) + return true; + if (Custom & SPELL_CUSTOM_NEGATIVE) + return false; + + // Hellfire. Damages the caster, but is still positive ! + // (Has same SpellFamilyFlags as Soul Fire oO) + if (IsFitToFamily() && SpellIconID == 937 && SpellVisual == 5423) + return true; + + switch (Effect[effIndex]) + { + case SPELL_EFFECT_DUMMY: + // some explicitly required dummy effect sets + switch (Id) + { + case 10258: // Awaken Vault Warder + case 18153: // Kodo Kombobulator + return true; + default: + break; + } + break; + // always positive effects (check before target checks that provided non-positive result in some case for positive effects) + case SPELL_EFFECT_HEAL: + case SPELL_EFFECT_LEARN_SPELL: + case SPELL_EFFECT_SKILL_STEP: + return true; + // Negative Effects + case SPELL_EFFECT_INSTAKILL: + // Suicide is a positive spell - ex. Garr Massive Eruption + if (EffectImplicitTargetA[effIndex] == TARGET_SELF && EffectImplicitTargetB[effIndex] == TARGET_NONE) + return true; + // Sacrifice is a positive spell - for the warlock :) + if (IsFitToFamily()) + return true; + return false; + // Dispel can be positive or negative depending on the target + case SPELL_EFFECT_DISPEL: + if (caster && victim) + { + if (CharmInfo *charm = victim->GetCharmInfo()) + if (FactionTemplateEntry const* ft = charm->GetOriginalFactionTemplate()) + return ft->IsFriendlyTo(*caster->getFactionTemplateEntry()); + return caster->IsFriendlyTo(victim); + } + // non-positive aura use + case SPELL_EFFECT_APPLY_AURA: + { + switch (EffectApplyAuraName[effIndex]) + { + case SPELL_AURA_DUMMY: + { + // dummy aura can be positive or negative dependent from casted spell + switch (Id) + { + case 13139: // net-o-matic special effect + case 23445: // evil twin + return false; + // some spells have unclear target modes for selection, so just make effect positive + case 27184: + case 27190: + case 27191: + case 27201: + case 27202: + case 27203: + return true; + default: + break; + } + } + break; + case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from base point sign (negative -> negative) + case SPELL_AURA_MOD_RESISTANCE: + case SPELL_AURA_MOD_STAT: + case SPELL_AURA_MOD_SKILL: + case SPELL_AURA_MOD_DODGE_PERCENT: + case SPELL_AURA_MOD_HEALING_PCT: + case SPELL_AURA_MOD_HEALING_DONE: + if (CalculateSimpleValue(effIndex) < 0) + return false; + break; + case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from bas point sign (positive -> negative) + if (CalculateSimpleValue(effIndex) < 0) + return true; + // let check by target modes (for Amplify Magic cases/etc) + break; + case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: + case SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT: + case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: + if (CalculateSimpleValue(effIndex) > 0) + return true; // some expected positive spells have unclear target modes // maybe don't need this at all now that we don't check for what was SPELL_ATTR_EX_NEGATIVE + break; + case SPELL_AURA_ADD_TARGET_TRIGGER: + return true; + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + if (Id != EffectTriggerSpell[effIndex]) + { + uint32 spellTriggeredId = EffectTriggerSpell[effIndex]; + SpellEntry const *spellTriggeredProto = sSpellMgr.GetSpellEntry(spellTriggeredId); + + if (spellTriggeredProto) + { + // non-positive targets of main spell return early + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + { + // if non-positive trigger cast targeted to positive target this main cast is non-positive + // this will place this spell auras as debuffs + if (spellTriggeredProto->Effect[i] && + IsPositiveTarget(spellTriggeredProto->EffectImplicitTargetA[i], spellTriggeredProto->EffectImplicitTargetB[i]) && + !spellTriggeredProto->IsPositiveEffect(SpellEffectIndex(i))) + return false; + } + } + } + break; + case SPELL_AURA_PROC_TRIGGER_SPELL: + // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example) + break; + case SPELL_AURA_MOD_STUN: //have positive and negative spells, we can't sort its correctly at this moment. + if (effIndex == EFFECT_INDEX_0 && Effect[EFFECT_INDEX_1] == 0 && Effect[EFFECT_INDEX_2] == 0) + return false; // but all single stun aura spells is negative + + // Petrification + if (Id == 17624) + return false; + break; + case SPELL_AURA_MOD_PACIFY_SILENCE: + if (Id == 24740) // Wisp Costume + return true; + return false; + case SPELL_AURA_MOD_SILENCE: + if (Id == 24732) // Bat Costume + return true; + return false; + case SPELL_AURA_MOD_ROOT: + case SPELL_AURA_GHOST: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_MOD_STALKED: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_MOD_DETECT_RANGE: + return false; + case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. + // part of negative spell if casted at self (prevent cancel) + if (EffectImplicitTargetA[effIndex] == TARGET_SELF) + return false; + break; + case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also + // part of positive spell if casted at self + if (EffectImplicitTargetA[effIndex] == TARGET_SELF && + SpellFamilyName == SPELLFAMILY_GENERIC) + return false; + // but not this if this first effect (don't found better check) + if (Attributes & 0x4000000 && effIndex == EFFECT_INDEX_0) + return false; + break; + case SPELL_AURA_MOD_SCALE: + // some spells negative + switch (Id) + { + case 802: // Mutate Bug, wrongly negative by target modes + return true; + } + break; + case SPELL_AURA_MECHANIC_IMMUNITY: + { + // non-positive immunities + switch (EffectMiscValue[effIndex]) + { + case MECHANIC_BANDAGE: + case MECHANIC_SHIELD: + case MECHANIC_MOUNT: + case MECHANIC_INVULNERABILITY: + return false; + default: + break; + } + } + break; + case SPELL_AURA_ADD_FLAT_MODIFIER: // mods + case SPELL_AURA_ADD_PCT_MODIFIER: + { + // non-positive mods + switch (EffectMiscValue[effIndex]) + { + case SPELLMOD_COST: // dependent from bas point sign (negative -> positive) + if (CalculateSimpleValue(effIndex) > 0) + return false; + break; + default: + break; + } + } + break; + default: + break; + } + break; + } + default: + break; + } + + // non-positive targets + if (!IsPositiveTarget(EffectImplicitTargetA[effIndex], EffectImplicitTargetB[effIndex])) + return false; + + // Attributes check + if (Attributes & SPELL_ATTR_NEGATIVE) + return false; + + // ok, positive + return true; +} + +SpellCastResult SpellEntry::GetErrorAtShapeshiftedCast(uint32 form) const +{ + // talents that learn spells can have stance requirements that need ignore + // (this requirement only for client-side stance show in talent description) + if (GetTalentSpellCost(Id) > 0 && + (Effect[EFFECT_INDEX_0] == SPELL_EFFECT_LEARN_SPELL || Effect[EFFECT_INDEX_1] == SPELL_EFFECT_LEARN_SPELL || Effect[EFFECT_INDEX_2] == SPELL_EFFECT_LEARN_SPELL)) + return SPELL_CAST_OK; + + uint32 stanceMask = (form ? 1 << (form - 1) : 0); + + if (stanceMask & StancesNot) // can explicitly not be casted in this stance + return SPELL_FAILED_NOT_SHAPESHIFT; + + if (stanceMask & Stances) // can explicitly be casted in this stance + return SPELL_CAST_OK; + + bool actAsShifted = false; + if (form > 0) + { + SpellShapeshiftFormEntry const *shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form); + if (!shapeInfo) + { + sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form); + return SPELL_CAST_OK; + } + actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells + } + + if (actAsShifted) + { + if (Attributes & SPELL_ATTR_NOT_SHAPESHIFT) // not while shapeshifted + return SPELL_FAILED_NOT_SHAPESHIFT; + else if (Stances != 0) // needs other shapeshift + return SPELL_FAILED_ONLY_SHAPESHIFT; + } + else + { + // needs shapeshift + if (!(AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && Stances != 0) + return SPELL_FAILED_ONLY_SHAPESHIFT; + } + + return SPELL_CAST_OK; +} diff --git a/src/game/Spells/SpellEntry.h b/src/game/Spells/SpellEntry.h index 739820883..4ffa1e0c3 100644 --- a/src/game/Spells/SpellEntry.h +++ b/src/game/Spells/SpellEntry.h @@ -25,11 +25,417 @@ #include #include "DBCStructure.h" #include "SharedDefines.h" +#include "SpellAuraDefines.h" -// Diminishing Returns interaction with spells -bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group); -DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); -float GetDiminishingRate(uint32 type); +class Spell; +class Unit; +class SpellEntry; + +// Custom flags assigned in the db +enum SpellAttributeCustom +{ + SPELL_CUSTOM_NONE = 0x000, + + SPELL_CUSTOM_ALLOW_STACK_BETWEEN_CASTER = 0x001, // For example 'Siphon Soul' must be able to stack between the warlocks on a mob + SPELL_CUSTOM_NEGATIVE = 0x002, + SPELL_CUSTOM_POSITIVE = 0x004, + SPELL_CUSTOM_CHAN_NO_DIST_LIMIT = 0x008, + SPELL_CUSTOM_FIXED_DAMAGE = 0x010, // Not affected by damage/healing done bonus + SPELL_CUSTOM_IGNORE_ARMOR = 0x020, + SPELL_CUSTOM_FROM_BEHIND = 0x040, // For spells that require the caster to be behind the target + SPELL_CUSTOM_FROM_FRONT = 0x080, // For spells that require the target to be in front of the caster + SPELL_CUSTOM_SINGLE_TARGET_AURA = 0x100, // Aura applied by spell can only be on 1 target at a time +}; + +// Custom flags assigned by the core based on spell template data +enum SpellAttributeInternal +{ + SPELL_INTERNAL_APPLIES_AURA = 0x001, + SPELL_INTERNAL_APPLIES_PERIODIC_AURA = 0x002, + SPELL_INTERNAL_PASSIVE_STACK_WITH_RANKS = 0x004, + SPELL_INTERNAL_POSITIVE = 0x008, + SPELL_INTERNAL_HEAL = 0x010, + SPELL_INTERNAL_DAMAGE = 0x020, + SPELL_INTERNAL_CASTER_SOURCE_TARGETS = 0x040, + SPELL_INTERNAL_AOE = 0x080, + SPELL_INTERNAL_AOE_AURA = 0x100, + SPELL_INTERNAL_DISMOUNT = 0x200, + SPELL_INTERNAL_CHARM = 0x400, + SPELL_INTERNAL_REFLECTABLE = 0x800, +}; + +// only used in code +enum SpellCategories +{ + SPELLCATEGORY_HEALTH_MANA_POTIONS = 4, + SPELLCATEGORY_DEVOUR_MAGIC = 12 +}; + +// Spell clasification +enum SpellSpecific +{ + SPELL_NORMAL = 0, + SPELL_SEAL = 1, + SPELL_BLESSING = 2, + SPELL_AURA = 3, + SPELL_STING = 4, + SPELL_CURSE = 5, + SPELL_ASPECT = 6, + SPELL_TRACKER = 7, + SPELL_WARLOCK_ARMOR = 8, + SPELL_MAGE_ARMOR = 9, + SPELL_ELEMENTAL_SHIELD = 10, + SPELL_MAGE_POLYMORPH = 11, + SPELL_POSITIVE_SHOUT = 12, + SPELL_JUDGEMENT = 13, + SPELL_BATTLE_ELIXIR = 14, + SPELL_GUARDIAN_ELIXIR = 15, + SPELL_FLASK_ELIXIR = 16, + //SPELL_PRESENCE = 17, // used in 3.x + //SPELL_HAND = 18, // used in 3.x + SPELL_WELL_FED = 19, + SPELL_FOOD = 20, + SPELL_DRINK = 21, + SPELL_FOOD_AND_DRINK = 22, + SPELL_NEGATIVE_HASTE = 23, + SPELL_SNARE = 24, +}; + +namespace Spells +{ + SpellSpecific GetSpellSpecific(uint32 spellId); + + // Diminishing Returns interaction with spells + inline DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) + { + switch (group) + { + case DIMINISHING_CONTROL_STUN: + case DIMINISHING_TRIGGER_STUN: + case DIMINISHING_KIDNEYSHOT: + return DRTYPE_ALL; + case DIMINISHING_SLEEP: + case DIMINISHING_CONTROL_ROOT: + case DIMINISHING_TRIGGER_ROOT: + case DIMINISHING_FEAR: + case DIMINISHING_CHARM: + case DIMINISHING_POLYMORPH: + case DIMINISHING_SILENCE: + case DIMINISHING_DISARM: + case DIMINISHING_DEATHCOIL: + case DIMINISHING_FREEZE: + case DIMINISHING_BANISH: + case DIMINISHING_WARLOCK_FEAR: + case DIMINISHING_KNOCKOUT: + return DRTYPE_PLAYER; + default: + break; + } + + return DRTYPE_NONE; + } + + inline float GetDiminishingRate(uint32 type) + { + switch (type) + { + case DIMINISHING_LEVEL_1: + return 1.0f; + case DIMINISHING_LEVEL_2: + return 0.5f; + case DIMINISHING_LEVEL_3: + return 0.25f; + case DIMINISHING_LEVEL_IMMUNE: + return 0.0f; + default: + break; + } + + return 1.0f; + } + + // Different spell properties + inline float GetSpellRadius(SpellRadiusEntry const *radius) { return (radius ? radius->Radius : 0); } + inline float GetSpellMinRange(SpellRangeEntry const *range) { return (range ? range->minRange : 0); } + inline float GetSpellMaxRange(SpellRangeEntry const *range) { return (range ? range->maxRange : 0); } + int32 CompareAuraRanks(uint32 spellId_1, uint32 spellId_2); + bool CompareSpellSpecificAuras(SpellEntry const* spellInfo_1, SpellEntry const* spellInfo_2); + + // order from less to more strict + // target not allow have more one spell specific from same caster + inline bool IsSingleFromSpellSpecificPerTargetPerCaster(SpellSpecific spellSpec1, SpellSpecific spellSpec2) + { + switch (spellSpec1) + { + case SPELL_BLESSING: + case SPELL_AURA: + case SPELL_STING: + case SPELL_CURSE: + case SPELL_ASPECT: + case SPELL_POSITIVE_SHOUT: + case SPELL_JUDGEMENT: + return spellSpec1 == spellSpec2; + default: + return false; + } + } + + // target not allow have more one ranks from spell from spell specific per target + inline bool IsSingleFromSpellSpecificSpellRanksPerTarget(SpellSpecific spellSpec1, SpellSpecific spellSpec2) + { + switch (spellSpec1) + { + case SPELL_BLESSING: + case SPELL_AURA: + case SPELL_CURSE: + case SPELL_ASPECT: + case SPELL_JUDGEMENT: + return spellSpec1 == spellSpec2; + default: + return false; + } + } + + // target not allow have more one spell specific per target from any caster + inline bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1, SpellSpecific spellSpec2) + { + switch (spellSpec1) + { + case SPELL_SEAL: + case SPELL_TRACKER: + case SPELL_WARLOCK_ARMOR: + case SPELL_MAGE_ARMOR: + case SPELL_ELEMENTAL_SHIELD: + case SPELL_MAGE_POLYMORPH: + case SPELL_WELL_FED: + case SPELL_NEGATIVE_HASTE: + case SPELL_SNARE: + return spellSpec1 == spellSpec2; + case SPELL_BATTLE_ELIXIR: + return spellSpec2 == SPELL_BATTLE_ELIXIR + || spellSpec2 == SPELL_FLASK_ELIXIR; + case SPELL_GUARDIAN_ELIXIR: + return spellSpec2 == SPELL_GUARDIAN_ELIXIR + || spellSpec2 == SPELL_FLASK_ELIXIR; + case SPELL_FLASK_ELIXIR: + return spellSpec2 == SPELL_BATTLE_ELIXIR + || spellSpec2 == SPELL_GUARDIAN_ELIXIR + || spellSpec2 == SPELL_FLASK_ELIXIR; + case SPELL_FOOD: + return spellSpec2 == SPELL_FOOD + || spellSpec2 == SPELL_FOOD_AND_DRINK; + case SPELL_DRINK: + return spellSpec2 == SPELL_DRINK + || spellSpec2 == SPELL_FOOD_AND_DRINK; + case SPELL_FOOD_AND_DRINK: + return spellSpec2 == SPELL_FOOD + || spellSpec2 == SPELL_DRINK + || spellSpec2 == SPELL_FOOD_AND_DRINK; + default: + return false; + } + } + + bool IsPassiveSpell(uint32 spellId); + bool IsPositiveSpell(uint32 spellId); + bool IsPositiveSpell(uint32 spellId, Unit* caster, Unit* victim); + + inline bool IsPositiveTarget(uint32 targetA, uint32 targetB) + { + switch (targetA) + { + // non-positive targets + case TARGET_CHAIN_DAMAGE: + case TARGET_ALL_ENEMY_IN_AREA: + case TARGET_ALL_ENEMY_IN_AREA_INSTANT: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + case TARGET_CURRENT_ENEMY_COORDINATES: + return false; + // positive or dependent + case TARGET_CASTER_COORDINATES: + return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER || targetB == TARGET_AREAEFFECT_INSTANT); + default: + break; + } + if (targetB) + return IsPositiveTarget(targetB, 0); + return true; + } + + inline bool IsExplicitPositiveTarget(uint32 targetA) + { + // positive targets that in target selection code expect target in m_targers, so not that auto-select target by spell data by m_caster and etc + switch (targetA) + { + case TARGET_SINGLE_FRIEND: + case TARGET_SINGLE_PARTY: + case TARGET_CHAIN_HEAL: + case TARGET_SINGLE_FRIEND_2: + case TARGET_AREAEFFECT_PARTY_AND_CLASS: + return true; + default: + break; + } + return false; + } + + inline bool IsExplicitNegativeTarget(uint32 targetA) + { + // non-positive targets that in target selection code expect target in m_targers, so not that auto-select target by spell data by m_caster and etc + switch (targetA) + { + case TARGET_CHAIN_DAMAGE: + case TARGET_CURRENT_ENEMY_COORDINATES: + return true; + default: + break; + } + return false; + } + + // Requires you to manually select an unit as the target. + inline bool IsExplicitlySelectedUnitTarget(uint32 target) + { + switch (target) + { + case TARGET_CHAIN_DAMAGE: + case TARGET_SINGLE_FRIEND: + case TARGET_UNIT_TARGET_ANY: + case TARGET_CHAIN_HEAL: + case TARGET_CURRENT_ENEMY_COORDINATES : + case TARGET_SINGLE_FRIEND_2: + //case TARGET_AREAEFFECT_PARTY_AND_CLASS: + return true; + } + return false; + } + + bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2); + + inline bool IsCasterSourceTarget(uint32 target) + { + switch (target ) + { + case TARGET_SELF: + case TARGET_PET: + case TARGET_ALL_PARTY_AROUND_CASTER: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_MASTER: + case TARGET_MINION: + case TARGET_ALL_PARTY: + case TARGET_ALL_PARTY_AROUND_CASTER_2: + case TARGET_SELF_FISHING: + case TARGET_TOTEM_EARTH: + case TARGET_TOTEM_WATER: + case TARGET_TOTEM_AIR: + case TARGET_TOTEM_FIRE: + case TARGET_AREAEFFECT_GO_AROUND_DEST: + return true; + default: + break; + } + return false; + } + + inline bool IsPointEffectTarget(SpellTarget target) + { + switch (target ) + { + case TARGET_INNKEEPER_COORDINATES: + case TARGET_TABLE_X_Y_Z_COORDINATES: + case TARGET_CASTER_COORDINATES: + case TARGET_SCRIPT_COORDINATES: + case TARGET_CURRENT_ENEMY_COORDINATES: + case TARGET_DUELVSPLAYER_COORDINATES: + return true; + default: + break; + } + return false; + } + + inline bool IsAreaEffectPossitiveTarget(SpellTarget target) + { + switch (target ) + { + case TARGET_ALL_PARTY_AROUND_CASTER: + case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: + case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: + case TARGET_ALL_PARTY: + case TARGET_ALL_PARTY_AROUND_CASTER_2: + case TARGET_AREAEFFECT_PARTY: + case TARGET_ALL_RAID_AROUND_CASTER: + case TARGET_AREAEFFECT_PARTY_AND_CLASS: + return true; + default: + break; + } + return false; + } + + inline bool IsAreaEffectTarget(SpellTarget target) + { + switch (target ) + { + case TARGET_AREAEFFECT_INSTANT: + case TARGET_AREAEFFECT_CUSTOM: + case TARGET_ALL_ENEMY_IN_AREA: + case TARGET_ALL_ENEMY_IN_AREA_INSTANT: + case TARGET_ALL_PARTY_AROUND_CASTER: + case TARGET_IN_FRONT_OF_CASTER: + case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: + case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: + case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: + case TARGET_ALL_PARTY: + case TARGET_ALL_PARTY_AROUND_CASTER_2: + case TARGET_AREAEFFECT_PARTY: + case TARGET_AREAEFFECT_GO_AROUND_DEST: + case TARGET_ALL_RAID_AROUND_CASTER: + case TARGET_AREAEFFECT_PARTY_AND_CLASS: + return true; + default: + break; + } + return false; + } + + inline bool IsAreaAuraEffect(uint32 effect) + { + return + effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect == SPELL_EFFECT_APPLY_AREA_AURA_PET || + // Post-vanilla but very useful sometimes. + effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID || + effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || + effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND ; + } + + inline uint32 GetDispellMask(DispelType dispel) + { + // If dispell all + if (dispel == DISPEL_ALL) + return DISPEL_ALL_MASK; + else + return (1 << dispel); + } + + inline bool IsEffectAppliesAura(uint32 effectName) + { + switch (effectName) + { + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + case SPELL_EFFECT_APPLY_AREA_AURA_PET: + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + return true; + } + + return false; + } +} class SpellEntry { @@ -201,6 +607,318 @@ class SpellEntry bool HasAttribute(SpellAttributesEx3 attribute) const { return AttributesEx3 & attribute; } bool HasAttribute(SpellAttributesEx4 attribute) const { return AttributesEx4 & attribute; } + inline bool HasEffect(SpellEffects effect) const + { + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + if (SpellEffects(Effect[i]) == effect) + return true; + return false; + } + + inline bool IsSpellAppliesAura() const + { + return Internal & SPELL_INTERNAL_APPLIES_AURA; + } + + inline bool IsSpellAppliesAura(uint32 effectMask) const + { + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + { + if (effectMask & (1 << i)) + { + if (Spells::IsEffectAppliesAura(Effect[i]) && EffectApplyAuraName[i]) + return true; + } + } + return false; + } + + // Spells that apply damage or heal over time + // Returns false for periodic and direct mixed spells (immolate, etc) + inline bool IsSpellAppliesPeriodicAura() const + { + return Internal & SPELL_INTERNAL_APPLIES_PERIODIC_AURA; + } + + inline bool IsEffectHandledOnDelayedSpellLaunch(SpellEffectIndex effecIdx) const + { + switch (Effect[effecIdx]) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + return true; + default: + return false; + } + } + + inline bool IsPeriodicRegenerateEffect(SpellEffectIndex effecIdx) const + { + switch (AuraType(EffectApplyAuraName[effecIdx])) + { + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + return true; + default: + return false; + } + } + + inline bool HasAura(AuraType aura) const + { + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + if (AuraType(EffectApplyAuraName[i]) == aura) + return true; + return false; + } + + inline bool HasSingleAura(AuraType aura) const + { + bool hasAura = false; + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + if (AuraType(EffectApplyAuraName[i]) == aura) + hasAura = true; + else if (Effect[i] == SPELL_EFFECT_APPLY_AURA) + return false; + return hasAura; + } + + inline bool IsSealSpell() const + { + //Collection of all the seal family flags. No other paladin spell has any of those. + return IsFitToFamily(); + } + + inline bool IsElementalShield() const + { + // family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus + return IsFitToFamilyMask() || Id == 23552; + } + + inline bool IsFromBehindOnlySpell() const + { + return ((AttributesEx2 == 0x100000 && (AttributesEx & 0x200) == 0x200) || (Custom & SPELL_CUSTOM_FROM_BEHIND)); + } + + inline bool IsPassiveSpell() const + { + // Nostalrius : 0x80 -> D'autres sorts passifs, dont les enchants par exemple + return (Attributes & (SPELL_ATTR_PASSIVE)) != 0; + } + + inline bool IsPassiveSpellStackableWithRanks() const + { + return Internal & SPELL_INTERNAL_PASSIVE_STACK_WITH_RANKS; + } + + inline bool IsDeathOnlySpell() const + { + return (AttributesEx3 & SPELL_ATTR_EX3_CAST_ON_DEAD) || (Id == 2584); + } + + inline bool IsDeathPersistentSpell() const + { + return HasAttribute(SPELL_ATTR_EX3_DEATH_PERSISTENT); + } + + inline bool IsNonCombatSpell() const + { + return (Attributes & SPELL_ATTR_CANT_USED_IN_COMBAT) != 0; + } + + inline bool IsPositiveSpell() const + { + return Internal & SPELL_INTERNAL_POSITIVE; + } + + bool IsPositiveSpell(Unit* caster, Unit* victim) const; + bool IsPositiveEffect(SpellEffectIndex effIndex, Unit* caster = nullptr, Unit* victim = nullptr) const; + + inline bool IsHealSpell() const + { + return Internal & SPELL_INTERNAL_HEAL; + } + + inline bool IsDamageSpell() const + { + return Internal & SPELL_INTERNAL_DAMAGE; + } + + inline bool HasSingleTargetAura() const + { + return Custom & SPELL_CUSTOM_SINGLE_TARGET_AURA; + } + + inline bool IsSpellWithCasterSourceTargetsOnly() const + { + return Internal & SPELL_INTERNAL_CASTER_SOURCE_TARGETS; + } + + inline bool IsAreaOfEffectSpell() const + { + return Internal & SPELL_INTERNAL_AOE; + } + + inline bool HasAreaAuraEffect() const + { + return Internal & SPELL_INTERNAL_AOE_AURA; + } + + inline bool IsDismountSpell() const + { + return Internal & SPELL_INTERNAL_DISMOUNT; + } + + inline bool IsCharmSpell() const + { + return Internal & SPELL_INTERNAL_CHARM; + } + + inline bool IsReflectableSpell() const + { + return Internal & SPELL_INTERNAL_REFLECTABLE; + } + + inline bool IsReflectableSpell(Unit* caster, Unit* victim) const + { + return DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !HasAttribute(SPELL_ATTR_IS_ABILITY) + && !HasAttribute(SPELL_ATTR_EX_CANT_BE_REFLECTED) && !HasAttribute(SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) + && !HasAttribute(SPELL_ATTR_PASSIVE) && !IsPositiveSpell(caster, victim); + } + + inline bool IsAutoRepeatRangedSpell() const + { + return (Attributes & SPELL_ATTR_RANGED) && (AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG); + } + + inline bool IsSpellRequiresRangedAP() const + { + return (SpellFamilyName == SPELLFAMILY_HUNTER && DmgClass != SPELL_DAMAGE_CLASS_MELEE); + } + + inline bool IsChanneledSpell() const + { + return (AttributesEx & (SPELL_ATTR_EX_CHANNELED_1 | SPELL_ATTR_EX_CHANNELED_2)); + } + + inline bool NeedsComboPoints() const + { + return (AttributesEx & (SPELL_ATTR_EX_REQ_TARGET_COMBO_POINTS | SPELL_ATTR_EX_REQ_COMBO_POINTS)); + } + + inline bool IsTotemSummonSpell() const + { + return Effect[0] >= SPELL_EFFECT_SUMMON_TOTEM_SLOT1 && Effect[0] <= SPELL_EFFECT_SUMMON_TOTEM_SLOT4; + } + + inline bool HasRealTimeDuration() const + { + return HasAttribute(SPELL_ATTR_EX4_REAL_TIME_DURATION); + } + + inline bool HasAuraWithSpellTriggerEffect() const + { + for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + switch (EffectApplyAuraName[i]) + { + case SPELL_AURA_PROC_TRIGGER_SPELL: + return true; + } + } + return false; + } + + inline bool IsNeedCastSpellAtFormApply(ShapeshiftForm form) const + { + if (!(Attributes & (SPELL_ATTR_PASSIVE | SPELL_ATTR_HIDDEN_CLIENTSIDE)) || !form) + return false; + + // passive spells with SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT are already active without shapeshift, do no recast! + // Feline Swiftness Passive 2a not have 0x1 mask in Stance field in spell data as expected + return ((Stances & (1 << (form - 1)) || Id == 24864 && form == FORM_CAT) && + !(AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT)); + } + + // Spell effects require a specific power type on the target + inline bool IsTargetPowerTypeValid(Powers powerType) const + { + for (int i = 0; i < MAX_EFFECT_INDEX; ++i) + { + if (Effect[i] == SPELL_EFFECT_NONE) + continue; + + if ((Effect[i] == SPELL_EFFECT_POWER_BURN || + Effect[i] == SPELL_EFFECT_POWER_DRAIN || + EffectApplyAuraName[i] == SPELL_AURA_PERIODIC_MANA_LEECH || + EffectApplyAuraName[i] == SPELL_AURA_POWER_BURN_MANA) && + int32(powerType) != EffectMiscValue[i]) + { + continue; + } + return true; + } + return false; + } + + inline bool IsRemovedOnShapeLostSpell() const + { + return (Stances || Id == 24864) && + !(AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && + !(Attributes & SPELL_ATTR_NOT_SHAPESHIFT); + } + + inline SpellSchoolMask GetSpellSchoolMask() const + { + return GetSchoolMask(School); + } + + inline uint32 GetSpellMechanicMask(uint32 effectMask) const + { + uint32 mask = 0; + if (Mechanic) + mask |= 1 << (Mechanic - 1); + + for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) + { + if (!(effectMask & (1 << i))) + continue; + + if (EffectMechanic[i]) + mask |= 1 << (EffectMechanic[i] - 1); + } + + return mask; + } + + inline Mechanics GetEffectMechanic(SpellEffectIndex effect) const + { + if (EffectMechanic[effect]) + return Mechanics(EffectMechanic[effect]); + if (Mechanic) + return Mechanics(Mechanic); + return MECHANIC_NONE; + } + + inline uint32 GetRecoveryTime() const + { + return RecoveryTime > CategoryRecoveryTime ? RecoveryTime : CategoryRecoveryTime; + } + + int32 GetDuration() const; + int32 GetMaxDuration() const; + int32 CalculateDuration(Unit const* caster = nullptr) const; + uint32 GetCastTime(Spell* spell = nullptr) const; + uint32 GetCastTimeForBonus(DamageEffectType damagetype) const; + uint16 GetAuraMaxTicks() const; + WeaponAttackType GetWeaponAttackType() const; + float CalculateDefaultCoefficient(DamageEffectType const damagetype) const; + float CalculateCustomCoefficient(Unit const* caster, DamageEffectType const damageType, float coeff, Spell* spell, bool donePart) const; + SpellCastResult GetErrorAtShapeshiftedCast(uint32 form) const; uint32 GetMechanic() const { return Mechanic; } uint32 GetManaCost() const { return manaCost; } uint32 GetSpellFamilyName() const { return SpellFamilyName; } @@ -211,6 +929,7 @@ class SpellEntry uint32 GetEffectApplyAuraNameByIndex(SpellEffectIndex j) const { return EffectApplyAuraName[j];} uint32 GetEffectMiscValue(SpellEffectIndex j) const { return EffectMiscValue[j];} uint64 GetSpellFamilyFlags() const { return SpellFamilyFlags; } + template struct Shift { diff --git a/src/game/Spells/SpellMgr.cpp b/src/game/Spells/SpellMgr.cpp index e2143d60a..e04db6a59 100644 --- a/src/game/Spells/SpellMgr.cpp +++ b/src/game/Spells/SpellMgr.cpp @@ -31,6 +31,8 @@ #include "MapManager.h" #include "Unit.h" +using namespace Spells; + SpellMgr::SpellMgr() { } @@ -41,1039 +43,6 @@ SpellMgr& SpellMgr::Instance() return spellMgr; } -int32 GetSpellDuration(SpellEntry const *spellInfo) -{ - if (!spellInfo) - return 0; - SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex); - if (!du) - return 0; - return (du->Duration[0] == -1) ? -1 : abs(du->Duration[0]); -} - -int32 GetSpellMaxDuration(SpellEntry const *spellInfo) -{ - if (!spellInfo) - return 0; - SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex); - if (!du) - return 0; - return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]); -} - -int32 CalculateSpellDuration(SpellEntry const *spellInfo, Unit const* caster) -{ - int32 duration = GetSpellDuration(spellInfo); - - if (duration != -1 && caster) - { - int32 maxduration = GetSpellMaxDuration(spellInfo); - - if (duration != maxduration && caster->GetTypeId() == TYPEID_PLAYER) - duration += int32((maxduration - duration) * ((Player*)caster)->GetComboPoints() / 5); - - if (Player* modOwner = caster->GetSpellModOwner()) - { - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_DURATION, duration); - - if (duration < 0) - duration = 0; - } - } - - return duration; -} - -uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell* spell) -{ - if (spell) - { - // some triggered spells have data only usable for client - if (spell->IsTriggeredSpellWithRedundentData()) - return 0; - - // spell targeted to non-trading trade slot item instant at trade success apply - if (spell->GetCaster()->GetTypeId() == TYPEID_PLAYER) - if (TradeData* my_trade = ((Player*)(spell->GetCaster()))->GetTradeData()) - if (Item* nonTrade = my_trade->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED)) - if (nonTrade == spell->m_targets.getItemTarget()) - return 0; - } - - SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex); - - // not all spells have cast time index and this is all is pasiive abilities - if (!spellCastTimeEntry) - return 0; - - int32 castTime = spellCastTimeEntry->CastTime; - - if (spell) - { - // Nostalrius: ne pas consommer les SpellModifier si 'castTime' = 0 (Eclat lunaire / Grace de la nature 16886) - if (castTime) - if (Player* modOwner = spell->GetCaster()->GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell); - - if (!(spellInfo->Attributes & (SPELL_ATTR_IS_ABILITY | SPELL_ATTR_TRADESPELL))) -#if SUPPORTED_CLIENT_BUILD >= CLIENT_BUILD_1_12_1 - castTime = int32(castTime * spell->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED)); -#else - castTime = int32(castTime * (1.0f + spell->GetCaster()->GetInt32Value(UNIT_MOD_CAST_SPEED)/100.0f)); -#endif - else - { - if (spell->IsRangedSpell() && !spell->IsAutoRepeat()) - castTime = int32(castTime * spell->GetCaster()->m_modAttackSpeedPct[RANGED_ATTACK]); - } - } - - if (spellInfo->Attributes & SPELL_ATTR_RANGED && (!spell || !spell->IsAutoRepeat())) - castTime += 500; - - return (castTime > 0) ? uint32(castTime) : 0; -} - -uint32 GetSpellCastTimeForBonus(SpellEntry const *spellProto, DamageEffectType damagetype) -{ - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - - if (CastingTime > 7000) CastingTime = 7000; - if (CastingTime < 1500) CastingTime = 1500; - - if (damagetype == DOT && !IsChanneledSpell(spellProto)) - CastingTime = 3500; - - int32 overTime = 0; - uint8 effects = 0; - bool DirectDamage = false; - bool AreaEffect = false; - - for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) - if (IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetA[i])) || IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetB[i]))) - AreaEffect = true; - - for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - switch (spellProto->Effect[i]) - { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_POWER_DRAIN: - case SPELL_EFFECT_HEALTH_LEECH: - case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE: - case SPELL_EFFECT_POWER_BURN: - case SPELL_EFFECT_HEAL: - DirectDamage = true; - break; - case SPELL_EFFECT_APPLY_AURA: - switch (spellProto->EffectApplyAuraName[i]) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_PERIODIC_LEECH: - if (GetSpellDuration(spellProto)) - overTime = GetSpellDuration(spellProto); - break; - // Penalty for additional effects - case SPELL_AURA_DUMMY: - ++effects; - break; - case SPELL_AURA_MOD_DECREASE_SPEED: - ++effects; - break; - case SPELL_AURA_MOD_CONFUSE: - case SPELL_AURA_MOD_STUN: - case SPELL_AURA_MOD_ROOT: - // -10% per effect - effects += 2; - break; - default: - break; - } - break; - default: - break; - } - } - - // Combined Spells with Both Over Time and Direct Damage - if (overTime > 0 && CastingTime > 0 && DirectDamage) - { - // mainly for DoTs which are 3500 here otherwise - uint32 OriginalCastTime = GetSpellCastTime(spellProto); - if (OriginalCastTime > 7000) OriginalCastTime = 7000; - if (OriginalCastTime < 1500) OriginalCastTime = 1500; - // Portion to Over Time - float PtOT = (overTime / 15000.0f) / ((overTime / 15000.0f) + (OriginalCastTime / 3500.0f)); - - if (damagetype == DOT) - CastingTime = uint32(CastingTime * PtOT); - else if (PtOT < 1.0f) - CastingTime = uint32(CastingTime * (1 - PtOT)); - else - CastingTime = 0; - } - - // Area Effect Spells receive only half of bonus - if (AreaEffect) - CastingTime /= 2; - - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for (int j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if (spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - (spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH)) - { - CastingTime /= 2; - break; - } - } - - // -5% of total per any additional effect (multiplicative) - for (int i = 0; i < effects; ++i) - CastingTime *= 0.95f; - - return CastingTime; -} - -uint16 GetSpellAuraMaxTicks(SpellEntry const* spellInfo) -{ - int32 DotDuration = GetSpellDuration(spellInfo); - if (DotDuration == 0) - return 1; - - // 200% limit - if (DotDuration > 30000) - DotDuration = 30000; - - for (int j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if (spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( - spellInfo->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || - spellInfo->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_HEAL || - spellInfo->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH)) - { - if (spellInfo->EffectAmplitude[j] != 0) - return DotDuration / spellInfo->EffectAmplitude[j]; - break; - } - } - - return 6; -} - -float CalculateDefaultCoefficient(SpellEntry const *spellProto, DamageEffectType const damagetype) -{ - // Damage over Time spells bonus calculation - float DotFactor = 1.0f; - if (damagetype == DOT) - { - if (!IsChanneledSpell(spellProto)) - DotFactor = GetSpellDuration(spellProto) / 15000.0f; - - if (uint16 DotTicks = GetSpellAuraMaxTicks(spellProto)) - DotFactor /= DotTicks; - } - - // Distribute Damage over multiple effects, reduce by AoE - float coeff = GetSpellCastTimeForBonus(spellProto, damagetype) / 3500.0f; - - return coeff * DotFactor; -} - - -float CalculateCustomCoefficient(SpellEntry const *spellProto, Unit const* caster, DamageEffectType const damageType, float coeff, Spell* spell, bool donePart) -{ - if (!caster) - return coeff; - - //if (caster->IsPlayer()) - //{ - switch (spellProto->SpellFamilyName) - { - case SPELLFAMILY_PALADIN: - { - // Seal of Righteousness - if (spellProto->IsFitToFamilyMask(UI64LIT(0x0000000008000000)) && spellProto->SpellIconID == 25) - { - coeff = 0.092f; - float speed = BASE_ATTACK_TIME; - - if (caster->IsPlayer()) - { - if (Item *item = ((Player*)caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) - { - coeff = item->isOneHandedWeapon() ? 0.092f : 0.108f; - speed = item->GetProto()->Delay; - } - } - - speed /= 1000.0f; - - return speed * coeff; - } - // Seal of Command - if (spellProto->Id == 20424) - { - return donePart ? 0.20f : 0.29f; - } - } - case SPELLFAMILY_SHAMAN: - { - if (!spell) - return coeff; - - // Chain Lightning / Chain Heal / Healing Wave (T1 8/8 bonus) - if (spellProto->IsFitToFamilyMask(UI64LIT(0x00000000142))) - { - float multiplier = spellProto->DmgMultiplier[0]; - - if (spell->GetTargetNum() > 1) - { - if (Player* modOwner = caster->GetSpellModOwner()) - { - // Improved Chain Heal (T2 3/8 bonus) / Gift of the Gathering Storm Chain Lightning Bonus - modOwner->ApplySpellMod(spell->m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier, spell); - } - } - - for (uint8 i = 1; i < spell->GetTargetNum(); ++i) - coeff *= multiplier; - return coeff; - } - } - default: - break; - } - //} - - return coeff; -} - -WeaponAttackType GetWeaponAttackType(SpellEntry const *spellInfo) -{ - if (!spellInfo) - return BASE_ATTACK; - - switch (spellInfo->DmgClass) - { - case SPELL_DAMAGE_CLASS_MELEE: - if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND) - return OFF_ATTACK; - else - return BASE_ATTACK; - break; - case SPELL_DAMAGE_CLASS_RANGED: - return RANGED_ATTACK; - break; - default: - // Wands - if (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG) - return RANGED_ATTACK; - else - return BASE_ATTACK; - break; - } -} - -bool IsPassiveSpell(uint32 spellId) -{ - SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(spellId); - if (!spellInfo) - return false; - return IsPassiveSpell(spellInfo); -} - -bool IsPassiveSpell(SpellEntry const *spellInfo) -{ - // Nostalrius : 0x80 -> D'autres sorts passifs, dont les enchants par exemple - return (spellInfo->Attributes & (SPELL_ATTR_PASSIVE)) != 0; -} - -bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 spellId_2) -{ - SpellEntry const *spellInfo_1 = sSpellMgr.GetSpellEntry(spellId_1); - SpellEntry const *spellInfo_2 = sSpellMgr.GetSpellEntry(spellId_2); - if (!spellInfo_1 || !spellInfo_2) return false; - if (spellInfo_1->Id == spellId_2) return false; - - for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - for (int32 j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if (spellInfo_1->Effect[i] == spellInfo_2->Effect[j] - && spellInfo_1->EffectApplyAuraName[i] == spellInfo_2->EffectApplyAuraName[j] - && spellInfo_1->EffectMiscValue[i] == spellInfo_2->EffectMiscValue[j] - && spellInfo_1->EffectItemType[i] == spellInfo_2->EffectItemType[j] - && (spellInfo_1->Effect[i] != 0 || spellInfo_1->EffectApplyAuraName[i] != 0 || - spellInfo_1->EffectMiscValue[i] != 0 || spellInfo_1->EffectItemType[i] != 0)) - return true; - } - } - - return false; -} - -int32 CompareAuraRanks(uint32 spellId_1, uint32 spellId_2) -{ - SpellEntry const*spellInfo_1 = sSpellMgr.GetSpellEntry(spellId_1); - SpellEntry const*spellInfo_2 = sSpellMgr.GetSpellEntry(spellId_2); - if (!spellInfo_1 || !spellInfo_2) return 0; - if (spellId_1 == spellId_2) return 0; - - for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - if (spellInfo_1->Effect[i] != 0 && spellInfo_2->Effect[i] != 0 && spellInfo_1->Effect[i] == spellInfo_2->Effect[i]) - { - int32 diff = spellInfo_1->EffectBasePoints[i] - spellInfo_2->EffectBasePoints[i]; - if (spellInfo_1->CalculateSimpleValue(SpellEffectIndex(i)) < 0 && spellInfo_2->CalculateSimpleValue(SpellEffectIndex(i)) < 0) - return -diff; - else return diff; - } - } - return 0; -} - -bool CompareSpellSpecificAuras(SpellEntry const* spellInfo_1, SpellEntry const* spellInfo_2) -{ - if (!spellInfo_1 || !spellInfo_2) return 0; - if (spellInfo_1 == spellInfo_2) return 0; - - for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - for (int32 j = 0; j < MAX_EFFECT_INDEX; ++j) - { - if (spellInfo_1->Effect[i] == SPELL_EFFECT_APPLY_AURA - && spellInfo_1->EffectApplyAuraName[i] == spellInfo_2->EffectApplyAuraName[j]) - { - if (spellInfo_1->EffectBasePoints[i] < spellInfo_2->EffectBasePoints[j] && spellInfo_2->EffectBasePoints[j] < 0) - return true; - else if (spellInfo_1->EffectBasePoints[i] > spellInfo_2->EffectBasePoints[j] && spellInfo_2->EffectBasePoints[j] >= 0) - return true; - else if (spellInfo_1->EffectBasePoints[i] == spellInfo_2->EffectBasePoints[j] && GetSpellDuration(spellInfo_1) >= GetSpellDuration(spellInfo_2)) - return true; - } - } - } - - return false; -} - -SpellSpecific GetSpellSpecific(uint32 spellId) -{ - SpellEntry const *spellInfo = sSpellMgr.GetSpellEntry(spellId); - if (!spellInfo) - return SPELL_NORMAL; - - switch (spellInfo->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - // Aspect of the Beast - if (spellInfo->Id == 13161) - return SPELL_ASPECT; - - // Food / Drinks (mostly) - if (spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) - { - bool food = false; - bool drink = false; - for (int i = 0; i < MAX_EFFECT_INDEX; ++i) - { - switch (spellInfo->EffectApplyAuraName[i]) - { - // Food - case SPELL_AURA_MOD_REGEN: - case SPELL_AURA_OBS_MOD_HEALTH: - food = true; - break; - // Drink - case SPELL_AURA_MOD_POWER_REGEN: - case SPELL_AURA_OBS_MOD_MANA: - drink = true; - break; - default: - break; - } - } - - if (food && drink) - return SPELL_FOOD_AND_DRINK; - else if (food) - return SPELL_FOOD; - else if (drink) - return SPELL_DRINK; - } - else - { - // Well Fed buffs (must be exclusive with Food / Drink replenishment effects, or else Well Fed will cause them to be removed) - // SpellIcon 2560 is Spell 46687, does not have this flag - if (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) - return SPELL_WELL_FED; - } - break; - } - case SPELLFAMILY_MAGE: - { - // family flags 18(Molten), 25(Frost/Ice), 28(Mage) - if (spellInfo->SpellFamilyFlags & UI64LIT(0x12000000)) - return SPELL_MAGE_ARMOR; - - if (spellInfo->EffectApplyAuraName[EFFECT_INDEX_0] == SPELL_AURA_MOD_CONFUSE && spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) - return SPELL_MAGE_POLYMORPH; - - break; - } - case SPELLFAMILY_WARRIOR: - { - if (spellInfo->SpellFamilyFlags & UI64LIT(0x00008000010000)) - return SPELL_POSITIVE_SHOUT; - - break; - } - case SPELLFAMILY_WARLOCK: - { - // only warlock curses have this - if (spellInfo->Dispel == DISPEL_CURSE) - return SPELL_CURSE; - break; - } - case SPELLFAMILY_PRIEST: - { - // "Well Fed" buff from Blessed Sunfruit, Blessed Sunfruit Juice, Alterac Spring Water - if ((spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_SITTING) && - (spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK) && - (spellInfo->SpellIconID == 52 || spellInfo->SpellIconID == 79)) - return SPELL_WELL_FED; - break; - } - case SPELLFAMILY_HUNTER: - { - // only hunter stings have this - if (spellInfo->Dispel == DISPEL_POISON) - return SPELL_STING; - - // only hunter aspects have this (one have generic family), if exclude Auto Shot - if (spellInfo->activeIconID == 122 && spellInfo->Id != 75) - return SPELL_ASPECT; - - break; - } - case SPELLFAMILY_PALADIN: - { - if (IsSealSpell(spellInfo)) - return SPELL_SEAL; - - if (spellInfo->IsFitToFamilyMask(UI64LIT(0x0000000010000100))) - return SPELL_BLESSING; - - if ((spellInfo->IsFitToFamilyMask(UI64LIT(0x0000000020180400))) && spellInfo->baseLevel != 0) - return SPELL_JUDGEMENT; - - // Old Judgement of Command - if (spellInfo->SpellIconID == 561 && spellInfo->SpellVisual == 5652) - return SPELL_JUDGEMENT; - - for (int i = 0; i < 3; ++i) - { - // only paladin auras have this - if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY) - return SPELL_AURA; - } - break; - } - case SPELLFAMILY_SHAMAN: - { - if (IsElementalShield(spellInfo)) - return SPELL_ELEMENTAL_SHIELD; - - break; - } - - case SPELLFAMILY_POTION: - return sSpellMgr.GetSpellElixirSpecific(spellInfo->Id); - } - - // only warlock armor/skin have this (in additional to family cases) - if (spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89) - return SPELL_WARLOCK_ARMOR; - - // Tracking spells (exclude Well Fed, some other always allowed cases) - if ((IsSpellHaveAura(spellInfo, SPELL_AURA_TRACK_CREATURES) || - IsSpellHaveAura(spellInfo, SPELL_AURA_TRACK_RESOURCES) || - IsSpellHaveAura(spellInfo, SPELL_AURA_TRACK_STEALTHED)) && - ((spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_RESET_AUTO_ACTIONS) || (spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED))) - return SPELL_TRACKER; - - // elixirs can have different families, but potion most ofc. - if (SpellSpecific sp = sSpellMgr.GetSpellElixirSpecific(spellInfo->Id)) - return sp; - - // Attack speed reduction - if (IsSpellHaveSingleAura(spellInfo, SPELL_AURA_MOD_MELEE_HASTE)) - for (int i = 0; i < MAX_EFFECT_INDEX; ++i) - if (AuraType(spellInfo->EffectApplyAuraName[i]) == SPELL_AURA_MOD_MELEE_HASTE && spellInfo->EffectBasePoints[i] < 0) - return SPELL_NEGATIVE_HASTE; - - // Movement speed reduction - // Dazes are not affected - if (IsSpellHaveSingleAura(spellInfo, SPELL_AURA_MOD_DECREASE_SPEED) && !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNK18)) - return SPELL_SNARE; - - return SPELL_NORMAL; -} - -// target not allow have more one spell specific from same caster -bool IsSingleFromSpellSpecificPerTargetPerCaster(SpellSpecific spellSpec1, SpellSpecific spellSpec2) -{ - switch (spellSpec1) - { - case SPELL_BLESSING: - case SPELL_AURA: - case SPELL_STING: - case SPELL_CURSE: - case SPELL_ASPECT: - case SPELL_POSITIVE_SHOUT: - case SPELL_JUDGEMENT: - return spellSpec1 == spellSpec2; - default: - return false; - } -} - -// target not allow have more one ranks from spell from spell specific per target -bool IsSingleFromSpellSpecificSpellRanksPerTarget(SpellSpecific spellSpec1, SpellSpecific spellSpec2) -{ - switch (spellSpec1) - { - case SPELL_BLESSING: - case SPELL_AURA: - case SPELL_CURSE: - case SPELL_ASPECT: - case SPELL_JUDGEMENT: - return spellSpec1 == spellSpec2; - default: - return false; - } -} - -// target not allow have more one spell specific per target from any caster -bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1, SpellSpecific spellSpec2) -{ - switch (spellSpec1) - { - case SPELL_SEAL: - case SPELL_TRACKER: - case SPELL_WARLOCK_ARMOR: - case SPELL_MAGE_ARMOR: - case SPELL_ELEMENTAL_SHIELD: - case SPELL_MAGE_POLYMORPH: - case SPELL_WELL_FED: - case SPELL_NEGATIVE_HASTE: - case SPELL_SNARE: - return spellSpec1 == spellSpec2; - case SPELL_BATTLE_ELIXIR: - return spellSpec2 == SPELL_BATTLE_ELIXIR - || spellSpec2 == SPELL_FLASK_ELIXIR; - case SPELL_GUARDIAN_ELIXIR: - return spellSpec2 == SPELL_GUARDIAN_ELIXIR - || spellSpec2 == SPELL_FLASK_ELIXIR; - case SPELL_FLASK_ELIXIR: - return spellSpec2 == SPELL_BATTLE_ELIXIR - || spellSpec2 == SPELL_GUARDIAN_ELIXIR - || spellSpec2 == SPELL_FLASK_ELIXIR; - case SPELL_FOOD: - return spellSpec2 == SPELL_FOOD - || spellSpec2 == SPELL_FOOD_AND_DRINK; - case SPELL_DRINK: - return spellSpec2 == SPELL_DRINK - || spellSpec2 == SPELL_FOOD_AND_DRINK; - case SPELL_FOOD_AND_DRINK: - return spellSpec2 == SPELL_FOOD - || spellSpec2 == SPELL_DRINK - || spellSpec2 == SPELL_FOOD_AND_DRINK; - default: - return false; - } -} - -bool IsPositiveTarget(uint32 targetA, uint32 targetB) -{ - switch (targetA) - { - // non-positive targets - case TARGET_CHAIN_DAMAGE: - case TARGET_ALL_ENEMY_IN_AREA: - case TARGET_ALL_ENEMY_IN_AREA_INSTANT: - case TARGET_IN_FRONT_OF_CASTER: - case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: - case TARGET_CURRENT_ENEMY_COORDINATES: - return false; - // positive or dependent - case TARGET_CASTER_COORDINATES: - return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER || targetB == TARGET_AREAEFFECT_INSTANT); - default: - break; - } - if (targetB) - return IsPositiveTarget(targetB, 0); - return true; -} - -bool IsExplicitPositiveTarget(uint32 targetA) -{ - // positive targets that in target selection code expect target in m_targers, so not that auto-select target by spell data by m_caster and etc - switch (targetA) - { - case TARGET_SINGLE_FRIEND: - case TARGET_SINGLE_PARTY: - case TARGET_CHAIN_HEAL: - case TARGET_SINGLE_FRIEND_2: - case TARGET_AREAEFFECT_PARTY_AND_CLASS: - return true; - default: - break; - } - return false; -} - -bool IsExplicitNegativeTarget(uint32 targetA) -{ - // non-positive targets that in target selection code expect target in m_targers, so not that auto-select target by spell data by m_caster and etc - switch (targetA) - { - case TARGET_CHAIN_DAMAGE: - case TARGET_CURRENT_ENEMY_COORDINATES: - return true; - default: - break; - } - return false; -} - -bool IsPositiveEffect(SpellEntry const *spellproto, SpellEffectIndex effIndex, Unit* caster, Unit* victim) -{ - // Nostalrius (SpellMod) - if (spellproto->Custom & SPELL_CUSTOM_POSITIVE) - return true; - if (spellproto->Custom & SPELL_CUSTOM_NEGATIVE) - return false; - - // Hellfire. Damages the caster, but is still positive ! - // (Has same SpellFamilyFlags as Soul Fire oO) - if (spellproto->IsFitToFamily() && spellproto->SpellIconID == 937 && spellproto->SpellVisual == 5423) - return true; - - switch (spellproto->Effect[effIndex]) - { - case SPELL_EFFECT_DUMMY: - // some explicitly required dummy effect sets - switch (spellproto->Id) - { - case 10258: // Awaken Vault Warder - case 18153: // Kodo Kombobulator - return true; - default: - break; - } - break; - // always positive effects (check before target checks that provided non-positive result in some case for positive effects) - case SPELL_EFFECT_HEAL: - case SPELL_EFFECT_LEARN_SPELL: - case SPELL_EFFECT_SKILL_STEP: - return true; - // Negative Effects - case SPELL_EFFECT_INSTAKILL: - // Suicide is a positive spell - ex. Garr Massive Eruption - if (spellproto->EffectImplicitTargetA[effIndex] == TARGET_SELF && spellproto->EffectImplicitTargetB[effIndex] == TARGET_NONE) - return true; - // Sacrifice is a positive spell - for the warlock :) - if (spellproto->IsFitToFamily()) - return true; - return false; - // Dispel can be positive or negative depending on the target - case SPELL_EFFECT_DISPEL: - if (caster && victim) - { - if (CharmInfo *charm = victim->GetCharmInfo()) - if (FactionTemplateEntry const* ft = charm->GetOriginalFactionTemplate()) - return ft->IsFriendlyTo(*caster->getFactionTemplateEntry()); - return caster->IsFriendlyTo(victim); - } - // non-positive aura use - case SPELL_EFFECT_APPLY_AURA: - { - switch (spellproto->EffectApplyAuraName[effIndex]) - { - case SPELL_AURA_DUMMY: - { - // dummy aura can be positive or negative dependent from casted spell - switch (spellproto->Id) - { - case 13139: // net-o-matic special effect - case 23445: // evil twin - return false; - // some spells have unclear target modes for selection, so just make effect positive - case 27184: - case 27190: - case 27191: - case 27201: - case 27202: - case 27203: - return true; - default: - break; - } - } - break; - case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from base point sign (negative -> negative) - case SPELL_AURA_MOD_RESISTANCE: - case SPELL_AURA_MOD_STAT: - case SPELL_AURA_MOD_SKILL: - case SPELL_AURA_MOD_DODGE_PERCENT: - case SPELL_AURA_MOD_HEALING_PCT: - case SPELL_AURA_MOD_HEALING_DONE: - if (spellproto->CalculateSimpleValue(effIndex) < 0) - return false; - break; - case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from bas point sign (positive -> negative) - if (spellproto->CalculateSimpleValue(effIndex) < 0) - return true; - // let check by target modes (for Amplify Magic cases/etc) - break; - case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: - case SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT: - case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: - if (spellproto->CalculateSimpleValue(effIndex) > 0) - return true; // some expected positive spells have unclear target modes // maybe don't need this at all now that we don't check for what was SPELL_ATTR_EX_NEGATIVE - break; - case SPELL_AURA_ADD_TARGET_TRIGGER: - return true; - case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - if (spellproto->Id != spellproto->EffectTriggerSpell[effIndex]) - { - uint32 spellTriggeredId = spellproto->EffectTriggerSpell[effIndex]; - SpellEntry const *spellTriggeredProto = sSpellMgr.GetSpellEntry(spellTriggeredId); - - if (spellTriggeredProto) - { - // non-positive targets of main spell return early - for (int i = 0; i < MAX_EFFECT_INDEX; ++i) - { - // if non-positive trigger cast targeted to positive target this main cast is non-positive - // this will place this spell auras as debuffs - if (spellTriggeredProto->Effect[i] && - IsPositiveTarget(spellTriggeredProto->EffectImplicitTargetA[i], spellTriggeredProto->EffectImplicitTargetB[i]) && - !IsPositiveEffect(spellTriggeredProto, SpellEffectIndex(i))) - return false; - } - } - } - break; - case SPELL_AURA_PROC_TRIGGER_SPELL: - // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example) - break; - case SPELL_AURA_MOD_STUN: //have positive and negative spells, we can't sort its correctly at this moment. - if (effIndex == EFFECT_INDEX_0 && spellproto->Effect[EFFECT_INDEX_1] == 0 && spellproto->Effect[EFFECT_INDEX_2] == 0) - return false; // but all single stun aura spells is negative - - // Petrification - if (spellproto->Id == 17624) - return false; - break; - case SPELL_AURA_MOD_PACIFY_SILENCE: - if (spellproto->Id == 24740) // Wisp Costume - return true; - return false; - case SPELL_AURA_MOD_SILENCE: - if (spellproto->Id == 24732) // Bat Costume - return true; - return false; - case SPELL_AURA_MOD_ROOT: - case SPELL_AURA_GHOST: - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_MOD_STALKED: - case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: - case SPELL_AURA_MOD_DETECT_RANGE: - return false; - case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. - // part of negative spell if casted at self (prevent cancel) - if (spellproto->EffectImplicitTargetA[effIndex] == TARGET_SELF) - return false; - break; - case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also - // part of positive spell if casted at self - if (spellproto->EffectImplicitTargetA[effIndex] == TARGET_SELF && - spellproto->SpellFamilyName == SPELLFAMILY_GENERIC) - return false; - // but not this if this first effect (don't found better check) - if (spellproto->Attributes & 0x4000000 && effIndex == EFFECT_INDEX_0) - return false; - break; - case SPELL_AURA_MOD_SCALE: - // some spells negative - switch (spellproto->Id) - { - case 802: // Mutate Bug, wrongly negative by target modes - return true; - } - break; - case SPELL_AURA_MECHANIC_IMMUNITY: - { - // non-positive immunities - switch (spellproto->EffectMiscValue[effIndex]) - { - case MECHANIC_BANDAGE: - case MECHANIC_SHIELD: - case MECHANIC_MOUNT: - case MECHANIC_INVULNERABILITY: - return false; - default: - break; - } - } - break; - case SPELL_AURA_ADD_FLAT_MODIFIER: // mods - case SPELL_AURA_ADD_PCT_MODIFIER: - { - // non-positive mods - switch (spellproto->EffectMiscValue[effIndex]) - { - case SPELLMOD_COST: // dependent from bas point sign (negative -> positive) - if (spellproto->CalculateSimpleValue(effIndex) > 0) - return false; - break; - default: - break; - } - } - break; - default: - break; - } - break; - } - default: - break; - } - - // non-positive targets - if (!IsPositiveTarget(spellproto->EffectImplicitTargetA[effIndex], spellproto->EffectImplicitTargetB[effIndex])) - return false; - - // Attributes check - if (spellproto->Attributes & SPELL_ATTR_NEGATIVE) - return false; - - // ok, positive - return true; -} - -bool IsPositiveSpell(uint32 spellId) -{ - SpellEntry const *spellproto = sSpellMgr.GetSpellEntry(spellId); - if (!spellproto) - return false; - - return IsPositiveSpell(spellproto); -} - -bool IsPositiveSpell(SpellEntry const *spellproto) -{ - return spellproto->Internal & SPELL_INTERNAL_POSITIVE; -} - -bool IsPositiveSpell(uint32 spellId, Unit* caster, Unit* victim) -{ - SpellEntry const *spellproto = sSpellMgr.GetSpellEntry(spellId); - if (!spellproto) - return false; - - return IsPositiveSpell(spellproto, caster, victim); -} - -bool IsPositiveSpell(SpellEntry const *spellproto, Unit* caster, Unit* victim) -{ - if (spellproto->Attributes & SPELL_ATTR_NEGATIVE) - return false; - // spells with at least one negative effect are considered negative - // some self-applied spells have negative effects but in self casting case negative check ignored. - for (int i = 0; i < MAX_EFFECT_INDEX; ++i) - if (spellproto->Effect[i] && !IsPositiveEffect(spellproto, SpellEffectIndex(i), caster, victim)) - return false; - return true; -} - -bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2) -{ - // TODO - need better check - // Equal icon and spellfamily - if (spellInfo1->SpellFamilyName == spellInfo2->SpellFamilyName && - spellInfo1->SpellIconID == spellInfo2->SpellIconID) - return true; - - // TODO - need found Judgements rule - SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id); - // spell with single target specific types - switch (spec1) - { - case SPELL_JUDGEMENT: - case SPELL_MAGE_POLYMORPH: - if (GetSpellSpecific(spellInfo2->Id) == spec1) - return true; - break; - default: - break; - } - - return false; -} - -SpellCastResult GetErrorAtShapeshiftedCast(SpellEntry const *spellInfo, uint32 form) -{ - // talents that learn spells can have stance requirements that need ignore - // (this requirement only for client-side stance show in talent description) - if (GetTalentSpellCost(spellInfo->Id) > 0 && - (spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[EFFECT_INDEX_1] == SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[EFFECT_INDEX_2] == SPELL_EFFECT_LEARN_SPELL)) - return SPELL_CAST_OK; - - uint32 stanceMask = (form ? 1 << (form - 1) : 0); - - if (stanceMask & spellInfo->StancesNot) // can explicitly not be casted in this stance - return SPELL_FAILED_NOT_SHAPESHIFT; - - if (stanceMask & spellInfo->Stances) // can explicitly be casted in this stance - return SPELL_CAST_OK; - - bool actAsShifted = false; - if (form > 0) - { - SpellShapeshiftFormEntry const *shapeInfo = sSpellShapeshiftFormStore.LookupEntry(form); - if (!shapeInfo) - { - sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form); - return SPELL_CAST_OK; - } - actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells - } - - if (actAsShifted) - { - if (spellInfo->Attributes & SPELL_ATTR_NOT_SHAPESHIFT) // not while shapeshifted - return SPELL_FAILED_NOT_SHAPESHIFT; - else if (spellInfo->Stances != 0) // needs other shapeshift - return SPELL_FAILED_ONLY_SHAPESHIFT; - } - else - { - // needs shapeshift - if (!(spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && spellInfo->Stances != 0) - return SPELL_FAILED_ONLY_SHAPESHIFT; - } - - return SPELL_CAST_OK; -} - void SpellMgr::LoadSpellTargetPositions() { mSpellTargetPositions.clear(); // need for reload case @@ -1572,7 +541,7 @@ void SpellMgr::LoadSpellBonuses() float direct_diff = 1000.0f; // for have big diff if no DB field value if (sbe.direct_damage) { - direct_calc = CalculateDefaultCoefficient(spell, SPELL_DIRECT_DAMAGE); + direct_calc = spell->CalculateDefaultCoefficient(SPELL_DIRECT_DAMAGE); direct_diff = std::abs(sbe.direct_damage - direct_calc); } @@ -1581,7 +550,7 @@ void SpellMgr::LoadSpellBonuses() float dot_diff = 1000.0f; // for have big diff if no DB field value if (sbe.dot_damage) { - dot_calc = CalculateDefaultCoefficient(spell, DOT); + dot_calc = spell->CalculateDefaultCoefficient(DOT); dot_diff = std::abs(sbe.dot_damage - dot_calc); } @@ -2372,7 +1341,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if (spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN) { // Paladin Seals - if (IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2)) + if (spellInfo_1->IsSealSpell() && spellInfo_2->IsSealSpell()) return true; // Concentration Aura and Improved Concentration Aura and Aura Mastery if ((spellInfo_1->SpellIconID == 1487) && (spellInfo_2->SpellIconID == 1487)) @@ -2415,7 +1384,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons // Generic peut etre, mais un peu debile .. :O // Exception : spellInfo_1->SpellIconID != 516 && // Sprint ameliore - IsPositiveSpell(spellInfo_1) == IsPositiveSpell(spellInfo_2) // Jugement n'ecrase pas le sceau en dudu pala-pala + spellInfo_1->IsPositiveSpell() == spellInfo_2->IsPositiveSpell() // Jugement n'ecrase pas le sceau en dudu pala-pala ) { bool isModifier = false; @@ -2542,7 +1511,7 @@ SpellEntry const* SpellMgr::SelectAuraRankForLevel(SpellEntry const* spellInfo, return spellInfo; // ignore selection for passive spells - if (IsPassiveSpell(spellInfo)) + if (spellInfo->IsPassiveSpell()) return spellInfo; bool needRankSelection = false; @@ -2551,9 +1520,9 @@ SpellEntry const* SpellMgr::SelectAuraRankForLevel(SpellEntry const* spellInfo, // for simple aura in check apply to any non caster based targets, in rank search mode to any explicit targets if (((spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA && (IsExplicitPositiveTarget(spellInfo->EffectImplicitTargetA[i]) || - IsAreaEffectPossitiveTarget(Targets(spellInfo->EffectImplicitTargetA[i])))) || + IsAreaEffectPossitiveTarget(SpellTarget(spellInfo->EffectImplicitTargetA[i])))) || spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY) && - IsPositiveEffect(spellInfo, SpellEffectIndex(i))) + spellInfo->IsPositiveEffect(SpellEffectIndex(i))) { needRankSelection = true; break; @@ -3165,7 +2134,7 @@ void SpellMgr::LoadSpellLearnSpells() // talent or passive spells or skill-step spells auto-casted and not need dependent learning, // pet teaching spells don't must be dependent learning (casted) // other required explicit dependent learning - dbc_node.autoLearned = entry->EffectImplicitTargetA[i] == TARGET_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(entry) || IsSpellHaveEffect(entry, SPELL_EFFECT_SKILL_STEP); + dbc_node.autoLearned = entry->EffectImplicitTargetA[i] == TARGET_PET || GetTalentSpellCost(spell) > 0 || entry->IsPassiveSpell() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMapBounds db_node_bounds = GetSpellLearnSpellMapBounds(spell); @@ -4061,13 +3030,13 @@ void SpellMgr::CheckUsedSpells(char const* table) } else { - if (effectType >= 0 && !IsSpellHaveEffect(spellEntry, SpellEffects(effectType))) + if (effectType >= 0 && !spellEntry->HasEffect(SpellEffects(effectType))) { sLog.outError("Spell %u '%s' not have effect %u but used in %s.", spell, name.c_str(), effectType, code.c_str()); continue; } - if (auraType >= 0 && !IsSpellHaveAura(spellEntry, AuraType(auraType))) + if (auraType >= 0 && !spellEntry->HasAura(AuraType(auraType))) { sLog.outError("Spell %u '%s' not have aura %u but used in %s.", spell, name.c_str(), auraType, code.c_str()); continue; @@ -4121,10 +3090,10 @@ void SpellMgr::CheckUsedSpells(char const* table) } else { - if (effectType >= 0 && !IsSpellHaveEffect(spellEntry, SpellEffects(effectType))) + if (effectType >= 0 && !spellEntry->HasEffect(SpellEffects(effectType))) continue; - if (auraType >= 0 && !IsSpellHaveAura(spellEntry, AuraType(auraType))) + if (auraType >= 0 && !spellEntry->HasAura(AuraType(auraType))) continue; } @@ -4384,7 +3353,7 @@ namespace SpellInternal bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellInfo) { - if (!IsPassiveSpell(spellInfo)) + if (!spellInfo->IsPassiveSpell()) return false; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) @@ -4474,12 +3443,12 @@ namespace SpellInternal bool IsAreaOfEffectSpell(SpellEntry const *spellInfo) { return - IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_0])) || - IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetB[EFFECT_INDEX_0])) || - IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_1])) || - IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetB[EFFECT_INDEX_1])) || - IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_2])) || - IsAreaEffectTarget(Targets(spellInfo->EffectImplicitTargetB[EFFECT_INDEX_2])); + IsAreaEffectTarget(SpellTarget(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_0])) || + IsAreaEffectTarget(SpellTarget(spellInfo->EffectImplicitTargetB[EFFECT_INDEX_0])) || + IsAreaEffectTarget(SpellTarget(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_1])) || + IsAreaEffectTarget(SpellTarget(spellInfo->EffectImplicitTargetB[EFFECT_INDEX_1])) || + IsAreaEffectTarget(SpellTarget(spellInfo->EffectImplicitTargetA[EFFECT_INDEX_2])) || + IsAreaEffectTarget(SpellTarget(spellInfo->EffectImplicitTargetB[EFFECT_INDEX_2])); } bool HasAreaAuraEffect(SpellEntry const *spellInfo) @@ -4502,14 +3471,14 @@ namespace SpellInternal bool IsCharmSpell(SpellEntry const *spellInfo) { - return IsSpellHaveAura(spellInfo, SPELL_AURA_MOD_CHARM) || IsSpellHaveAura(spellInfo, SPELL_AURA_MOD_POSSESS); + return spellInfo->HasAura(SPELL_AURA_MOD_CHARM) || spellInfo->HasAura(SPELL_AURA_MOD_POSSESS); } bool IsReflectableSpell(SpellEntry const* spellInfo) { return spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !spellInfo->HasAttribute(SPELL_ATTR_IS_ABILITY) && !spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_BE_REFLECTED) && !spellInfo->HasAttribute(SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) - && !spellInfo->HasAttribute(SPELL_ATTR_PASSIVE) && !IsPositiveSpell(spellInfo); + && !spellInfo->HasAttribute(SPELL_ATTR_PASSIVE) && !spellInfo->IsPositiveSpell(); } } @@ -4528,7 +3497,7 @@ void SpellMgr::AssignInternalSpellFlags() if (SpellInternal::IsPassiveSpellStackableWithRanks(pSpellEntry.get())) pSpellEntry->Internal |= SPELL_INTERNAL_PASSIVE_STACK_WITH_RANKS; - if (IsPositiveSpell(pSpellEntry.get(), nullptr, nullptr)) + if (pSpellEntry->IsPositiveSpell(nullptr, nullptr)) pSpellEntry->Internal |= SPELL_INTERNAL_POSITIVE; if (SpellInternal::IsHealSpell(pSpellEntry.get())) diff --git a/src/game/Spells/SpellMgr.h b/src/game/Spells/SpellMgr.h index 76873e166..d4941e457 100644 --- a/src/game/Spells/SpellMgr.h +++ b/src/game/Spells/SpellMgr.h @@ -38,574 +38,6 @@ class Player; class Spell; class Unit; -struct SpellModifier; - -// Custom flags assigned in the db -enum SpellAttributeCustom -{ - SPELL_CUSTOM_NONE = 0x000, - - // Par exemple 'Siphon d'ame' doit pouvoir se stacker entre les demos sur un mob. - SPELL_CUSTOM_ALLOW_STACK_BETWEEN_CASTER = 0x001, - SPELL_CUSTOM_NEGATIVE = 0x002, - SPELL_CUSTOM_POSITIVE = 0x004, - SPELL_CUSTOM_CHAN_NO_DIST_LIMIT = 0x008, - SPELL_CUSTOM_FIXED_DAMAGE = 0x010, // Not affected by damage/healing done bonus - SPELL_CUSTOM_IGNORE_ARMOR = 0x020, - SPELL_CUSTOM_FROM_BEHIND = 0x040, // For spells that require the caster to be behind the target - SPELL_CUSTOM_FROM_FRONT = 0x080, // For spells that require the target to be in front of the caster - SPELL_CUSTOM_SINGLE_TARGET_AURA = 0x100, // Aura applied by spell can only be on 1 target at a time -}; - -// Custom flags assigned by the core based on spell template data -enum SpellAttributeInternal -{ - SPELL_INTERNAL_APPLIES_AURA = 0x001, - SPELL_INTERNAL_APPLIES_PERIODIC_AURA = 0x002, - SPELL_INTERNAL_PASSIVE_STACK_WITH_RANKS = 0x004, - SPELL_INTERNAL_POSITIVE = 0x008, - SPELL_INTERNAL_HEAL = 0x010, - SPELL_INTERNAL_DAMAGE = 0x020, - SPELL_INTERNAL_CASTER_SOURCE_TARGETS = 0x040, - SPELL_INTERNAL_AOE = 0x080, - SPELL_INTERNAL_AOE_AURA = 0x100, - SPELL_INTERNAL_DISMOUNT = 0x200, - SPELL_INTERNAL_CHARM = 0x400, - SPELL_INTERNAL_REFLECTABLE = 0x800, -}; - -// only used in code -enum SpellCategories -{ - SPELLCATEGORY_HEALTH_MANA_POTIONS = 4, - SPELLCATEGORY_DEVOUR_MAGIC = 12 -}; - -// Spell clasification -enum SpellSpecific -{ - SPELL_NORMAL = 0, - SPELL_SEAL = 1, - SPELL_BLESSING = 2, - SPELL_AURA = 3, - SPELL_STING = 4, - SPELL_CURSE = 5, - SPELL_ASPECT = 6, - SPELL_TRACKER = 7, - SPELL_WARLOCK_ARMOR = 8, - SPELL_MAGE_ARMOR = 9, - SPELL_ELEMENTAL_SHIELD = 10, - SPELL_MAGE_POLYMORPH = 11, - SPELL_POSITIVE_SHOUT = 12, - SPELL_JUDGEMENT = 13, - SPELL_BATTLE_ELIXIR = 14, - SPELL_GUARDIAN_ELIXIR = 15, - SPELL_FLASK_ELIXIR = 16, - //SPELL_PRESENCE = 17, // used in 3.x - //SPELL_HAND = 18, // used in 3.x - SPELL_WELL_FED = 19, - SPELL_FOOD = 20, - SPELL_DRINK = 21, - SPELL_FOOD_AND_DRINK = 22, - SPELL_NEGATIVE_HASTE = 23, - SPELL_SNARE = 24, -}; - -SpellSpecific GetSpellSpecific(uint32 spellId); - -// Different spell properties -inline float GetSpellRadius(SpellRadiusEntry const *radius) { return (radius ? radius->Radius : 0); } -uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell* spell = NULL); -uint32 GetSpellCastTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype ); -float CalculateDefaultCoefficient(SpellEntry const *spellProto, DamageEffectType const damagetype); -float CalculateCustomCoefficient(SpellEntry const *spellProto, Unit const* caster, DamageEffectType const damageType, float coeff, Spell* spell, bool donePart); -inline float GetSpellMinRange(SpellRangeEntry const *range) { return (range ? range->minRange : 0); } -inline float GetSpellMaxRange(SpellRangeEntry const *range) { return (range ? range->maxRange : 0); } -inline uint32 GetSpellRecoveryTime(SpellEntry const *spellInfo) { return spellInfo->RecoveryTime > spellInfo->CategoryRecoveryTime ? spellInfo->RecoveryTime : spellInfo->CategoryRecoveryTime; } -int32 GetSpellDuration(SpellEntry const *spellInfo); -int32 GetSpellMaxDuration(SpellEntry const *spellInfo); -int32 CalculateSpellDuration(SpellEntry const *spellInfo, Unit const* caster = NULL); -uint16 GetSpellAuraMaxTicks(SpellEntry const* spellInfo); -WeaponAttackType GetWeaponAttackType(SpellEntry const *spellInfo); - -inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) -{ - for(int i = 0; i < MAX_EFFECT_INDEX; ++i) - if(SpellEffects(spellInfo->Effect[i])==effect) - return true; - return false; -} - -inline bool IsEffectAppliesAura(uint32 effectName) -{ - switch (effectName) - { - case SPELL_EFFECT_APPLY_AURA: - case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: - case SPELL_EFFECT_APPLY_AREA_AURA_PET: - case SPELL_EFFECT_APPLY_AREA_AURA_RAID: - case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: - case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: - return true; - } - - return false; -} - -inline bool IsSpellAppliesAura(SpellEntry const *spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_APPLIES_AURA; -} - -inline bool IsSpellAppliesAura(SpellEntry const *spellInfo, uint32 effectMask) -{ - for(int i = 0; i < MAX_EFFECT_INDEX; ++i) - { - if (effectMask & (1 << i)) - { - if (IsEffectAppliesAura(spellInfo->Effect[i]) && spellInfo->EffectApplyAuraName[i]) - return true; - } - } - return false; -} - -// Spells that apply damage or heal over time -// Returns false for periodic and direct mixed spells (immolate, etc) -inline bool IsSpellAppliesPeriodicAura(SpellEntry const *spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_APPLIES_PERIODIC_AURA; -} - -inline bool IsEffectHandledOnDelayedSpellLaunch(SpellEntry const *spellInfo, SpellEffectIndex effecIdx) -{ - switch (spellInfo->Effect[effecIdx]) - { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - return true; - default: - return false; - } -} - -inline bool IsPeriodicRegenerateEffect(SpellEntry const* spellInfo, SpellEffectIndex effecIdx) -{ - switch (AuraType(spellInfo->EffectApplyAuraName[effecIdx])) - { - case SPELL_AURA_PERIODIC_ENERGIZE: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: - return true; - default: - return false; - } -} - -inline bool IsSpellHaveAura(SpellEntry const *spellInfo, AuraType aura) -{ - for(int i = 0; i < MAX_EFFECT_INDEX; ++i) - if(AuraType(spellInfo->EffectApplyAuraName[i])==aura) - return true; - return false; -} - -inline bool IsSpellHaveSingleAura(SpellEntry const *spellInfo, AuraType aura) -{ - bool hasAura = false; - for (int i = 0; i < MAX_EFFECT_INDEX; ++i) - if (AuraType(spellInfo->EffectApplyAuraName[i]) == aura) - hasAura = true; - else if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA) - return false; - return hasAura; -} - -inline bool IsSpellLastAuraEffect(SpellEntry const *spellInfo, SpellEffectIndex effecIdx) -{ - for(int i = effecIdx+1; i < MAX_EFFECT_INDEX; ++i) - if(spellInfo->EffectApplyAuraName[i]) - return false; - return true; -} - -bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 spellId_2); - -inline bool IsSealSpell(SpellEntry const *spellInfo) -{ - //Collection of all the seal family flags. No other paladin spell has any of those. - return spellInfo->IsFitToFamily(); -} - -inline bool IsElementalShield(SpellEntry const *spellInfo) -{ - // family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus - return spellInfo->IsFitToFamilyMask() || spellInfo->Id == 23552; -} - -inline bool IsFromBehindOnlySpell(SpellEntry const *spellInfo) -{ - return ((spellInfo->AttributesEx2 == 0x100000 && (spellInfo->AttributesEx & 0x200) == 0x200) || (spellInfo->Custom & SPELL_CUSTOM_FROM_BEHIND)); -} - -int32 CompareAuraRanks(uint32 spellId_1, uint32 spellId_2); -bool CompareSpellSpecificAuras(SpellEntry const* spellInfo_1, SpellEntry const* spellInfo_2); - -// order from less to more strict -bool IsSingleFromSpellSpecificPerTargetPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2); -bool IsSingleFromSpellSpecificSpellRanksPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2); -bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2); - -bool IsPassiveSpell(uint32 spellId); -bool IsPassiveSpell(SpellEntry const* spellProto); - -inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto) -{ - return spellProto->Internal & SPELL_INTERNAL_PASSIVE_STACK_WITH_RANKS; -} - -inline bool IsDeathOnlySpell(SpellEntry const *spellInfo) -{ - return spellInfo->AttributesEx3 & SPELL_ATTR_EX3_CAST_ON_DEAD - || spellInfo->Id == 2584; -} - -inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) -{ - return spellInfo->HasAttribute(SPELL_ATTR_EX3_DEATH_PERSISTENT); -} - -inline bool IsNonCombatSpell(SpellEntry const *spellInfo) -{ - return (spellInfo->Attributes & SPELL_ATTR_CANT_USED_IN_COMBAT) != 0; -} - -bool IsPositiveSpell(uint32 spellId); -bool IsPositiveSpell(SpellEntry const *spellproto); -bool IsPositiveSpell(uint32 spellId, Unit* caster, Unit* victim); -bool IsPositiveSpell(SpellEntry const *spellproto, Unit* caster, Unit* victim); -bool IsPositiveEffect(SpellEntry const *spellInfo, SpellEffectIndex effIndex, Unit* caster = NULL, Unit* victim = NULL); -bool IsPositiveTarget(uint32 targetA, uint32 targetB); - -inline bool IsHealSpell(SpellEntry const *spellProto) -{ - return spellProto->Internal & SPELL_INTERNAL_HEAL; -} - -inline bool IsDamageSpell(SpellEntry const *spellProto) -{ - return spellProto->Internal & SPELL_INTERNAL_DAMAGE; -} - -bool IsExplicitPositiveTarget(uint32 targetA); -bool IsExplicitNegativeTarget(uint32 targetA); - -// Requires you to manually select an unit as the target. -inline bool IsExplicitlySelectedUnitTarget(uint32 target) -{ - switch (target) - { - case TARGET_CHAIN_DAMAGE: - case TARGET_SINGLE_FRIEND: - case TARGET_UNIT_TARGET_ANY: - case TARGET_CHAIN_HEAL: - case TARGET_CURRENT_ENEMY_COORDINATES : - case TARGET_SINGLE_FRIEND_2: - //case TARGET_AREAEFFECT_PARTY_AND_CLASS: - return true; - } - return false; -} - -inline bool HasSingleTargetAura(SpellEntry const *spellInfo) -{ - return spellInfo->Custom & SPELL_CUSTOM_SINGLE_TARGET_AURA; -} - -bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2); - -inline bool IsCasterSourceTarget(uint32 target) -{ - switch (target ) - { - case TARGET_SELF: - case TARGET_PET: - case TARGET_ALL_PARTY_AROUND_CASTER: - case TARGET_IN_FRONT_OF_CASTER: - case TARGET_MASTER: - case TARGET_MINION: - case TARGET_ALL_PARTY: - case TARGET_ALL_PARTY_AROUND_CASTER_2: - case TARGET_SELF_FISHING: - case TARGET_TOTEM_EARTH: - case TARGET_TOTEM_WATER: - case TARGET_TOTEM_AIR: - case TARGET_TOTEM_FIRE: - case TARGET_AREAEFFECT_GO_AROUND_DEST: - return true; - default: - break; - } - return false; -} - -inline bool IsSpellWithCasterSourceTargetsOnly(SpellEntry const* spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_CASTER_SOURCE_TARGETS; -} - -inline bool IsPointEffectTarget( Targets target ) -{ - switch (target ) - { - case TARGET_INNKEEPER_COORDINATES: - case TARGET_TABLE_X_Y_Z_COORDINATES: - case TARGET_CASTER_COORDINATES: - case TARGET_SCRIPT_COORDINATES: - case TARGET_CURRENT_ENEMY_COORDINATES: - case TARGET_DUELVSPLAYER_COORDINATES: - return true; - default: - break; - } - return false; -} - -inline bool IsAreaEffectPossitiveTarget( Targets target ) -{ - switch (target ) - { - case TARGET_ALL_PARTY_AROUND_CASTER: - case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: - case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: - case TARGET_ALL_PARTY: - case TARGET_ALL_PARTY_AROUND_CASTER_2: - case TARGET_AREAEFFECT_PARTY: - case TARGET_ALL_RAID_AROUND_CASTER: - case TARGET_AREAEFFECT_PARTY_AND_CLASS: - return true; - default: - break; - } - return false; -} - -inline bool IsAreaEffectTarget( Targets target ) -{ - switch (target ) - { - case TARGET_AREAEFFECT_INSTANT: - case TARGET_AREAEFFECT_CUSTOM: - case TARGET_ALL_ENEMY_IN_AREA: - case TARGET_ALL_ENEMY_IN_AREA_INSTANT: - case TARGET_ALL_PARTY_AROUND_CASTER: - case TARGET_IN_FRONT_OF_CASTER: - case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: - case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: - case TARGET_ALL_FRIENDLY_UNITS_IN_AREA: - case TARGET_ALL_PARTY: - case TARGET_ALL_PARTY_AROUND_CASTER_2: - case TARGET_AREAEFFECT_PARTY: - case TARGET_AREAEFFECT_GO_AROUND_DEST: - case TARGET_ALL_RAID_AROUND_CASTER: - case TARGET_AREAEFFECT_PARTY_AND_CLASS: - return true; - default: - break; - } - return false; -} - -inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_AOE; -} - -inline bool IsAreaAuraEffect(uint32 effect) -{ - return - effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || - effect == SPELL_EFFECT_APPLY_AREA_AURA_PET || - // Post-vanilla mais bien utile desfois. - effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID || - effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || - effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND ; -} - -inline bool HasAreaAuraEffect(SpellEntry const *spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_AOE_AURA; -} - -inline bool HasAuraWithTriggerEffect(SpellEntry const *spellInfo) -{ - for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - switch(spellInfo->EffectApplyAuraName[i]) - { - case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - case SPELL_AURA_PROC_TRIGGER_SPELL: - case SPELL_AURA_PROC_TRIGGER_DAMAGE: - return true; - } - } - return false; -} - -inline bool HasAuraWithSpellTriggerEffect(SpellEntry const *spellInfo) -{ - for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - switch (spellInfo->EffectApplyAuraName[i]) - { - case SPELL_AURA_PROC_TRIGGER_SPELL: - return true; - } - } - return false; -} - -inline bool IsDismountSpell(SpellEntry const *spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_DISMOUNT; -} - -inline bool IsCharmSpell(SpellEntry const *spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_CHARM; -} - -inline bool IsDispelSpell(SpellEntry const *spellInfo) -{ - return IsSpellHaveEffect(spellInfo, SPELL_EFFECT_DISPEL); -} - -inline bool IsAutoRepeatRangedSpell(SpellEntry const* spellInfo) -{ - return (spellInfo->Attributes & SPELL_ATTR_RANGED) && (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG); -} - -inline bool IsSpellRequiresRangedAP(SpellEntry const* spellInfo) -{ - return (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE); -} - -SpellCastResult GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form); - -inline bool IsChanneledSpell(SpellEntry const* spellInfo) -{ - return (spellInfo->AttributesEx & (SPELL_ATTR_EX_CHANNELED_1 | SPELL_ATTR_EX_CHANNELED_2)); -} - -inline bool IsNeedCastSpellAtFormApply(SpellEntry const* spellInfo, ShapeshiftForm form) -{ - if (!(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | SPELL_ATTR_HIDDEN_CLIENTSIDE)) || !form) - return false; - - // passive spells with SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT are already active without shapeshift, do no recast! - // Feline Swiftness Passive 2a not have 0x1 mask in Stance field in spell data as expected - return ((spellInfo->Stances & (1<<(form-1)) || spellInfo->Id == 24864 && form == FORM_CAT) && - !(spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT)); -} - -inline bool IsReflectableSpell(SpellEntry const* spellInfo) -{ - return spellInfo->Internal & SPELL_INTERNAL_REFLECTABLE; -} - -inline bool IsReflectableSpell(SpellEntry const* spellInfo, Unit* caster, Unit* victim) -{ - return spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !spellInfo->HasAttribute(SPELL_ATTR_IS_ABILITY) - && !spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_BE_REFLECTED) && !spellInfo->HasAttribute(SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) - && !spellInfo->HasAttribute(SPELL_ATTR_PASSIVE) && !IsPositiveSpell(spellInfo, caster, victim); -} - -inline bool NeedsComboPoints(SpellEntry const* spellInfo) -{ - return (spellInfo->AttributesEx & (SPELL_ATTR_EX_REQ_TARGET_COMBO_POINTS | SPELL_ATTR_EX_REQ_COMBO_POINTS)); -} - -inline bool IsTotemSummonSpell(SpellEntry const* spellInfo) -{ - return spellInfo->Effect[0] >= SPELL_EFFECT_SUMMON_TOTEM_SLOT1 && spellInfo->Effect[0] <= SPELL_EFFECT_SUMMON_TOTEM_SLOT4; -} - -inline bool HasRealTimeDuration(SpellEntry const* spellInfo) -{ - return spellInfo->AttributesEx4 & SPELL_ATTR_EX4_REAL_TIME_DURATION; -} - -// Spell effects require a specific power type on the target -inline bool IsTargetPowerTypeValid(SpellEntry const *spellInfo, Powers powerType) -{ - for (int i = 0; i < MAX_EFFECT_INDEX; ++i) - { - if (spellInfo->Effect[i] == SPELL_EFFECT_NONE) - continue; - - if ((spellInfo->Effect[i] == SPELL_EFFECT_POWER_BURN || - spellInfo->Effect[i] == SPELL_EFFECT_POWER_DRAIN || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_PERIODIC_MANA_LEECH || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_POWER_BURN_MANA) && - int32(powerType) != spellInfo->EffectMiscValue[i]) - { - continue; - } - return true; - } - return false; -} - -inline bool IsRemovedOnShapeLostSpell(SpellEntry const *spellInfo) -{ - return (spellInfo->Stances || spellInfo->Id == 24864) && - !(spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && - !(spellInfo->Attributes & SPELL_ATTR_NOT_SHAPESHIFT); -} - -inline SpellSchoolMask GetSpellSchoolMask(SpellEntry const* spellInfo) -{ - return GetSchoolMask(spellInfo->School); -} - -inline uint32 GetSpellMechanicMask(SpellEntry const* spellInfo, uint32 effectMask) -{ - uint32 mask = 0; - if (spellInfo->Mechanic) - mask |= 1 << (spellInfo->Mechanic - 1); - - for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - if (!(effectMask & (1 << i))) - continue; - - if (spellInfo->EffectMechanic[i]) - mask |= 1 << (spellInfo->EffectMechanic[i]-1); - } - - return mask; -} - -inline Mechanics GetEffectMechanic(SpellEntry const* spellInfo, SpellEffectIndex effect) -{ - if (spellInfo->EffectMechanic[effect]) - return Mechanics(spellInfo->EffectMechanic[effect]); - if (spellInfo->Mechanic) - return Mechanics(spellInfo->Mechanic); - return MECHANIC_NONE; -} - -inline uint32 GetDispellMask(DispelType dispel) -{ - // If dispell all - if (dispel == DISPEL_ALL) - return DISPEL_ALL_MASK; - else - return (1 << dispel); -} // Spell affects related declarations (accessed using SpellMgr functions) typedef std::map SpellAffectMap; diff --git a/src/game/Threat/HostileRefManager.cpp b/src/game/Threat/HostileRefManager.cpp index a1eb868c6..b086d5d14 100644 --- a/src/game/Threat/HostileRefManager.cpp +++ b/src/game/Threat/HostileRefManager.cpp @@ -66,7 +66,7 @@ void HostileRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry co HostileReference* ref = getFirst(); while (ref) { - ref->getSource()->addThreat(pVictim, threat, false, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell, true); + ref->getSource()->addThreat(pVictim, threat, false, (pThreatSpell ? pThreatSpell->GetSpellSchoolMask() : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell, true); ref = ref->next(); } diff --git a/src/game/UnitAuraProcHandler.cpp b/src/game/UnitAuraProcHandler.cpp index b71a42bad..0bd872024 100644 --- a/src/game/UnitAuraProcHandler.cpp +++ b/src/game/UnitAuraProcHandler.cpp @@ -284,7 +284,7 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, SpellAuraHolder* holder, S if (spellProto->Id == 25906) { // Should be able to proc when negative magical effect lands on a target. - if (!isVictim && (procSpell->DmgClass == SPELL_DAMAGE_CLASS_MAGIC) && !IsPositiveSpell(procSpell) && (procExtra & (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT)) && !(IsSpellAppliesAura(procSpell) && (procFlag & PROC_FLAG_ON_DO_PERIODIC))) + if (!isVictim && (procSpell->DmgClass == SPELL_DAMAGE_CLASS_MAGIC) && !procSpell->IsPositiveSpell() && (procExtra & (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT)) && !(procSpell->IsSpellAppliesAura() && (procFlag & PROC_FLAG_ON_DO_PERIODIC))) return roll_chance_f((float)spellProto->procChance); } #if SUPPORTED_CLIENT_BUILD <= CLIENT_BUILD_1_10_2 @@ -636,7 +636,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura if (!found) return SPELL_AURA_PROC_FAILED; - switch (GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) + switch (GetFirstSchoolInMask(procSpell->GetSpellSchoolMask())) { case SPELL_SCHOOL_NORMAL: case SPELL_SCHOOL_HOLY: @@ -669,7 +669,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura if (!procSpell) return SPELL_AURA_PROC_FAILED; - switch (GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) + switch (GetFirstSchoolInMask(procSpell->GetSpellSchoolMask())) { case SPELL_SCHOOL_NORMAL: return SPELL_AURA_PROC_FAILED; // ignore @@ -1549,7 +1549,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit *pVictim, uint32 d } // not allow proc extra attack spell at extra attack - if (m_extraAttacks && IsSpellHaveEffect(triggerEntry, SPELL_EFFECT_ADD_EXTRA_ATTACKS) && triggerEntry->Id != 20178) + if (m_extraAttacks && triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS) && triggerEntry->Id != 20178) return SPELL_AURA_PROC_FAILED; // Custom basepoints/target for exist spell @@ -1590,7 +1590,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit *pVictim, uint32 d // try detect target manually if not set if (target == NULL) - target = !(procFlags & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL) && IsPositiveSpell(trigger_spell_id) ? this : pVictim; + target = !(procFlags & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL) && Spells::IsPositiveSpell(trigger_spell_id) ? this : pVictim; // default case if (!target || target != this && !target->isAlive()) @@ -1707,7 +1707,7 @@ SpellAuraProcResult Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint3 case 3656: // Corrupted Healing { // only proc on direct healing - if (IsSpellHaveEffect(procSpell, SPELL_EFFECT_HEAL)) + if (procSpell->HasEffect(SPELL_EFFECT_HEAL)) triggered_spell_id = 23402; break; } @@ -1766,7 +1766,7 @@ SpellAuraProcResult Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint3 SpellAuraProcResult Unit::HandleModCastingSpeedNotStackAuraProc(Unit* /*pVictim*/, uint32 /*damage*/, Aura* /*triggeredByAura*/, SpellEntry const* procSpell, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 /*cooldown*/) { // Skip melee hits or instant cast spells - return !(procSpell == NULL || GetSpellCastTime(procSpell) == 0) ? SPELL_AURA_PROC_OK : SPELL_AURA_PROC_FAILED; + return !(procSpell == NULL || procSpell->GetCastTime() == 0) ? SPELL_AURA_PROC_OK : SPELL_AURA_PROC_FAILED; } SpellAuraProcResult Unit::HandleReflectSpellsSchoolAuraProc(Unit* /*pVictim*/, uint32 /*damage*/, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 /*cooldown*/) diff --git a/src/shared/Util.h b/src/shared/Util.h index 05f58ed34..a3c183851 100644 --- a/src/shared/Util.h +++ b/src/shared/Util.h @@ -110,12 +110,14 @@ inline bool roll_chance_f(float chance) { return chance > rand_chance(); } - -/* Return true if a random roll fits in the specified chance (range 0-100). */ inline bool roll_chance_i(int chance) { return chance > irand(0, 99); } +inline bool roll_chance_u(uint32 chance) +{ + return chance > urand(0, 99); +} inline void ApplyModUInt32Var(uint32& var, int32 val, bool apply) {