diff options
Diffstat (limited to 'src')
137 files changed, 4617 insertions, 3206 deletions
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index e808f91db55..b6d15a9632c 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -181,7 +181,7 @@ void PetAI::UpdateAI(uint32 diff) } } - if (spellInfo->HasEffect(SPELL_EFFECT_JUMP_DEST)) + if (spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_JUMP_DEST)) { if (!spellUsed) delete spell; diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index 33772c2c165..08832f73295 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -227,9 +227,12 @@ void UnitAI::FillAISpellInfo() UPDATE_TARGET(AITARGET_SELF) else { - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - uint32 targetType = spellInfo->Effects[j].TargetA.GetTarget(); + if (!effect) + continue; + + uint32 targetType = effect->TargetA.GetTarget(); if (targetType == TARGET_UNIT_TARGET_ENEMY || targetType == TARGET_DEST_TARGET_ENEMY) @@ -237,7 +240,7 @@ void UnitAI::FillAISpellInfo() else if (targetType == TARGET_UNIT_DEST_AREA_ENEMY) UPDATE_TARGET(AITARGET_ENEMY) - if (spellInfo->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA) + if (effect->Effect == SPELL_EFFECT_APPLY_AURA) { if (targetType == TARGET_UNIT_TARGET_ENEMY) UPDATE_TARGET(AITARGET_DEBUFF) @@ -282,7 +285,7 @@ void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) } SpellTargetSelector::SpellTargetSelector(Unit* caster, uint32 spellId) : - _caster(caster), _spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(sSpellMgr->GetSpellInfo(spellId), caster)) + _caster(caster), _spellInfo(sSpellMgr->GetSpellInfo(spellId)) { ASSERT(_spellInfo); } diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 5bf3c41df41..6d8e5d67ebb 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -282,9 +282,9 @@ struct ScriptedAI : public CreatureAI { switch (_difficulty) { - case DUNGEON_DIFFICULTY_NORMAL: + case DIFFICULTY_NORMAL: return normal5; - case DUNGEON_DIFFICULTY_HEROIC: + case DIFFICULTY_HEROIC: return heroic10; default: break; @@ -298,9 +298,9 @@ struct ScriptedAI : public CreatureAI { switch (_difficulty) { - case RAID_DIFFICULTY_10MAN_NORMAL: + case DIFFICULTY_10_N: return normal10; - case RAID_DIFFICULTY_25MAN_NORMAL: + case DIFFICULTY_25_N: return normal25; default: break; @@ -314,13 +314,13 @@ struct ScriptedAI : public CreatureAI { switch (_difficulty) { - case RAID_DIFFICULTY_10MAN_NORMAL: + case DIFFICULTY_10_N: return normal10; - case RAID_DIFFICULTY_25MAN_NORMAL: + case DIFFICULTY_25_N: return normal25; - case RAID_DIFFICULTY_10MAN_HEROIC: + case DIFFICULTY_10_HC: return heroic10; - case RAID_DIFFICULTY_25MAN_HEROIC: + case DIFFICULTY_25_HC: return heroic25; default: break; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index cc7864f1f4e..d1a590e24b1 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -823,13 +823,13 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT2)) + if (effect && (effect->IsEffect(SPELL_EFFECT_KILL_CREDIT) || effect->IsEffect(SPELL_EFFECT_KILL_CREDIT2))) { - if (spellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER) + if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry " SI64FMTD " SourceType %u Event %u Action %u Effect: SPELL_EFFECT_KILL_CREDIT: (SpellId: %u targetA: %u - targetB: %u) has invalid target for this Action", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.cast.spell, spellInfo->Effects[j].TargetA.GetTarget(), spellInfo->Effects[j].TargetB.GetTarget()); + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.cast.spell, effect->TargetA.GetTarget(), effect->TargetB.GetTarget()); } } break; @@ -1277,19 +1277,22 @@ void SmartAIMgr::LoadHelperStores() if (!spellInfo) continue; - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_SUMMON)) - SummonCreatureSpellStore.insert(std::make_pair(uint32(spellInfo->Effects[j].MiscValue), std::make_pair(i, SpellEffIndex(j)))); + if (!effect) + continue; + + if (effect->IsEffect(SPELL_EFFECT_SUMMON)) + SummonCreatureSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(i, SpellEffIndex(effect->EffectIndex)))); - else if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_SUMMON_OBJECT_WILD)) - SummonGameObjectSpellStore.insert(std::make_pair(uint32(spellInfo->Effects[j].MiscValue), std::make_pair(i, SpellEffIndex(j)))); + else if (effect->IsEffect(SPELL_EFFECT_SUMMON_OBJECT_WILD)) + SummonGameObjectSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(i, SpellEffIndex(effect->EffectIndex)))); - else if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT2)) - KillCreditSpellStore.insert(std::make_pair(uint32(spellInfo->Effects[j].MiscValue), std::make_pair(i, SpellEffIndex(j)))); + else if (effect->IsEffect(SPELL_EFFECT_KILL_CREDIT) || effect->IsEffect(SPELL_EFFECT_KILL_CREDIT2)) + KillCreditSpellStore.insert(std::make_pair(uint32(effect->MiscValue), std::make_pair(i, SpellEffIndex(effect->EffectIndex)))); - else if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_CREATE_ITEM)) - CreateItemSpellStore.insert(std::make_pair(uint32(spellInfo->Effects[j].ItemType), std::make_pair(i, SpellEffIndex(j)))); + else if (effect->IsEffect(SPELL_EFFECT_CREATE_ITEM)) + CreateItemSpellStore.insert(std::make_pair(uint32(effect->ItemType), std::make_pair(i, SpellEffIndex(effect->EffectIndex)))); } } diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 8fe96be26fb..a55ee01e787 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -138,13 +138,14 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id); return false; } - if (aura.effect_idx >= 3) + SpellEffectInfo const* effect = spellEntry->GetEffect(DIFFICULTY_NONE, aura.effect_idx); + if (!effect) { TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has wrong spell effect index in value2 (%u), ignored.", criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.effect_idx); return false; } - if (!spellEntry->Effects[aura.effect_idx].ApplyAuraName) + if (!effect->ApplyAuraName) { TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has non-aura spell effect (ID: %u Effect: %u), ignores.", criteria->ID, criteria->type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id, aura.effect_idx); @@ -2533,7 +2534,7 @@ bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const* ac if (!achievIdForDungeon[j][2]) break; // for } - else if (referencePlayer->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL) + else if (referencePlayer->GetDungeonDifficulty() == DIFFICULTY_NORMAL) { // dungeon in normal mode accepted if (!achievIdForDungeon[j][1]) diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index 85510ab0545..cd1e3d5be95 100644 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -41,8 +41,8 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float threat *= threatEntry->pctMod; // Energize is not affected by Mods - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) - if (threatSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE || threatSpell->Effects[i].ApplyAuraName == SPELL_AURA_PERIODIC_ENERGIZE) + for (SpellEffectInfo const* effect : threatSpell->GetEffectsForDifficulty(hatedUnit->GetMap()->GetDifficulty())) + if (effect && (effect->Effect == SPELL_EFFECT_ENERGIZE || effect->ApplyAuraName == SPELL_AURA_PERIODIC_ENERGIZE)) return threat; if (Player* modOwner = hatedUnit->GetSpellModOwner()) diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index b8ff56f94ca..654451af949 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1231,6 +1231,9 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) std::list<uint32> sharedMasks; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { + SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, i); + if (!effect) + continue; // check if effect is already a part of some shared mask bool found = false; for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr) @@ -1245,12 +1248,15 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) continue; // build new shared mask with found effect - uint32 sharedMask = (1 << i); - ConditionList* cmp = spellInfo->Effects[i].ImplicitTargetConditions; + uint32 sharedMask = (1<<i); + ConditionList* cmp = effect->ImplicitTargetConditions; for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex) { - if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp) - sharedMask |= 1 << effIndex; + SpellEffectInfo const* inner = spellInfo->GetEffect(DIFFICULTY_NONE, effIndex); + if (!inner) + continue; + if (inner->ImplicitTargetConditions == cmp) + sharedMask |= 1<<effIndex; } sharedMasks.push_back(sharedMask); } @@ -1268,8 +1274,12 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) if (firstEffIndex >= MAX_SPELL_EFFECTS) return false; + SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, firstEffIndex); + if (!effect) + continue; + // get shared data - ConditionList* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions; + ConditionList* sharedList = effect->ImplicitTargetConditions; // there's already data entry for that sharedMask if (sharedList) @@ -1290,9 +1300,13 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) bool assigned = false; for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i) { + SpellEffectInfo const* eff = spellInfo->GetEffect(DIFFICULTY_NONE, firstEffIndex); + if (!eff) + continue; + if ((1<<i) & commonMask) { - spellInfo->Effects[i].ImplicitTargetConditions = sharedList; + const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = sharedList; assigned = true; } } @@ -1543,7 +1557,11 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) if (!((1 << i) & cond->SourceGroup)) continue; - switch (spellInfo->Effects[i].TargetA.GetSelectionCategory()) + SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, i); + if (!effect) + continue; + + switch (effect->TargetA.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: @@ -1553,7 +1571,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) break; } - switch (spellInfo->Effects[i].TargetB.GetSelectionCategory()) + switch (effect->TargetB.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_NEARBY: case TARGET_SELECT_CATEGORY_CONE: diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp index a7cf8478704..65c5ec6873a 100644 --- a/src/server/game/Conditions/DisableMgr.cpp +++ b/src/server/game/Conditions/DisableMgr.cpp @@ -134,11 +134,11 @@ void LoadDisables() break; case MAP_INSTANCE: case MAP_RAID: - if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DUNGEON_DIFFICULTY_HEROIC)) + if (flags & DUNGEON_STATUSFLAG_HEROIC && !GetMapDifficultyData(entry, DIFFICULTY_HEROIC)) flags -= DUNGEON_STATUSFLAG_HEROIC; - if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_10MAN_HEROIC)) + if (flags & RAID_STATUSFLAG_10MAN_HEROIC && !GetMapDifficultyData(entry, DIFFICULTY_10_HC)) flags -= RAID_STATUSFLAG_10MAN_HEROIC; - if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, RAID_DIFFICULTY_25MAN_HEROIC)) + if (flags & RAID_STATUSFLAG_25MAN_HEROIC && !GetMapDifficultyData(entry, DIFFICULTY_25_HC)) flags -= RAID_STATUSFLAG_25MAN_HEROIC; if (!flags) isFlagInvalid = true; @@ -354,13 +354,13 @@ bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags GetDownscaledMapDifficultyData(entry, targetDifficulty); switch (targetDifficulty) { - case DUNGEON_DIFFICULTY_NORMAL: + case DIFFICULTY_NORMAL: return (disabledModes & DUNGEON_STATUSFLAG_NORMAL) != 0; - case DUNGEON_DIFFICULTY_HEROIC: + case DIFFICULTY_HEROIC: return (disabledModes & DUNGEON_STATUSFLAG_HEROIC) != 0; - case RAID_DIFFICULTY_10MAN_HEROIC: + case DIFFICULTY_10_HC: return (disabledModes & RAID_STATUSFLAG_10MAN_HEROIC) != 0; - case RAID_DIFFICULTY_25MAN_HEROIC: + case DIFFICULTY_25_HC: return (disabledModes & RAID_STATUSFLAG_25MAN_HEROIC) != 0; } } diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 2d3751ccd9e..3c111da8aee 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -39,6 +39,7 @@ DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore(Spell DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore(SpellClassOptionsEntryfmt); DB2Storage<SpellMiscEntry> sSpellMiscStore(SpellMiscEntryfmt); DB2Storage<SpellPowerEntry> sSpellPowerStore(SpellPowerEntryfmt); +SpellPowerBySpellIDMap sSpellPowerBySpellIDStore; DB2Storage<SpellReagentsEntry> sSpellReagentsStore(SpellReagentsEntryfmt); DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostEntryfmt); DB2Storage<SpellTotemsEntry> sSpellTotemsStore(SpellTotemsEntryfmt); @@ -144,6 +145,10 @@ void LoadDB2Stores(std::string const& dataPath) LoadDB2(availableDb2Locales, bad_db2_files, sTaxiPathStore, db2Path, "TaxiPath.db2"); LoadDB2(availableDb2Locales, bad_db2_files, sTaxiPathNodeStore, db2Path, "TaxiPathNode.db2"); + for (uint32 i = 0; i < sSpellPowerStore.GetNumRows(); ++i) + if (SpellPowerEntry const* power = sSpellPowerStore.LookupEntry(i)) + sSpellPowerBySpellIDStore[power->SpellID] = power; + for (uint32 i = 0; i < sPhaseGroupStore.GetNumRows(); ++i) if (PhaseGroupEntry const* group = sPhaseGroupStore.LookupEntry(i)) if (PhaseEntry const* phase = sPhaseStore.LookupEntry(group->PhaseID)) diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 4294636b138..6521ea930a8 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -39,6 +39,7 @@ extern DB2Storage<SpellCastingRequirementsEntry> sSpellCastingRequirementsStore; extern DB2Storage<SpellClassOptionsEntry> sSpellClassOptionsStore; extern DB2Storage<SpellMiscEntry> sSpellMiscStore; extern DB2Storage<SpellPowerEntry> sSpellPowerStore; +extern SpellPowerBySpellIDMap sSpellPowerBySpellIDStore; extern DB2Storage<SpellReagentsEntry> sSpellReagentsStore; extern DB2Storage<SpellRuneCostEntry> sSpellRuneCostStore; extern DB2Storage<SpellTotemsEntry> sSpellTotemsStore; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index e720017b09d..8e91ec8396f 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -354,6 +354,8 @@ struct TaxiPathNodeEntry typedef std::map<uint32, uint32> ItemDisplayIDMap; +typedef std::map<uint32, SpellPowerEntry const*> SpellPowerBySpellIDMap; + struct TaxiPathBySourceAndDestination { TaxiPathBySourceAndDestination() : ID(0), price(0) { } diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 19b3c54f6a8..fa1ca29f4ef 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -337,16 +337,26 @@ enum AreaFlags enum Difficulty { - REGULAR_DIFFICULTY = 0, - - DUNGEON_DIFFICULTY_NORMAL = 0, - DUNGEON_DIFFICULTY_HEROIC = 1, - DUNGEON_DIFFICULTY_EPIC = 2, - - RAID_DIFFICULTY_10MAN_NORMAL = 0, - RAID_DIFFICULTY_25MAN_NORMAL = 1, - RAID_DIFFICULTY_10MAN_HEROIC = 2, - RAID_DIFFICULTY_25MAN_HEROIC = 3 + DIFFICULTY_NONE = 0, + DIFFICULTY_NORMAL = 1, + DIFFICULTY_HEROIC = 2, + DIFFICULTY_10_N = 3, + DIFFICULTY_25_N = 4, + DIFFICULTY_10_HC = 5, + DIFFICULTY_25_HC = 6, + DIFFICULTY_LFR = 7, + DIFFICULTY_CHALLENGE = 8, + DIFFICULTY_40 = 9, + DIFFICULTY_HC_SCENARIO = 11, + DIFFICULTY_N_SCENARIO = 12, + DIFFICULTY_NORMAL2 = 14, + DIFFICULTY_HEROIC2 = 15, + DIFFICULTY_MYTHIC = 16, + DIFFICULTY_LFR2 = 17, + DIFFICULTY_EVENT = 18, + DIFFICULTY_EVENT2 = 19, + DIFFICULTY_EVENT_SCENARIO = 20, + DIFFICULTY_MAX = 21, }; #define RAID_DIFFICULTY_MASK_25MAN 1 // since 25man difficulties are 1 and 3, we can check them like that @@ -357,18 +367,18 @@ enum Difficulty enum SpawnMask { - SPAWNMASK_CONTINENT = (1 << REGULAR_DIFFICULTY), // any maps without spawn modes + SPAWNMASK_CONTINENT = (1 << DIFFICULTY_NONE), // any maps without spawn modes - SPAWNMASK_DUNGEON_NORMAL = (1 << DUNGEON_DIFFICULTY_NORMAL), - SPAWNMASK_DUNGEON_HEROIC = (1 << DUNGEON_DIFFICULTY_HEROIC), + SPAWNMASK_DUNGEON_NORMAL = (1 << DIFFICULTY_NORMAL), + SPAWNMASK_DUNGEON_HEROIC = (1 << DIFFICULTY_HEROIC), SPAWNMASK_DUNGEON_ALL = (SPAWNMASK_DUNGEON_NORMAL | SPAWNMASK_DUNGEON_HEROIC), - SPAWNMASK_RAID_10MAN_NORMAL = (1 << RAID_DIFFICULTY_10MAN_NORMAL), - SPAWNMASK_RAID_25MAN_NORMAL = (1 << RAID_DIFFICULTY_25MAN_NORMAL), + SPAWNMASK_RAID_10MAN_NORMAL = (1 << DIFFICULTY_10_N), + SPAWNMASK_RAID_25MAN_NORMAL = (1 << DIFFICULTY_25_N), SPAWNMASK_RAID_NORMAL_ALL = (SPAWNMASK_RAID_10MAN_NORMAL | SPAWNMASK_RAID_25MAN_NORMAL), - SPAWNMASK_RAID_10MAN_HEROIC = (1 << RAID_DIFFICULTY_10MAN_HEROIC), - SPAWNMASK_RAID_25MAN_HEROIC = (1 << RAID_DIFFICULTY_25MAN_HEROIC), + SPAWNMASK_RAID_10MAN_HEROIC = (1 << DIFFICULTY_10_HC), + SPAWNMASK_RAID_25MAN_HEROIC = (1 << DIFFICULTY_25_HC), SPAWNMASK_RAID_HEROIC_ALL = (SPAWNMASK_RAID_10MAN_HEROIC | SPAWNMASK_RAID_25MAN_HEROIC), SPAWNMASK_RAID_ALL = (SPAWNMASK_RAID_NORMAL_ALL | SPAWNMASK_RAID_HEROIC_ALL) diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 325a1d9a6db..ecff4836416 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -20,6 +20,7 @@ #include "Containers.h" #include "Log.h" #include "SharedDefines.h" +#include "SpellInfo.h" #include "SpellMgr.h" #include "TransportMgr.h" #include "DBCfmt.h" @@ -191,8 +192,13 @@ DBCStorage <SpecializationSpellsEntry> sSpecializationSpellsStore(Specialization DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore(SpellItemEnchantmentfmt); DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt); DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt); +DBCStorage <SpellEffectScalingEntry> sSpellEffectScalingStore(SpellEffectScalingfmt); + SpellCategoryStore sSpellsByCategoryStore; PetFamilySpellsStore sPetFamilySpellsStore; +SpellsPerClassStore sSpellsPerClassStore; +ClassBySkillIdStore sClassBySkillIdStore; +SpellEffectScallingByEffectId sSpellEffectScallingByEffectId; DBCStorage <SpellScalingEntry> sSpellScalingStore(SpellScalingEntryfmt); @@ -216,6 +222,8 @@ DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt); DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt); TalentBySpellIDMap sTalentBySpellIDMap; +SpecializationSpellsMap sSpecializationSpellsMap; +SpecializationOverrideSpellsMap sSpecializationOverrideSpellMap; DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt); DBCStorage <TransportAnimationEntry> sTransportAnimationStore(TransportAnimationfmt); @@ -510,7 +518,10 @@ void LoadDBCStores(const std::string& dataPath) SpecializationSpellsEntry const* specSpells = sSpecializationSpellsStore.LookupEntry(i); if (!specSpells) continue; - sSpecializationSpellsBySpecStore[specSpells->SpecID].insert(specSpells); + sSpecializationSpellsBySpecStore[specSpells->SpecID].push_back(specSpells); + + if (specSpells->OverridesSpellID) + sSpecializationOverrideSpellMap[specSpells->SpecID][specSpells->OverridesSpellID] = specSpells->SpellID; } LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc"/*, &CustomSpellEntryfmt, &CustomSpellEntryIndex*/); LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoriesStore, dbcPath, "SpellCategories.dbc");//15595 @@ -536,6 +547,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCastTimesStore, dbcPath, "SpellCastTimes.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sSpellDurationStore, dbcPath, "SpellDuration.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sSpellFocusObjectStore, dbcPath, "SpellFocusObject.dbc");//19116 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellEffectScalingStore, dbcPath, "SpellEffectScaling.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentStore, dbcPath, "SpellItemEnchantment.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sSpellItemEnchantmentConditionStore, dbcPath, "SpellItemEnchantmentCondition.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sSpellRadiusStore, dbcPath, "SpellRadius.dbc");//19116 @@ -545,41 +557,67 @@ void LoadDBCStores(const std::string& dataPath) //LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");//15595 - // Must be done when sSkillLineAbilityStore, sSpellStore, sSpellLevelsStore and sCreatureFamilyStore are all loaded - /* TODO: Requires spells attributes from SpellMisc.db2 is loaded after dbc + for (uint32 j = 0; j < sSpellEffectScalingStore.GetNumRows(); j++) + { + SpellEffectScalingEntry const* spellEffectScaling = sSpellEffectScalingStore.LookupEntry(j); + if (!spellEffectScaling) + continue; + + sSpellEffectScallingByEffectId.insert(std::make_pair(spellEffectScaling->SpellEffectID, j)); + } + std::map<std::string, uint32> classIdByName; + for (uint32 j = 0; j < sChrClassesStore.GetNumRows(); j++) + { + ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(j); + if (!classEntry) + continue; + + classIdByName.insert(std::make_pair(std::string(classEntry->Name_lang), j)); + } + + for (uint32 j = 0; j < sSkillLineStore.GetNumRows(); j++) + { + SkillLineEntry const* skillEntry = sSkillLineStore.LookupEntry(j); + if (!skillEntry) + continue; + + if (skillEntry->CategoryID!= SKILL_CATEGORY_CLASS) + continue; + + std::map<std::string, uint32> ::const_iterator iter = classIdByName.find(std::string(skillEntry->DisplayName_lang)); + if (iter == classIdByName.end()) + continue; + + sClassBySkillIdStore.insert(std::make_pair(j, iter->second)); + } + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { - SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j); - if (!skillLine) + SkillLineAbilityEntry const* skillAbility = sSkillLineAbilityStore.LookupEntry(j); + if (!skillAbility) continue; - SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->SpellID); + if (skillAbility->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillAbility->SpellID); if (!spellInfo) continue; - SpellLevelsEntry const* levels = sSpellLevelsStore.LookupEntry(spellInfo->SpellLevelsID); - if (spellInfo->SpellLevelsID && (!levels || levels->spellLevel)) + SpellLevelsEntry const* spellLevels = sSpellLevelsStore.LookupEntry(spellInfo->LevelsID); + if (!spellLevels || !spellLevels->SpellLevel) continue; - if (spellInfo && spellInfo->Attributes & SPELL_ATTR0_PASSIVE) - { - for (uint32 i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i) - { - CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i); - if (!cFamily) - continue; + uint32 classId = GetClassBySkillId(skillAbility->SkillLine); - if (skillLine->SkillLine != cFamily->SkillLine[0] && skillLine->SkillLine != cFamily->SkillLine[1]) - continue; + if (!classId) + continue; - if (skillLine->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) - continue; + if (sSpellsPerClassStore.find(classId) == sSpellsPerClassStore.end()) + sSpellsPerClassStore.insert(make_pair(classId, std::list<SkillLineAbilityEntry const*>())); - sPetFamilySpellsStore[i].insert(spellInfo->ID); - } - } + sSpellsPerClassStore[classId].push_back(skillAbility); } - */ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");//15595 @@ -889,7 +927,7 @@ MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &di MapDifficulty const* mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); if (!mapDiff) { - if (tmpDiff > RAID_DIFFICULTY_25MAN_NORMAL) // heroic, downscale to normal + if (tmpDiff > DIFFICULTY_25_N) // heroic, downscale to normal tmpDiff -= 2; else tmpDiff -= 1; // any non-normal mode for raids like tbc (only one mode) @@ -1170,3 +1208,82 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u return NULL; } + +uint32 GetClassBySkillId(uint32 skillId) +{ + ClassBySkillIdStore::const_iterator iter = sClassBySkillIdStore.find(skillId); + if (iter != sClassBySkillIdStore.end()) + return iter->second; + return 0; +} + +uint32 GetSkillIdByClass(uint32 classId) +{ + for (ClassBySkillIdStore::const_iterator iter = sClassBySkillIdStore.begin(); iter != sClassBySkillIdStore.end(); iter++) + if (iter->second == classId) + return iter->first; + return 0; +} + +std::list<uint32> GetSpellsForLevels(uint32 classId, uint32 raceMask, uint32 specializationId, uint32 minLevel, uint32 maxLevel) +{ + std::list<uint32> spellList; + + if (classId != 0) + { + SpellsPerClassStore::const_iterator classIter = sSpellsPerClassStore.find(classId); + if (classIter != sSpellsPerClassStore.end()) + { + const std::list<SkillLineAbilityEntry const*>& learnSpellList = classIter->second; + for (std::list<SkillLineAbilityEntry const*>::const_iterator iter = learnSpellList.begin(); iter != learnSpellList.end(); iter++) + { + SkillLineAbilityEntry const* skillLine = *iter; + if (!skillLine) + continue; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(skillLine->SpellID); + if (!spellInfo) + continue; + + if (skillLine->RaceMask && !(skillLine->RaceMask & raceMask)) + continue; + + if (spellInfo->SpellLevel <= minLevel || spellInfo->SpellLevel > maxLevel) + continue; + + spellList.push_back(spellInfo->Id); + } + } + } + + if (!specializationId) + return spellList; + + SpecializationSpellsBySpecStore::const_iterator specIter = sSpecializationSpellsBySpecStore.find(specializationId); + if (specIter != sSpecializationSpellsBySpecStore.end()) + { + SpecializationSpellsBySpecEntry learnSpellList = specIter->second; + for (int i = 0; i < learnSpellList.size(); i++) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(learnSpellList[i]->SpellID); + if (!spellInfo) + { + TC_LOG_ERROR("spells", "GetSpellsForLevels: spell %u not found in spellstore", learnSpellList[i]->SpellID); + continue; + } + if (spellInfo->SpellLevel <= minLevel || spellInfo->SpellLevel > maxLevel) + continue; + + spellList.push_back(spellInfo->Id); + } + } + return spellList; +} + +uint32 GetTalentSpellCost(uint32 spellId) +{ + TalentBySpellIDMap::const_iterator itr = sTalentBySpellIDMap.find(spellId); + if (itr == sTalentBySpellIDMap.end()) + return 0; + return 1; +}
\ No newline at end of file diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 5bbccf830d6..633376d85aa 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -26,11 +26,14 @@ #include <list> +typedef std::map<uint32, uint32> SpecializationOverrideSpellsList; +typedef std::map<uint32, SpecializationOverrideSpellsList> SpecializationOverrideSpellsMap; + typedef std::list<uint32> SimpleFactionsList; SimpleFactionsList const* GetFactionTeamList(uint32 faction); char const* GetPetName(uint32 petfamily, uint32 dbclang); - +uint32 GetTalentSpellCost(uint32 spellId); TalentEntry const* GetTalentBySpellID(uint32 spellID); int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found @@ -66,6 +69,9 @@ bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredT void Zone2MapCoordinates(float &x, float &y, uint32 zone); void Map2ZoneCoordinates(float &x, float &y, uint32 zone); +uint32 GetClassBySkillId(uint32 skillId); +uint32 GetSkillIdByClass(uint32 classId); +std::list<uint32> GetSpellsForLevels(uint32 classId, uint32 raceMask, uint32 specializationId, uint32 minLevel, uint32 maxLevel); typedef std::map<uint32/*pair32(map, diff)*/, MapDifficulty> MapDifficultyMap; MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty); @@ -87,11 +93,14 @@ typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRac typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds; SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); -typedef std::set<SpecializationSpellsEntry const*> SpecializationSpellsBySpecEntry; +typedef std::vector<SpecializationSpellsEntry const*> SpecializationSpellsBySpecEntry; typedef std::unordered_map<uint32, SpecializationSpellsBySpecEntry> SpecializationSpellsBySpecStore; typedef ChrSpecializationEntry const* ChrSpecializationByIndexArray[MAX_CLASSES][MAX_SPECIALIZATIONS]; typedef std::unordered_map<uint32, TalentEntry const*> TalentBySpellIDMap; +typedef std::map<uint32, std::vector<uint32> > SpecializationSpellsMap; +extern SpecializationSpellsMap sSpecializationSpellsMap; +extern SpecializationOverrideSpellsMap sSpecializationOverrideSpellMap; extern DBCStorage <AchievementEntry> sAchievementStore; extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore; extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index f6727221cd9..ee168f2349f 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1800,8 +1800,18 @@ struct SpellEffectEntry float BonusCoefficientFromAP; // 30 }; -#define MAX_SPELL_EFFECTS 3 -#define MAX_EFFECT_MASK 7 +#define MAX_SPELL_EFFECTS 32 +#define MAX_EFFECT_MASK 0xFFFFFFFF + +// SpellEffectScaling.dbc +struct SpellEffectScalingEntry +{ + uint32 ID; // 0 + float Coefficient; // 1 + float Variance; // 2 + float ResourceCoefficient; // 3 + uint32 SpellEffectID; // 4 +}; // SpellAuraOptions.dbc struct SpellAuraOptionsEntry @@ -1865,6 +1875,9 @@ typedef std::set<uint32> SpellCategorySet; typedef std::map<uint32, SpellCategorySet > SpellCategoryStore; typedef std::set<uint32> PetFamilySpellsSet; typedef std::map<uint32, PetFamilySpellsSet > PetFamilySpellsStore; +typedef std::unordered_map<uint32, std::list<SkillLineAbilityEntry const*> > SpellsPerClassStore; +typedef std::unordered_map<uint32, uint32> ClassBySkillIdStore; +typedef std::unordered_map<uint32, uint32> SpellEffectScallingByEffectId; struct SpellCastTimesEntry { diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 9f53cb09ad8..bd0283aee7f 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -135,6 +135,7 @@ const std::string CustomSpellEffectEntryIndex = "Id"; char const SpellEntryfmt[] = "nsxxxiiiiiiiiiiiiiiiiiii"; const std::string CustomSpellEntryfmt = "ppppppppppppppapaaaaaaaaapaaaaaapapppaapppaaapa"; const std::string CustomSpellEntryIndex = "Id"; +char const SpellEffectScalingfmt[] = "nfffi"; char const SpellFocusObjectfmt[] = "nx"; char const SpellItemEnchantmentfmt[] = "niiiiiiiiiixiiiiiiiiiiifff"; char const SpellItemEnchantmentConditionfmt[] = "nbbbbbiiiiibbbbbbbbbbiiiiibbbbb"; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 863324f278c..7099d38d428 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -1406,7 +1406,7 @@ void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId) } // Update achievements - if (dungeon->difficulty == DUNGEON_DIFFICULTY_HEROIC) + if (dungeon->difficulty == DIFFICULTY_HEROIC) player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS, 1); LfgReward const* reward = GetRandomDungeonReward(rDungeonId, player->getLevel()); @@ -1594,7 +1594,7 @@ LfgLockMap const LFGMgr::GetLockedDungeons(ObjectGuid guid) lockStatus = LFG_LOCKSTATUS_INSUFFICIENT_EXPANSION; else if (DisableMgr::IsDisabledFor(DISABLE_TYPE_MAP, dungeon->map, player)) lockStatus = LFG_LOCKSTATUS_RAID_LOCKED; - else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) + else if (dungeon->difficulty > DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) lockStatus = LFG_LOCKSTATUS_RAID_LOCKED; else if (dungeon->minlevel > level) lockStatus = LFG_LOCKSTATUS_TOO_LOW_LEVEL; diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index dea8d996c53..4fbd60202c3 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -268,7 +268,7 @@ struct LfgPlayerBoot struct LFGDungeonData { LFGDungeonData(): id(0), name(""), map(0), type(0), expansion(0), group(0), minlevel(0), - maxlevel(0), difficulty(REGULAR_DIFFICULTY), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f), + maxlevel(0), difficulty(DIFFICULTY_NONE), seasonal(false), x(0.0f), y(0.0f), z(0.0f), o(0.0f), requiredItemLevel(0) { } LFGDungeonData(LFGDungeonEntry const* dbc): id(dbc->ID), name(dbc->Name_lang), map(dbc->MapID), diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 491b1864dda..3cbe4057106 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -284,7 +284,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) } // for instances heroic to normal, other cases attempt to retrieve previous difficulty - if (diff >= RAID_DIFFICULTY_10MAN_HEROIC && GetMap()->IsRaid()) + if (diff >= DIFFICULTY_10_HC && GetMap()->IsRaid()) diff -= 2; // to normal raid difficulty cases else --diff; @@ -1620,11 +1620,11 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo) const // This check must be done instead of 'if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1)))' for not break // the check of mechanic immunity on DB (tested) because GetCreatureTemplate()->MechanicImmuneMask and m_spellImmune[IMMUNITY_MECHANIC] don't have same data. bool immunedToAllEffects = true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if (!spellInfo->Effects[i].IsEffect()) + if (!effect || !effect->IsEffect()) continue; - if (!IsImmunedToSpellEffect(spellInfo, i)) + if (!IsImmunedToSpellEffect(spellInfo, effect->EffectIndex)) { immunedToAllEffects = false; break; @@ -1638,10 +1638,13 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo) const bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const { - if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Effects[index].Mechanic - 1))) + SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty()); + if (!effect) + return true; + if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (effect->Mechanic - 1))) return true; - if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellInfo->Effects[index].Effect == SPELL_EFFECT_HEAL) + if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && effect->Effect == SPELL_EFFECT_HEAL) return true; return Unit::IsImmunedToSpellEffect(spellInfo, index); @@ -1681,13 +1684,13 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) } bool bcontinue = true; - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; j++) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if ((spellInfo->Effects[j].Effect == SPELL_EFFECT_SCHOOL_DAMAGE) || - (spellInfo->Effects[j].Effect == SPELL_EFFECT_INSTAKILL) || - (spellInfo->Effects[j].Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE) || - (spellInfo->Effects[j].Effect == SPELL_EFFECT_HEALTH_LEECH) - ) + if (effect && ((effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) || + (effect->Effect == SPELL_EFFECT_INSTAKILL) || + (effect->Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE) || + (effect->Effect == SPELL_EFFECT_HEALTH_LEECH) + )) { bcontinue = false; break; @@ -1729,9 +1732,9 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim) } bool bcontinue = true; - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; j++) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if ((spellInfo->Effects[j].Effect == SPELL_EFFECT_HEAL)) + if (effect && (effect->Effect == SPELL_EFFECT_HEAL)) { bcontinue = false; break; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index bb8ebfe1567..382bf45052b 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1809,9 +1809,9 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /*= true return; bool self = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER) + if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) { self = true; break; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 0e49852ab7e..b6286eac5bb 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -788,9 +788,9 @@ Player::Player(WorldSession* session): Unit(true) m_HomebindTimer = 0; m_InstanceValid = true; - m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL; - m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL; - m_raidMapDifficulty = RAID_DIFFICULTY_10MAN_NORMAL; + m_dungeonDifficulty = DIFFICULTY_NORMAL; + m_raidDifficulty = DIFFICULTY_10_N; + m_raidMapDifficulty = DIFFICULTY_10_N; m_lastPotionId = 0; _talentMgr = new PlayerTalentInfo(); @@ -2985,11 +2985,39 @@ void Player::GiveLevel(uint8 level) SetByteFlag(PLAYER_FIELD_BYTES, 1, 0x01); } + std::list<uint32> learnList = GetSpellsForLevels(getClass(), getRaceMask(), GetTalentSpec(GetActiveTalentGroup()), oldLevel, level); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) + { + if (!HasSpell(*iter)) + LearnSpell(*iter, true); + } + sScriptMgr->OnPlayerLevelChanged(this, oldLevel); } void Player::InitTalentForLevel() { + uint8 level = getLevel(); + // talents base at level diff (talents = level - 9 but some can be used already) + if (level < 15) + { + // Remove all talent points + if (GetUsedTalentCount() > 0) // Free any used talents + { + ResetTalents(true); + } + } + else + { + if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || GetTalentGroupsCount() == 0) + { + SetTalentGroupsCount(1); + SetActiveTalentGroup(0); + } + } + + SetUInt32Value(PLAYER_FIELD_MAX_TALENT_TIERS, CalculateTalentsPoints()); + if (!GetSession()->PlayerLoading()) SendTalentsInfoData(); // update at client } @@ -3164,7 +3192,7 @@ void Player::InitStatsForLevel(bool reapplyMods) void Player::SendKnownSpells() { - WorldPackets::Spell::SendKnownSpells knownSpells; + WorldPackets::Spells::SendKnownSpells knownSpells; knownSpells.InitialLogin = false; /// @todo knownSpells.KnownSpells.reserve(m_spells.size()); @@ -3267,7 +3295,7 @@ void DeleteSpellFromAllPlayers(uint32 spellId) } } -bool Player::AddTalent(uint32 talentId, uint8 spec) +bool Player::AddTalent(uint32 talentId, uint8 spec, bool learning) { TalentEntry const* talentEntry = sTalentStore.LookupEntry(talentId); @@ -3309,15 +3337,28 @@ bool Player::AddTalent(uint32 talentId, uint8 spec) return false; } - TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(spec); + PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(talentId); + if (itr == GetTalentMap(spec)->end()) + { + //if (GetTalentBySpellID(talentEntry->SpellID)) + { + PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; + PlayerTalent* newtalent = new PlayerTalent(); - // Check if player already has this talent - if (talentGroupInfo->HasTalent(talentId)) - return false; + newtalent->state = state; + newtalent->spec = spec; - talentGroupInfo->Talents[talentEntry->TierID] = talentId; + (*GetTalentMap(spec))[talentId] = newtalent; - return true; + return true; + } + //else + // TC_LOG_ERROR("spells", "Player::addTalent: Talent %u not found in talent store.", talentId); + } + else + itr->second->state = PLAYERSPELL_UNCHANGED; + + return false; } bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent, bool disabled, bool loading /*= false*/, bool fromSkill /*= false*/) @@ -3421,9 +3462,9 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent SendSupercededSpell(spellId, next_active_spell_id); else { - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint32(spellId); - GetSession()->SendPacket(&data); + WorldPackets::Spells::SendRemovedSpell removedSpells; + removedSpells.Spells.push_back(spellId); + GetSession()->SendPacket(removedSpells.Write()); } } @@ -3529,9 +3570,11 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent return false; } + uint32 talentCost = GetTalentSpellCost(spellId); + // 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 (!loading && spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL)) + if (!loading && talentCost > 0 && 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, spellId, true); @@ -3548,6 +3591,9 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent return false; } + // update used talent points count + SetUsedTalentCount(GetUsedTalentCount() + talentCost); + // update free primary prof.points (if any, can be none in case GM .learn prof. learning) if (uint32 freeProfs = GetFreePrimaryProfessionPoints()) { @@ -3555,38 +3601,62 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent SetFreePrimaryProfessions(freeProfs-1); } + // add dependent skills + uint16 maxskill = GetMaxSkillValueForLevel(); + + SpellLearnSkillNode const* spellLearnSkill = sSpellMgr->GetSpellLearnSkill(spellId); + SkillLineAbilityMapBounds skill_bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId); - // add dependent skills if this spell is not learned from adding skill already - if (!fromSkill) + if (spellLearnSkill) { - if (SpellLearnSkillNode const* spellLearnSkill = sSpellMgr->GetSpellLearnSkill(spellId)) - { - uint32 skill_value = GetPureSkillValue(spellLearnSkill->skill); - uint32 skill_max_value = GetPureMaxSkillValue(spellLearnSkill->skill); + uint32 skill_value = GetPureSkillValue(spellLearnSkill->skill); + uint32 skill_max_value = GetPureMaxSkillValue(spellLearnSkill->skill); - if (skill_value < spellLearnSkill->value) - skill_value = spellLearnSkill->value; + if (skill_value < spellLearnSkill->value) + skill_value = spellLearnSkill->value; - uint32 new_skill_max_value = spellLearnSkill->maxvalue == 0 ? GetMaxSkillValueForLevel() : spellLearnSkill->maxvalue; + uint32 new_skill_max_value = spellLearnSkill->maxvalue == 0 ? maxskill : spellLearnSkill->maxvalue; - if (skill_max_value < new_skill_max_value) - skill_max_value = new_skill_max_value; + if (skill_max_value < new_skill_max_value) + skill_max_value = new_skill_max_value; - SetSkill(spellLearnSkill->skill, spellLearnSkill->step, skill_value, skill_max_value); - } - else + SetSkill(spellLearnSkill->skill, spellLearnSkill->step, skill_value, skill_max_value); + } + else + { + // not ranked skills + for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx) { - // not ranked skills - for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx) - { - SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->SkillLine); - if (!pSkill) - continue; + SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(_spell_idx->second->SkillLine); + if (!pSkill) + continue; + + if (HasSkill(pSkill->ID)) + continue; - ///@todo: confirm if rogues start with lockpicking skill at level 1 but only receive the spell to use it at level 16 - if ((_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->ID)) || (pSkill->ID == SKILL_LOCKPICKING && _spell_idx->second->TrivialSkillLineRankHigh == 0)) - LearnDefaultSkill(pSkill->ID, 0); + SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pSkill->ID, getRace(), getClass()); + if (!rcEntry) + continue; + + if (_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN || + // lockpicking/runeforging special case, not have SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN + ((pSkill->ID == SKILL_LOCKPICKING || pSkill->ID == SKILL_RUNEFORGING) && (_spell_idx->second->TrivialSkillLineRankHigh == 0 || _spell_idx->second->TrivialSkillLineRankHigh == 1))) + { + switch (GetSkillRangeType(rcEntry)) + { + case SKILL_RANGE_LANGUAGE: + SetSkill(pSkill->ID, GetSkillStep(pSkill->ID), 300, 300); + break; + case SKILL_RANGE_LEVEL: + SetSkill(pSkill->ID, GetSkillStep(pSkill->ID), 1, GetMaxSkillValueForLevel()); + break; + case SKILL_RANGE_MONO: + SetSkill(pSkill->ID, GetSkillStep(pSkill->ID), 1, 1); + break; + default: + break; + } } } } @@ -3665,6 +3735,7 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const { + if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) return spellInfo->Id == chrSpec->MasterySpellID[0] || spellInfo->Id == chrSpec->MasterySpellID[1]; @@ -3683,10 +3754,9 @@ void Player::LearnSpell(uint32 spell_id, bool dependent, bool fromSkill /*= fals // prevent duplicated entires in spell book, also not send if not in world (loading) if (learning && IsInWorld()) { - WorldPacket data(SMSG_LEARNED_SPELL, 8); - data << uint32(spell_id); - data << uint32(0); - GetSession()->SendPacket(&data); + WorldPackets::Spells::LearnedSpells packet; + packet.SpellID.push_back(spell_id); + GetSession()->SendPacket(packet.Write()); } // learn all disabled higher ranks and required spells (recursive) @@ -3854,8 +3924,8 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id); if (spellInfo->IsPassive()) { - for (int i = 0; i < MAX_SPELL_EFFECTS; i++) - if (spellInfo->Effects[i].Effect == SPELL_EFFECT_DUAL_WIELD) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->Effect == SPELL_EFFECT_DUAL_WIELD) { SetCanDualWield(false); break; @@ -3869,9 +3939,9 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) // remove from spell book if not replaced by lesser rank if (!prev_activate) { - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint32(spell_id); - GetSession()->SendPacket(&data); + WorldPackets::Spells::SendRemovedSpell removedSpells; + removedSpells.Spells.push_back(spell_id); + GetSession()->SendPacket(removedSpells.Write()); } } @@ -4056,17 +4126,20 @@ uint32 Player::GetNextResetTalentsCost() const } } -bool Player::ResetTalents(bool no_cost) +bool Player::ResetTalents(bool noCost, bool resetTalents, bool resetSpecialization) { - sScriptMgr->OnPlayerTalentsReset(this, no_cost); + if (!resetTalents && !resetSpecialization) + return false; + sScriptMgr->OnPlayerTalentsReset(this, noCost); + // not need after this call if (HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) RemoveAtLoginFlag(AT_LOGIN_RESET_TALENTS, true); uint32 cost = 0; - if (!no_cost && !sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST)) + if (!noCost && !sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST)) { cost = GetNextResetTalentsCost(); @@ -4079,66 +4152,54 @@ bool Player::ResetTalents(bool no_cost) RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - uint8 group = GetActiveTalentGroup(); - uint32 specID = GetActiveTalentSpec(); - - for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) + if (resetTalents) { - TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); + for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) + { + TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); - if (!talentInfo) - continue; + if (!talentInfo) + continue; - // unlearn only talents for character class - // some spell learned by one class as normal spells or know at creation but another class learn it as talent, - // to prevent unexpected lost normal learned spell skip another class talents - if (getClass() != talentInfo->ClassID) - continue; + // unlearn only talents for character class + // some spell learned by one class as normal spells or know at creation but another class learn it as talent, + // to prevent unexpected lost normal learned spell skip another class talents + if (talentInfo->ClassID != getClass()) + continue; - const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + if (!spellEntry) + continue; - if (!_spellEntry) - continue; + RemoveSpell(spellEntry->Id, false); - RemoveSpell(talentInfo->SpellID, true); + // search for spells that the talent teaches and unlearn them, 6.x remove? + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + RemoveSpell(effect->TriggerSpell, true); - // search for spells that the talent teaches and unlearn them - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL) - RemoveSpell(_spellEntry->Effects[i].TriggerSpell, true); + GetTalentMap(GetActiveTalentGroup())->erase(talentId); + } } - // Remove all specialization specific spells and give default ones which were overriden - auto specSpells = sSpecializationSpellsBySpecStore.find(specID); - if (specSpells != sSpecializationSpellsBySpecStore.end()) + if (resetSpecialization) { - for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) + std::list<uint32> learnList = GetSpellsForLevels(0, getRaceMask(), GetTalentSpec(GetActiveTalentGroup()), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) { - SpecializationSpellsEntry const* specSpell = *it; - if (HasSpell(specSpell->SpellID)) { - RemoveSpell(specSpell->SpellID, true); - if (specSpell->OverridesSpellID) - LearnSpell(specSpell->OverridesSpellID, false); - } + if (HasSpell(*iter)) + RemoveSpell(*iter, true); } + SetTalentSpec(GetActiveTalentGroup(), 0); + SetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID, 0); } - // Unlearn masteries - if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(specID)) - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (uint32 mastery = chrSpec->MasterySpellID[i]) - RemoveAurasDueToSpell(mastery); - - // Reset talents store - GetTalentGroupInfo(group)->Reset(); - SetTalentSpec(group, 0); - SQLTransaction trans = CharacterDatabase.BeginTransaction(); _SaveTalents(trans); _SaveSpells(trans); CharacterDatabase.CommitTransaction(trans); - if (!no_cost) + if (!noCost) { ModifyMoney(-(int64)cost); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost); @@ -4159,6 +4220,35 @@ bool Player::ResetTalents(bool no_cost) return true; } +bool Player::RemoveTalent(uint32 talentId) +{ + TalentEntry const* talent = sTalentStore.LookupEntry(talentId); + if (!talent) + return false; + + uint32 spellId = talent->SpellID; + + SpellInfo const* unlearnSpellProto = sSpellMgr->GetSpellInfo(spellId); + + RemoveSpell(spellId, false); + + // 6.x remove? + for (SpellEffectInfo const* effect : unlearnSpellProto->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + RemoveSpell(effect->TriggerSpell, false); + + GetTalentMap(GetActiveTalentSpec())->erase(talentId); + + // Needs to be executed orthewise the talents will be screwedsx + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + _SaveTalents(trans); + _SaveSpells(trans); + CharacterDatabase.CommitTransaction(trans); + + SendTalentsInfoData(); + return true; +} + Mail* Player::GetMail(uint32 id) { for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr) @@ -4225,7 +4315,8 @@ bool Player::HasSpell(uint32 spell) const bool Player::HasTalent(uint32 talentId, uint8 group) { - return GetTalentGroupInfo(group)->HasTalent(talentId); + PlayerTalentMap::const_iterator itr = GetTalentMap(group)->find(talentId); + return (itr != GetTalentMap(group)->end()); } bool Player::HasActiveSpell(uint32 spell) const @@ -6200,13 +6291,13 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const void Player::SendActionButtons(uint32 state) const { - WorldPackets::Spell::UpdateActionButtons packet; + WorldPackets::Spells::UpdateActionButtons packet; for (uint8 button = 0; button < MAX_ACTION_BUTTONS; ++button) { ActionButtonList::const_iterator itr = m_actionButtons.find(button); if (itr != m_actionButtons.end() && itr->second.uState != ACTIONBUTTON_DELETED) - packet.ActionButtons[button] = uint32(itr->second.packedData); + packet.ActionButtons[button] = uint64(itr->second.packedData); else packet.ActionButtons[button] = 0; } @@ -8260,7 +8351,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 } // not allow proc extra attack spell at extra attack - if (m_extraAttacks && spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) + if (m_extraAttacks && spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return; float chance = (float)spellInfo->ProcChance; @@ -15121,7 +15212,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, if (quest->GetRewSpellCast() > 0) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpellCast()); - if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(SPELL_EFFECT_CREATE_ITEM)) + if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_CREATE_ITEM)) { if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID())) creature->CastSpell(this, quest->GetRewSpellCast(), true); @@ -15132,7 +15223,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, else if (quest->GetRewSpell() > 0) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell()); - if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(SPELL_EFFECT_CREATE_ITEM)) + if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_CREATE_ITEM)) { if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID())) creature->CastSpell(this, quest->GetRewSpell(), true); @@ -16996,10 +17087,10 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) uint32 dungeonDiff = fields[39].GetUInt8() & 0x0F; if (dungeonDiff >= MAX_DUNGEON_DIFFICULTY) - dungeonDiff = DUNGEON_DIFFICULTY_NORMAL; + dungeonDiff = DIFFICULTY_NORMAL; uint32 raidDiff = (fields[39].GetUInt8() >> 4) & 0x0F; if (raidDiff >= MAX_RAID_DIFFICULTY) - raidDiff = RAID_DIFFICULTY_10MAN_NORMAL; + raidDiff = DIFFICULTY_10_N; SetDungeonDifficulty(Difficulty(dungeonDiff)); // may be changed in _LoadGroup SetRaidDifficulty(Difficulty(raidDiff)); // may be changed in _LoadGroup @@ -17391,11 +17482,16 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) break; uint32 talentSpec = atoul(talentSpecs[i]); - if (sChrSpecializationStore.LookupEntry(talentSpec)) - SetTalentSpec(i, talentSpec); - else - SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); + if (talentSpec) + { + if (sChrSpecializationStore.LookupEntry(talentSpec)) + SetTalentSpec(i, talentSpec); + else + SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); + } } + + SetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID, GetActiveTalentSpec()); _LoadTalents(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS)); _LoadSpells(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELLS)); @@ -18462,6 +18558,13 @@ void Player::_LoadSpells(PreparedQueryResult result) AddSpell((*result)[0].GetUInt32(), (*result)[1].GetBool(), false, false, (*result)[2].GetBool(), true); while (result->NextRow()); } + + std::list<uint32> learnList = GetSpellsForLevels(getClass(), getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) + { + if (!HasSpell(*iter)) + LearnSpell(*iter, true); + } } void Player::_LoadGroup(PreparedQueryResult result) @@ -18710,7 +18813,7 @@ void Player::SendRaidInfo() if (itr->second.perm) { InstanceSave* save = itr->second.save; - bool isHeroic = save->GetDifficulty() == RAID_DIFFICULTY_10MAN_HEROIC || save->GetDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC; + bool isHeroic = save->GetDifficulty() == DIFFICULTY_10_HC || save->GetDifficulty() == DIFFICULTY_25_HC; uint32 completedEncounters = 0; if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId())) if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript()) @@ -20173,7 +20276,7 @@ void Player::ResetInstances(uint8 method, bool isRaid) if (method == INSTANCE_RESET_ALL) { // the "reset all instances" method can only reset normal maps - if (entry->IsRaid() || diff == DUNGEON_DIFFICULTY_HEROIC) + if (entry->IsRaid() || diff == DIFFICULTY_HEROIC) { ++itr; continue; @@ -20791,14 +20894,18 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply) TC_LOG_DEBUG("spells", "Player::AddSpellMod %d", mod->spellId); OpcodeServer opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER; + WorldPackets::Spells::SetSpellModifier packet(opcode); + int i = 0; flag96 _mask; uint32 modTypeCount = 0; // count of mods per one mod->op - WorldPacket data(opcode); - data << uint32(1); // count of different mod->op's in packet - size_t writePos = data.wpos(); - data << uint32(modTypeCount); - data << uint8(mod->op); + + /// @todo Implement sending of bulk modifiers instead of single + packet.Modifiers.resize(1); + WorldPackets::Spells::SpellModifier& spellMod = packet.Modifiers[0]; + + spellMod.ModIndex = mod->op; + for (int eff = 0; eff < 96; ++eff) { if (eff != 0 && (eff % 32) == 0) @@ -20807,19 +20914,21 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply) _mask[i] = uint32(1) << (eff - (32 * i)); if (mod->mask & _mask) { - int32 val = 0; + WorldPackets::Spells::SpellModifierData modData; + for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr) if ((*itr)->type == mod->type && (*itr)->mask & _mask) - val += (*itr)->value; - val += apply ? mod->value : -(mod->value); + modData.ModifierValue += (*itr)->value; + + modData.ModifierValue += apply ? mod->value : -(mod->value); + modData.ClassIndex = eff; - data << uint8(eff); - data << float(val); - ++modTypeCount; + spellMod.ModifierData.push_back(modData); } } - data.put<uint32>(writePos, modTypeCount); - SendDirectMessage(&data); + + SendDirectMessage(packet.Write()); + if (apply) m_spellMods[mod->op].push_back(mod); else @@ -22987,7 +23096,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SendKnownSpells(); /// SMSG_SEND_UNLEARN_SPELLS - SendDirectMessage(WorldPackets::Spell::SendUnlearnSpells().Write()); + SendDirectMessage(WorldPackets::Spells::SendUnlearnSpells().Write()); /// @todo: SMSG_SEND_SPELL_HISTORY /// @todo: SMSG_SEND_SPELL_CHARGES @@ -23213,7 +23322,7 @@ void Player::ResetSpells(bool myClassOnly) else for (PlayerSpellMap::const_iterator iter = smap.begin(); iter != smap.end(); ++iter) RemoveSpell(iter->first, false, false); // only iter->first can be accessed, object by iter->second can be deleted already - + LearnDefaultSkills(); LearnCustomSpells(); LearnQuestRewardedSpells(); @@ -23257,7 +23366,6 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank) if (!rcInfo) return; - TC_LOG_DEBUG("entities.player.loading", "PLAYER (Class: %u Race: %u): Adding initial skill, id = %u", uint32(getClass()), uint32(getRace()), skillId); switch (GetSkillRangeType(rcInfo)) { case SKILL_RANGE_LANGUAGE: @@ -23303,6 +23411,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank) } } + void Player::LearnQuestRewardedSpells(Quest const* quest) { int32 spell_id = quest->GetRewSpellCast(); @@ -23325,9 +23434,9 @@ void Player::LearnQuestRewardedSpells(Quest const* quest) // check learned spells state bool found = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellInfo->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL && !HasSpell(spellInfo->Effects[i].TriggerSpell)) + if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL && !HasSpell(effect->TriggerSpell)) { found = true; break; @@ -23338,8 +23447,12 @@ void Player::LearnQuestRewardedSpells(Quest const* quest) if (!found) return; + SpellEffectInfo const* effect = spellInfo->GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (!effect) + return; + // prevent learn non first rank unknown profession and second specialization for same profession) - uint32 learned_0 = spellInfo->Effects[0].TriggerSpell; + uint32 learned_0 = effect->TriggerSpell; if (sSpellMgr->GetSpellRank(learned_0) > 1 && !HasSpell(learned_0)) { SpellInfo const* learnedInfo = sSpellMgr->GetSpellInfo(learned_0); @@ -23355,8 +23468,15 @@ void Player::LearnQuestRewardedSpells(Quest const* quest) { uint32 profSpell = itr2->second; + SpellEffectInfo const* effect0 = learnedInfo->GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (!effect0) + continue; + SpellEffectInfo const* effect1 = learnedInfo->GetEffect(DIFFICULTY_NONE, EFFECT_1); + if (!effect1) + continue; + // specialization - if (learnedInfo->Effects[0].Effect == SPELL_EFFECT_TRADE_SKILL && learnedInfo->Effects[1].Effect == 0 && profSpell) + if (effect0->Effect == SPELL_EFFECT_TRADE_SKILL && effect1->Effect == 0 && profSpell) { // search other specialization for same prof for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) @@ -23368,8 +23488,16 @@ void Player::LearnQuestRewardedSpells(Quest const* quest) if (!itrInfo) return; + + SpellEffectInfo const* itrEffect0 = itrInfo->GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (!itrEffect0) + continue; + SpellEffectInfo const* itrEffect1 = itrInfo->GetEffect(DIFFICULTY_NONE, EFFECT_1); + if (!itrEffect1) + continue; + // compare only specializations - if (itrInfo->Effects[0].Effect != SPELL_EFFECT_TRADE_SKILL || itrInfo->Effects[1].Effect != 0) + if (itrEffect0->Effect != SPELL_EFFECT_TRADE_SKILL || itrEffect1->Effect != 0) continue; // compare same chain spells @@ -23406,7 +23534,8 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) if (!ability || ability->SkillLine != skillId) continue; - if (!sSpellMgr->GetSpellInfo(ability->SpellID)) + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ability->SpellID); + if (!spellInfo) continue; if (ability->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && ability->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) @@ -23420,6 +23549,10 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) if (ability->ClassMask && !(ability->ClassMask & classMask)) continue; + // check level, skip class spells if not high enough + if (getLevel() < spellInfo->SpellLevel) + continue; + // need unlearn spell if (skillValue < ability->MinSkillLineRank && ability->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) RemoveSpell(ability->SpellID); @@ -23448,17 +23581,18 @@ void Player::SendAurasForTarget(Unit* target) if (target->HasAuraType(SPELL_AURA_HOVER)) target->SetHover(true, true); - WorldPacket data(SMSG_AURA_UPDATE_ALL); - data << target->GetPackGUID(); - Unit::VisibleAuraMap const* visibleAuras = target->GetVisibleAuras(); + + WorldPackets::Spells::SendAuraUpdate update; + update.Init(true, GetGUID(), visibleAuras->size()); + for (Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr) { AuraApplication * auraApp = itr->second; - auraApp->BuildUpdatePacket(data, false); + update.BuildUpdatePacket(auraApp, false, getLevel()); // TODO 6.x should be caster's level } - GetSession()->SendPacket(&data); + GetSession()->SendPacket(const_cast<WorldPacket*>(update.Write())); } void Player::SetDailyQuestStatus(uint32 quest_id) @@ -25417,37 +25551,36 @@ void Player::CompletedAchievement(AchievementEntry const* entry) bool Player::LearnTalent(uint32 talentId) { - uint8 group = GetActiveTalentGroup(); - - // check if talent specialization is learnt - if (!GetTalentSpec(group)) - return false; - TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); if (!talentInfo) return false; + + uint32 maxTalentTier = GetUInt32Value(PLAYER_FIELD_MAX_TALENT_TIERS); // prevent learn talent for different class (cheating) - if (getClass() != talentInfo->ClassID) + if (talentInfo->ClassID != getClass()) return false; - // Check player level - // TODO: fix level requirements for deathknights - uint8 levelReq = std::min(15*talentInfo->TierID + 15, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); - if (getLevel() < levelReq) + // check if we have enough talent points + if (talentInfo->TierID > maxTalentTier) return false; - // Check if such tier talent hasn't been picked already - TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group); - if (talentGroupInfo->Talents[talentInfo->TierID]) - return false; + // Check if player doesnt have any spell in selected collumn + for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) + { + if (TalentEntry const* talent = sTalentStore.LookupEntry(i)) + { + if (talentInfo->TierID == talent->TierID && HasSpell(talent->SpellID)) + return false; + } + } // spell not set in talent.dbc uint32 spellid = talentInfo->SpellID; if (spellid == 0) { - TC_LOG_ERROR("entities.player", "Talent.dbc have for talent: %u spell id = 0", talentId); + TC_LOG_ERROR("entities.player", "Talent.dbc has no spellInfo for talent: %u (spell id = 0)", talentId); return false; } @@ -25455,54 +25588,64 @@ bool Player::LearnTalent(uint32 talentId) if (HasSpell(spellid)) return false; - // Check talent spec - if (talentInfo->SpecID != GetTalentSpec(group)) + if (!AddTalent(talentId, GetActiveTalentGroup(), true)) return false; - // learn! (other talent ranks will unlearned at learning) LearnSpell(spellid, false); - AddTalent(talentId, group); - TC_LOG_INFO("misc", "TalentID: %u Spell: %u Group: %u\n", talentId, spellid, group); + TC_LOG_INFO("misc", "TalentID: %u Spell: %u Group: %u\n", talentId, spellid, GetActiveTalentGroup()); return true; } void Player::LearnTalentSpecialization(uint32 talentSpec) { + if (GetActiveTalentSpec()) + return; + SetTalentSpec(GetActiveTalentGroup(), talentSpec); - // Replace default spells by specialization spells - auto specSpells = sSpecializationSpellsBySpecStore.find(talentSpec); - if (specSpells != sSpecializationSpellsBySpecStore.end()) + SetUInt32Value(PLAYER_FIELD_CURRENT_SPEC_ID, talentSpec); + + PlayerTalentMap* talents = GetTalentMap(GetActiveTalentGroup()); + + for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) { - for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) - { - SpecializationSpellsEntry const* specSpell = *it; + TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); - // Unlearn spell if it is replaced by new specialization - if (specSpell->OverridesSpellID) - RemoveSpell(specSpell->OverridesSpellID, true); + if (!talentInfo || talentInfo->ClassID != getClass() || talentInfo->SpecID != talentSpec) + continue; - // Learn new spell - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID)) - if (spellInfo->BaseLevel <= getLevel()) - LearnSpell(specSpell->SpellID, false); + for (PlayerTalentMap::iterator itr = talents->begin(); itr != talents->end();) + { + TalentEntry const* talent = sTalentStore.LookupEntry(itr->first); + if (!talent || talent->TierID != talentInfo->TierID) + { + ++itr; + continue; + } + RemoveSpell(talent->SpellID, false); + itr = talents->erase(itr); + + TC_LOG_DEBUG("spells", "Player %s unlearning talent id: %u tier: %u because of specialization change", GetName().c_str(), talent->ID, talent->TierID); } } - if (CanUseMastery()) + SendTalentsInfoData(); + + std::list<uint32> learnList = GetSpellsForLevels(0, getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) { - ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(talentSpec); - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (SpellInfo const* masterySpell = sSpellMgr->GetSpellInfo(chrSpec->MasterySpellID[i])) - if (masterySpell->IsPassive() && IsNeedCastPassiveSpellAtLearn(masterySpell)) - CastSpell(this, masterySpell->Id, true); + if (!HasSpell(*iter)) + LearnSpell(*iter, true); } + SaveToDB(); + SendTalentsInfoData(); } + void Player::AddKnownCurrency(uint32 itemId) { if (CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId)) @@ -25587,23 +25730,39 @@ void Player::SendTalentsInfoData() for (uint8 i = 0; i < groupsCount; ++i) { - TalentGroupInfo* groupInfo = GetTalentGroupInfo(i); WorldPackets::Talent::TalentGroupInfo groupInfoPkt; - groupInfoPkt.SpecID = groupInfo->SpecID; + groupInfoPkt.SpecID = GetTalentSpec(i); + + groupInfoPkt.TalentIDs.reserve(GetTalentMap(i)->size()); - groupInfoPkt.TalentIDs.reserve(MAX_TALENT_TIERS); - for (uint32 x = 0; x < MAX_TALENT_TIERS; ++x) + for (PlayerTalentMap::const_iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end(); ++itr) { - // Do not send empty talents - if (!groupInfo->Talents[x]) - break; + TalentEntry const* talentInfo = sTalentStore.LookupEntry(itr->first); + if (!talentInfo) + { + TC_LOG_ERROR("entities.player", "Player %s has unknown talent id: %u", GetName().c_str(), itr->first); + continue; + } + + if (talentInfo->ClassID != getClass()) + continue; + + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + if (!spellEntry) + { + TC_LOG_ERROR("entities.player", "Player %s has unknown talent spell: %u", GetName().c_str(), talentInfo->SpellID); + continue; + } + + if (!HasTalent(itr->first, i)) + continue; - groupInfoPkt.TalentIDs.push_back(groupInfo->Talents[x]); + groupInfoPkt.TalentIDs.push_back(uint16(itr->first)); } for (uint32 x = 0; x < MAX_GLYPH_SLOT_INDEX; ++x) - groupInfoPkt.GlyphIDs[x] = groupInfo->Glyphs[x]; + groupInfoPkt.GlyphIDs[x] = uint16(GetGlyph(i, x)); packet.Info.TalentGroups.push_back(groupInfoPkt); } @@ -25915,7 +26074,7 @@ void Player::_LoadTalents(PreparedQueryResult result) if (result) { do - AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8()); + AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8(), false); while (result->NextRow()); } } @@ -25928,17 +26087,12 @@ void Player::_SaveTalents(SQLTransaction& trans) for (uint8 group = 0; group < MAX_TALENT_GROUPS; ++group) { - TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group); - - for (uint32 tier = 0; tier < MAX_TALENT_TIERS; ++tier) + for (PlayerTalentMap::iterator itr = GetTalentMap(group)->begin(); itr != GetTalentMap(group)->end(); ++itr) { - if (!talentGroupInfo->Talents[tier]) - continue; - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT); stmt->setUInt64(0, GetGUID().GetCounter()); - stmt->setUInt32(1, talentGroupInfo->Talents[tier]); - stmt->setUInt8(2, group); + stmt->setUInt32(1, itr->first); + stmt->setUInt8(2, itr->second->spec); trans->Append(stmt); } } @@ -26037,30 +26191,27 @@ void Player::ActivateTalentGroup(uint8 group) if (getClass() != talentInfo->ClassID) continue; + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); + if (!spellEntry) + continue; + RemoveSpell(talentInfo->SpellID, true); + + // search for spells that the talent teaches and unlearn them + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->TriggerSpell > 0 && effect->Effect == SPELL_EFFECT_LEARN_SPELL) + RemoveSpell(effect->TriggerSpell, true); } // Unlearn specialization specific spells - auto specSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec()); - if (specSpells != sSpecializationSpellsBySpecStore.end()) + std::list<uint32> learnList = GetSpellsForLevels(0, getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) { - for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) - { - SpecializationSpellsEntry const* specSpell = *it; - if (HasSpell(specSpell->SpellID)) { - RemoveSpell(specSpell->SpellID, true); - LearnSpell(specSpell->OverridesSpellID, false); - } - } + if (HasSpell(*iter)) + RemoveSpell(*iter, true); } - // Unlearn mastery spells - ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec()); - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (chrSpec->MasterySpellID[i]) - RemoveSpell(chrSpec->MasterySpellID[i], true); - - // set glyphs + // remove glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) // remove secondary glyph if (uint32 oldglyph = GetGlyph(GetActiveTalentGroup(), slot)) @@ -26070,6 +26221,15 @@ void Player::ActivateTalentGroup(uint8 group) // Activate new group SetActiveTalentGroup(group); + uint32 spentTalents = 0; + + learnList = GetSpellsForLevels(getClass(), getRaceMask(), GetActiveTalentSpec(), 0, getLevel()); + for (std::list<uint32>::const_iterator iter = learnList.begin(); iter != learnList.end(); iter++) + { + if (!HasSpell(*iter)) + LearnSpell(*iter, true); + } + for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); @@ -26081,31 +26241,12 @@ void Player::ActivateTalentGroup(uint8 group) if (getClass() != talentInfo->ClassID) continue; - LearnSpell(talentInfo->SpellID, false); - } + ++spentTalents; - // Replace default spells with specialization specific spells - auto newSpecSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec()); - if (newSpecSpells != sSpecializationSpellsBySpecStore.end()) - { - for (auto it = newSpecSpells->second.begin(); it != newSpecSpells->second.end(); ++it) - { - SpecializationSpellsEntry const* specSpell = *it; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID); - if (getLevel() >= spellInfo->BaseLevel) { - if (specSpell->OverridesSpellID) - RemoveSpell(specSpell->OverridesSpellID, true); - LearnSpell(specSpell->SpellID, false); - } - } + if (HasTalent(talentInfo->SpellID, group)) + LearnSpell(talentInfo->SpellID, false); } - if (CanUseMastery()) - if (ChrSpecializationEntry const* newChrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (newChrSpec->MasterySpellID[i]) - LearnSpell(newChrSpec->MasterySpellID[i], false); - // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) { @@ -26119,6 +26260,7 @@ void Player::ActivateTalentGroup(uint8 group) SetGlyph(slot, glyph); } + SetUsedTalentCount(spentTalents); InitTalentForLevel(); { @@ -26138,7 +26280,9 @@ void Player::ActivateTalentGroup(uint8 group) SetPower(pw, 0); if (!sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) + { ResetTalents(true); + } } void Player::ResetTimeSync() @@ -27178,3 +27322,9 @@ void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) data << uint32(newSpell) << uint32(oldSpell); GetSession()->SendPacket(&data); } + +uint32 Player::CalculateTalentsPoints() const +{ + // 1 talent point for every 15 levels + return getLevel() >= 100 ? 7 : uint32(floor(getLevel() / 15.f)); +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1dcd75a156e..6b9e925e28d 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -116,6 +116,12 @@ struct PlayerSpell bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks }; +struct PlayerTalent +{ + PlayerSpellState state : 8; + uint8 spec : 8; +}; + extern uint32 const MasterySpells[MAX_CLASSES]; enum TalentSpecialization // talent tabs @@ -184,6 +190,7 @@ struct PlayerCurrency uint32 weekCount; }; +typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap; typedef std::unordered_map<uint32, PlayerSpell*> PlayerSpellMap; typedef std::list<SpellModifier*> SpellModList; typedef std::unordered_map<uint32, PlayerCurrency> PlayerCurrenciesMap; @@ -329,7 +336,7 @@ enum ReputationSource }; #define ACTION_BUTTON_ACTION(X) (uint64(X) & 0x00000000FFFFFFFF) -#define ACTION_BUTTON_TYPE(X) ((uint64(X) & 0xFFFFFFFF00000000) >> 32) +#define ACTION_BUTTON_TYPE(X) ((uint64(X) & 0xFFFFFFFF00000000) >> 56) #define MAX_ACTION_BUTTON_ACTION_VALUE (0xFFFFFFFF) struct ActionButton @@ -344,7 +351,7 @@ struct ActionButton uint32 GetAction() const { return ACTION_BUTTON_ACTION(packedData); } void SetActionAndType(uint32 action, ActionButtonType type) { - uint64 newData = uint64(action) | (uint64(type) << 32); + uint64 newData = uint64(action) | (uint64(type) << 56); if (newData != packedData || uState == ACTIONBUTTON_DELETED) { packedData = newData; @@ -1223,48 +1230,36 @@ private: bool _isPvP; }; -struct TalentGroupInfo +struct PlayerTalentInfo { - uint32 Talents[MAX_TALENT_TIERS]; - uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; - uint32 SpecID; - - bool HasTalent(uint32 talentId) + PlayerTalentInfo() : UsedTalentCount(0), ResetTalentsCost(0), ResetTalentsTime(0), ActiveGroup(0), GroupsCount(1) { - for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) - if (Talents[i] == talentId) - return true; - return false; - } - - uint32 TalentCount() - { - for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) - if (!Talents[i]) - return i; - return MAX_TALENT_TIERS; + for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) + { + GroupInfo[i].Talents = new PlayerTalentMap(); + memset(GroupInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); + GroupInfo[i].TalentTree = 0; + } } - void Reset() - { - for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) - Talents[i] = 0; - } -}; - -struct PlayerTalentInfo -{ - PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveGroup(0), GroupsCount(1) + ~PlayerTalentInfo() { for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) { - memset(GroupInfo[i].Talents, 0, sizeof(uint32)*MAX_TALENT_TIERS); - memset(GroupInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); - GroupInfo[i].SpecID = 0; + for (PlayerTalentMap::const_iterator itr = GroupInfo[i].Talents->begin(); itr != GroupInfo[i].Talents->end(); ++itr) + delete itr->second; + delete GroupInfo[i].Talents; } } - TalentGroupInfo GroupInfo[MAX_TALENT_GROUPS]; + struct TalentGroupInfo + { + PlayerTalentMap* Talents; + uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; + uint32 TalentTree; + } GroupInfo[MAX_TALENT_GROUPS]; + + uint32 UsedTalentCount; uint32 ResetTalentsCost; time_t ResetTalentsTime; uint8 ActiveGroup; @@ -1833,25 +1828,35 @@ class Player : public Unit, public GridObject<Player> std::string GetGuildName(); // Talents + uint32 GetUsedTalentCount() const { return _talentMgr->UsedTalentCount; } + void SetUsedTalentCount(uint32 talents) { _talentMgr->UsedTalentCount = talents; } uint32 GetTalentResetCost() const { return _talentMgr->ResetTalentsCost; } void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; } uint32 GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; } void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; } - uint8 GetActiveTalentGroup() const { return _talentMgr->ActiveGroup; } - void SetActiveTalentGroup(uint8 group){ _talentMgr->ActiveGroup = group; } + uint8 GetTalentGroupsCount() const { return _talentMgr->GroupsCount; } void SetTalentGroupsCount(uint8 count) { _talentMgr->GroupsCount = count; } - uint32 GetTalentSpec(uint8 group) const { return _talentMgr->GroupInfo[group].SpecID; } - void SetTalentSpec(uint8 group, uint32 talentSpec) const { _talentMgr->GroupInfo[group].SpecID = talentSpec; } - uint32 GetActiveTalentSpec() const { return _talentMgr->GroupInfo[_talentMgr->ActiveGroup].SpecID; } + uint8 GetActiveTalentGroup() const { return _talentMgr->ActiveGroup; } + void SetActiveTalentGroup(uint8 group){ _talentMgr->ActiveGroup = group; } + + uint32 GetTalentSpec(uint8 group) const { return _talentMgr->GroupInfo[group].TalentTree; } + void SetTalentSpec(uint8 group, uint32 talentSpec) const { _talentMgr->GroupInfo[group].TalentTree = talentSpec; } + uint32 GetActiveTalentSpec() const { return _talentMgr->GroupInfo[_talentMgr->ActiveGroup].TalentTree; } + + + bool ResetTalents(bool noCost = false, bool resetTalents = true, bool resetSpecialization = true); + bool RemoveTalent(uint32 talentId); - bool ResetTalents(bool no_cost = false); uint32 GetNextResetTalentsCost() const; void InitTalentForLevel(); void SendTalentsInfoData(); bool LearnTalent(uint32 talentId); - bool AddTalent(uint32 talentId, uint8 spec); + bool AddTalent(uint32 talentId, uint8 spec, bool learning); bool HasTalent(uint32 talentId, uint8 spec); + uint32 CalculateTalentsPoints() const; + + void LearnTalentSpecialization(uint32 talentSpec); // Dual Spec @@ -1865,7 +1870,8 @@ class Player : public Unit, public GridObject<Player> void SetGlyph(uint8 slot, uint32 glyph); uint32 GetGlyph(uint8 group, uint8 slot) const { return _talentMgr->GroupInfo[group].Glyphs[slot]; } - TalentGroupInfo* GetTalentGroupInfo(uint8 group) { return &_talentMgr->GroupInfo[group]; } + PlayerTalentMap const* GetTalentMap(uint8 spec) const { return _talentMgr->GroupInfo[spec].Talents; } + PlayerTalentMap* GetTalentMap(uint8 spec) { return _talentMgr->GroupInfo[spec].Talents; } ActionButtonList const& GetActionButtons() const { return m_actionButtons; } uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); } diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 54956e591b4..d6aeb5dee9c 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -145,9 +145,10 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) con /// @todo possibly all negative auras immune? if (GetEntry() == 5925) return false; - - switch (spellInfo->Effects[index].ApplyAuraName) + if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), index)) { + switch (effect->ApplyAuraName) + { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_LEECH: case SPELL_AURA_MOD_FEAR: @@ -155,7 +156,10 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) con return true; default: break; + } } + else + return true; return Creature::IsImmunedToSpellEffect(spellInfo, index); } diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index ea15daed587..47567d1a35a 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -537,16 +537,16 @@ void Player::UpdateMastery() if (Aura* aura = GetAura(chrSpec->MasterySpellID[i])) { - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : aura->GetSpellEffectInfos()) { - if (!aura->HasEffect(j)) + if (!effect) continue; - float mult = aura->GetSpellInfo()->Effects[j].BonusCoefficient; + float mult = effect->BonusCoefficient; if (G3D::fuzzyEq(mult, 0.0f)) continue; - aura->GetEffect(j)->ChangeAmount(int32(value * aura->GetSpellInfo()->Effects[j].BonusCoefficient)); + aura->GetEffect(effect->EffectIndex)->ChangeAmount(int32(value * effect->BonusCoefficient)); } } } @@ -989,8 +989,9 @@ bool Guardian::UpdateStats(Stats stat) AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); if (aurEff) { - SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value - AddPct(mod, spellInfo->Effects[EFFECT_1].CalcValue(owner)); // Ravenous Dead edits the original scale + SpellInfo const* spellInfo = aurEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value + if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), EFFECT_1)) + AddPct(mod, effect->CalcValue(owner)); // Ravenous Dead edits the original scale } // Glyph of the Ghoul aurEff = owner->GetAuraEffect(58686, 0); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 6a41a304639..65b2904fdbf 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -65,6 +65,7 @@ #include "ChatPackets.h" #include "MovementPackets.h" #include "CombatPackets.h" +#include "CombatLogPackets.h" #include <cmath> @@ -1430,10 +1431,10 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s return false; // bleeding effects are not reduced by armor - if (effIndex != MAX_SPELL_EFFECTS) + if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), effIndex)) { - if (spellInfo->Effects[effIndex].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || - spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_SCHOOL_DAMAGE) + if (effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || + effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) if (spellInfo->GetEffectMechanicMask(effIndex) & (1<<MECHANIC_BLEED)) return false; } @@ -1699,7 +1700,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe int32 manaReduction = currentAbsorb; // lower absorb amount by talents - if (float manaMultiplier = absorbAurEff->GetSpellInfo()->Effects[absorbAurEff->GetEffIndex()].CalcValueMultiplier(absorbAurEff->GetCaster())) + if (float manaMultiplier = absorbAurEff->GetSpellEffectInfo()->CalcValueMultiplier(absorbAurEff->GetCaster())) manaReduction = int32(float(manaReduction) * manaMultiplier); int32 manaTaken = -victim->ModifyPower(POWER_MANA, -manaReduction); @@ -2169,12 +2170,12 @@ int32 Unit::GetMechanicResistChance(SpellInfo const* spellInfo) const return 0; int32 resistMech = 0; - for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if (!spellInfo->Effects[eff].IsEffect()) + if (!effect || !effect->IsEffect()) break; - int32 effectMech = spellInfo->GetEffectMechanic(eff); + int32 effectMech = spellInfo->GetEffectMechanic(effect->EffectIndex, GetMap()->GetDifficulty()); if (effectMech) { int32 temp = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effectMech); @@ -2229,7 +2230,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo // Get effects mechanic and chance for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) { - int32 effect_mech = spellInfo->GetEffectMechanic(eff); + int32 effect_mech = spellInfo->GetEffectMechanic(eff, GetMap()->GetDifficulty()); if (effect_mech) { int32 temp = victim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech); @@ -2993,7 +2994,7 @@ void Unit::DeMorph() SetDisplayId(GetNativeDisplayId()); } -Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= 0*/) +Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= 0*/) { ASSERT(!casterGUID.IsEmpty() || caster); @@ -3019,18 +3020,22 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 return NULL; // update basepoints with new values - effect amount will be recalculated in ModStackAmount - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : foundAura->GetSpellEffectInfos()) { - if (!foundAura->HasEffect(i)) + if (!effect) + continue; + + AuraEffect const* eff = foundAura->GetEffect(effect->EffectIndex); + if (!eff) continue; int bp; if (baseAmount) - bp = *(baseAmount + i); + bp = *(baseAmount + effect->EffectIndex); else - bp = foundAura->GetSpellInfo()->Effects[i].BasePoints; - - int32* oldBP = const_cast<int32*>(&(foundAura->GetEffect(i)->m_baseAmount)); + bp = effect->BasePoints; + + int32* oldBP = const_cast<int32*>(&(foundAura->GetEffect(effect->EffectIndex)->m_baseAmount)); // todo 6.x review GetBaseAmount and GetCastItemGUID in this case *oldBP = bp; } @@ -3090,7 +3095,7 @@ void Unit::_AddAura(UnitAura* aura, Unit* caster) // creates aura application instance and registers it in lists // aura application effects are handled separately to prevent aura list corruption -AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint8 effMask) +AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 effMask) { // can't apply aura on unit which is going to be deleted - to not create a memory leak ASSERT(!m_cleanupDone); @@ -3119,7 +3124,7 @@ AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint8 effMask) AddInterruptMask(aurSpellInfo->AuraInterruptFlags); } - if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState()) + if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficulty())) m_auraStateAuras.insert(AuraStateAurasMap::value_type(aState, aurApp)); aura->_ApplyForTarget(this, caster, aurApp); @@ -3140,7 +3145,7 @@ void Unit::_ApplyAuraEffect(Aura* aura, uint8 effIndex) // handles effects of aura application // should be done after registering aura in lists -void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask) +void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask) { Aura* aura = aurApp->GetBase(); @@ -3150,7 +3155,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask) return; // Update target aura state flag - if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState()) + if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficulty())) ModifyAuraState(aState, true); if (aurApp->GetRemoveMode()) @@ -3205,7 +3210,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo } bool auraStateFound = false; - AuraStateType auraState = aura->GetSpellInfo()->GetAuraState(); + AuraStateType auraState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficulty()); if (auraState) { bool canBreak = false; @@ -3281,12 +3286,12 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura) SpellInfo const* spellProto = aura->GetSpellInfo(); // passive spell special case (only non stackable with ranks) - if (spellProto->IsPassiveStackableWithRanks()) + if (spellProto->IsPassiveStackableWithRanks(GetMap()->GetDifficulty())) return; if (!IsHighestExclusiveAura(aura)) { - if (!aura->GetSpellInfo()->IsAffectingArea()) + if (!aura->GetSpellInfo()->IsAffectingArea(GetMap()->GetDifficulty())) { Unit* caster = aura->GetCaster(); if (caster && caster->GetTypeId() == TYPEID_PLAYER) @@ -3346,7 +3351,7 @@ void Unit::RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode) i = m_ownedAuras.begin(); } -void Unit::RemoveOwnedAura(uint32 spellId, ObjectGuid casterGUID, uint8 reqEffMask, AuraRemoveMode removeMode) +void Unit::RemoveOwnedAura(uint32 spellId, ObjectGuid casterGUID, uint32 reqEffMask, AuraRemoveMode removeMode) { for (AuraMap::iterator itr = m_ownedAuras.lower_bound(spellId); itr != m_ownedAuras.upper_bound(spellId);) if (((itr->second->GetEffectMask() & reqEffMask) == reqEffMask) && (!casterGUID || itr->second->GetCasterGUID() == casterGUID)) @@ -3380,7 +3385,7 @@ void Unit::RemoveOwnedAura(Aura* aura, AuraRemoveMode removeMode) ASSERT(false); } -Aura* Unit::GetOwnedAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask, Aura* except) const +Aura* Unit::GetOwnedAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint32 reqEffMask, Aura* except) const { AuraMapBounds range = m_ownedAuras.equal_range(spellId); for (AuraMap::const_iterator itr = range.first; itr != range.second; ++itr) @@ -3409,7 +3414,7 @@ void Unit::RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode) aura->Remove(mode); } -void Unit::RemoveAura(uint32 spellId, ObjectGuid caster, uint8 reqEffMask, AuraRemoveMode removeMode) +void Unit::RemoveAura(uint32 spellId, ObjectGuid caster, uint32 reqEffMask, AuraRemoveMode removeMode) { AuraApplicationMapBoundsNonConst range = m_appliedAuras.equal_range(spellId); for (AuraApplicationMap::iterator iter = range.first; iter != range.second;) @@ -3469,7 +3474,7 @@ void Unit::RemoveAura(Aura* aura, AuraRemoveMode mode) RemoveAura(aurApp, mode); } -void Unit::RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID, uint8 reqEffMask, AuraRemoveMode removeMode) +void Unit::RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID, uint32 reqEffMask, AuraRemoveMode removeMode) { for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);) { @@ -3878,7 +3883,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type) for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) { Aura const* aura = iter->second->GetBase(); - if (aura->GetSpellInfo()->HasAura(type)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type)) ++iter; else _UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -3887,7 +3892,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type) for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();) { Aura* aura = iter->second; - if (aura->GetSpellInfo()->HasAura(type)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type)) ++iter; else RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -3899,7 +3904,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type1, AuraType type2) for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) { Aura const* aura = iter->second->GetBase(); - if (aura->GetSpellInfo()->HasAura(type1) || aura->GetSpellInfo()->HasAura(type2)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type2)) ++iter; else _UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -3908,7 +3913,7 @@ void Unit::RemoveAllAurasExceptType(AuraType type1, AuraType type2) for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();) { Aura* aura = iter->second; - if (aura->GetSpellInfo()->HasAura(type1) || aura->GetSpellInfo()->HasAura(type2)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type2)) ++iter; else RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -4008,7 +4013,7 @@ AuraEffect* Unit::GetDummyAuraEffect(SpellFamilyNames name, uint32 iconId, uint8 return GetAuraEffect(SPELL_AURA_DUMMY, name, iconId, effIndex); } -AuraApplication * Unit::GetAuraApplication(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask, AuraApplication * except) const +AuraApplication * Unit::GetAuraApplication(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint32 reqEffMask, AuraApplication * except) const { AuraApplicationMapBounds range = m_appliedAuras.equal_range(spellId); for (; range.first != range.second; ++range.first) @@ -4027,13 +4032,13 @@ AuraApplication * Unit::GetAuraApplication(uint32 spellId, ObjectGuid casterGUID return NULL; } -Aura* Unit::GetAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask) const +Aura* Unit::GetAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint32 reqEffMask) const { AuraApplication * aurApp = GetAuraApplication(spellId, casterGUID, itemCasterGUID, reqEffMask); return aurApp ? aurApp->GetBase() : NULL; } -AuraApplication * Unit::GetAuraApplicationOfRankedSpell(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask, AuraApplication* except) const +AuraApplication * Unit::GetAuraApplicationOfRankedSpell(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint32 reqEffMask, AuraApplication* except) const { uint32 rankSpell = sSpellMgr->GetFirstSpellInChain(spellId); while (rankSpell) @@ -4045,7 +4050,7 @@ AuraApplication * Unit::GetAuraApplicationOfRankedSpell(uint32 spellId, ObjectGu return NULL; } -Aura* Unit::GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask) const +Aura* Unit::GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint32 reqEffMask) const { AuraApplication * aurApp = GetAuraApplicationOfRankedSpell(spellId, casterGUID, itemCasterGUID, reqEffMask); return aurApp ? aurApp->GetBase() : NULL; @@ -4120,7 +4125,7 @@ uint32 Unit::GetAuraCount(uint32 spellId) const return count; } -bool Unit::HasAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask) const +bool Unit::HasAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint32 reqEffMask) const { if (GetAuraApplication(spellId, casterGUID, itemCasterGUID, reqEffMask)) return true; @@ -4199,9 +4204,9 @@ bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const if (spellInfo->Mechanic && (mechanicMask & (1 << spellInfo->Mechanic))) return true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (iter->second->HasEffect(i) && spellInfo->Effects[i].Effect && spellInfo->Effects[i].Mechanic) - if (mechanicMask & (1 << spellInfo->Effects[i].Mechanic)) + for (SpellEffectInfo const* effect : iter->second->GetBase()->GetSpellEffectInfos()) + if (effect && effect->Effect && effect->Mechanic) + if (mechanicMask & (1 << effect->Mechanic)) return true; } @@ -4724,22 +4729,20 @@ void Unit::RemoveAllGameObjects() void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage* log) { - WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16+4+4+4+1+4+4+1+1+4+4+1)); // we guess size - data << log->target->GetPackGUID(); - data << log->attacker->GetPackGUID(); - data << uint32(log->SpellID); - data << uint32(log->damage); // damage amount + WorldPackets::CombatLog::SpellNonMeleeDamageLog packet; + packet.Me = log->target->GetGUID(); + packet.CasterGUID = log->attacker->GetGUID(); + packet.SpellID = log->SpellID; + packet.Damage = log->damage; int32 overkill = log->damage - log->target->GetHealth(); - data << uint32(overkill > 0 ? overkill : 0); // overkill - data << uint8 (log->schoolMask); // damage school - data << uint32(log->absorb); // AbsorbedDamage - data << uint32(log->resist); // resist - data << uint8 (log->physicalLog); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name - data << uint8 (log->unused); // unused - data << uint32(log->blocked); // blocked - data << uint32(log->HitInfo); - data << uint8 (0); // flag to use extend data - SendMessageToSet(&data, true); + packet.Overkill = (overkill > 0 ? overkill : 0); + packet.SchoolMask = log->schoolMask; + packet.ShieldBlock = log->blocked; + packet.Resisted = log->resist; + packet.Absorbed = log->absorb; + packet.Periodic = false; + packet.Flags = log->HitInfo; + SendMessageToSet(packet.Write(), true); } void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit) @@ -4896,13 +4899,17 @@ bool Unit::HandleAuraProcOnPowerAmount(Unit* victim, uint32 /*damage*/, AuraEffe // Get effect index used for the proc uint32 effIndex = triggeredByAura->GetEffIndex(); + SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(); + if (!effect) + return false; + // Power amount required to proc the spell int32 powerAmountRequired = triggeredByAura->GetAmount(); // Power type required to proc - Powers powerRequired = Powers(auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].MiscValue); + Powers powerRequired = Powers(effect->MiscValue); // Set trigger spell id, target, custom basepoints - uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell; + uint32 trigger_spell_id = effect->TriggerSpell; Unit* target = NULL; int32 basepoints0 = 0; @@ -4932,7 +4939,7 @@ bool Unit::HandleAuraProcOnPowerAmount(Unit* victim, uint32 /*damage*/, AuraEffe } // not allow proc extra attack spell at extra attack - if (m_extraAttacks && triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) + if (m_extraAttacks && triggerEntry->HasEffect(GetMap()->GetDifficulty(), SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return false; if (!powerRequired || !powerAmountRequired) @@ -5578,18 +5585,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 28810; break; } - // Priest T10 Healer 2P Bonus - case 70770: - // Flash Heal - if (procSpell->SpellFamilyFlags[0] & 0x800) - { - triggered_spell_id = 70772; - SpellInfo const* blessHealing = sSpellMgr->GetSpellInfo(triggered_spell_id); - if (!blessHealing) - return false; - basepoints0 = int32(CalculatePct(damage, triggerAmount) / (blessHealing->GetMaxDuration() / blessHealing->Effects[0].ApplyAuraPeriod)); - } - break; + break; } break; } @@ -5707,7 +5703,10 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!triggeredSpell) return false; - basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraPeriod); + SpellEffectInfo const* effect = triggeredSpell->GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (!effect) + return false; + basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / effect->ApplyAuraPeriod); // Add remaining ticks to damage done basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE); } @@ -6091,7 +6090,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!triggeredSpell) return false; - basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraPeriod); + if (SpellEffectInfo const* effect = triggeredSpell->GetEffect(DIFFICULTY_NONE, EFFECT_0)) + basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / effect->ApplyAuraPeriod); } break; } @@ -6105,9 +6105,12 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!triggeredSpell) return false; - basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraPeriod); - // Add remaining ticks to healing done - basepoints0 += GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_HEAL); + if (SpellEffectInfo const* effect = triggeredSpell->GetEffect(DIFFICULTY_NONE, EFFECT_0)) + { + basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / effect->ApplyAuraPeriod); + // Add remaining ticks to healing done + basepoints0 += GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_HEAL); + } } break; } @@ -6149,53 +6152,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 63685; break; } - // Flametongue Weapon (Passive) - if (dummySpell->SpellFamilyFlags[0] & 0x200000) - { - if (GetTypeId() != TYPEID_PLAYER || !victim || !victim->IsAlive() || !castItem || !castItem->IsEquipped()) - return false; - - WeaponAttackType attType = WeaponAttackType(Player::GetAttackBySlot(castItem->GetSlot())); - if ((attType != BASE_ATTACK && attType != OFF_ATTACK) - || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK) - || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)) - return false; - - float fire_onhit = float(CalculatePct(dummySpell->Effects[EFFECT_0]. CalcValue(), 1.0f)); - - float add_spellpower = (float)(SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE) - + victim->SpellBaseDamageBonusTaken(SPELL_SCHOOL_MASK_FIRE)); - - // 1.3speed = 5%, 2.6speed = 10%, 4.0 speed = 15%, so, 1.0speed = 3.84% - ApplyPct(add_spellpower, 3.84f); - - // Enchant on Off-Hand and ready? - if (castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK) - { - float BaseWeaponSpeed = GetAttackTime(OFF_ATTACK) / 1000.0f; - - // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed - basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed)); - triggered_spell_id = 10444; - } - - // Enchant on Main-Hand and ready? - else if (castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK) - { - float BaseWeaponSpeed = GetAttackTime(BASE_ATTACK) / 1000.0f; - - // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed - basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed)); - triggered_spell_id = 10444; - } - - // If not ready, we should return, shouldn't we?! - else - return false; - - CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); - return true; - } // Static Shock if (dummySpell->SpellIconID == 3059) { @@ -6217,15 +6173,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } case SPELLFAMILY_DEATHKNIGHT: { - // Blood-Caked Blade - if (dummySpell->SpellIconID == 138) - { - if (!target || !target->IsAlive()) - return false; - - triggered_spell_id = dummySpell->Effects[effIndex].TriggerSpell; - break; - } // Dancing Rune Weapon if (dummySpell->Id == 49028) { @@ -6251,24 +6198,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere else return false; } - // Unholy Blight - if (dummySpell->Id == 49194) - { - triggered_spell_id = 50536; - SpellInfo const* unholyBlight = sSpellMgr->GetSpellInfo(triggered_spell_id); - if (!unholyBlight) - return false; - - basepoints0 = CalculatePct(int32(damage), triggerAmount); - - //Glyph of Unholy Blight - if (AuraEffect* glyph=GetAuraEffect(63332, 0)) - AddPct(basepoints0, glyph->GetAmount()); - - basepoints0 = basepoints0 / (unholyBlight->GetMaxDuration() / unholyBlight->Effects[0].ApplyAuraPeriod); - basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE); - break; - } // Threat of Thassarian if (dummySpell->SpellIconID == 2023) { @@ -6309,26 +6238,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } case SPELLFAMILY_PET: { - switch (dummySpell->SpellIconID) - { - // Guard Dog - case 201: - { - if (!victim) - return false; - - triggered_spell_id = 54445; - target = this; - float addThreat = float(CalculatePct(procSpell->Effects[0].CalcValue(this), triggerAmount)); - victim->AddThreat(this, addThreat); - break; - } - // Silverback - case 1582: - triggered_spell_id = dummySpell->Id == 62765 ? 62801 : 62800; - target = this; - break; - } break; } default: @@ -6337,7 +6246,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // if not handled by custom case, get triggered spell from dummySpell proto if (!triggered_spell_id) - triggered_spell_id = dummySpell->Effects[triggeredByAura->GetEffIndex()].TriggerSpell; + triggered_spell_id = triggeredByAura->GetSpellEffectInfo()->TriggerSpell; // processed charge only counting case if (!triggered_spell_id) @@ -6421,9 +6330,12 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura // Swift Hand of Justice case 59906: { - int32 bp0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_0]. CalcValue()); - CastCustomSpell(this, 59913, &bp0, NULL, NULL, true); - *handled = true; + if (SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(EFFECT_0)) + { + int32 bp0 = CalculatePct(GetMaxHealth(), effect->CalcValue()); + CastCustomSpell(this, 59913, &bp0, NULL, NULL, true); + *handled = true; + } break; } } @@ -6438,49 +6350,10 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura CastSpell(victim, 68055, true); return true; } - // Glyph of Divinity - else if (dummySpell->Id == 54939) - { - if (!procSpell) - return false; - *handled = true; - // Check if we are the target and prevent mana gain - if (victim && triggeredByAura->GetCasterGUID() == victim->GetGUID()) - return false; - // Lookup base amount mana restore - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) - { - if (procSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE) - { - // value multiplied by 2 because you should get twice amount - int32 mana = procSpell->Effects[i].CalcValue() * 2; - CastCustomSpell(this, 54986, 0, &mana, NULL, true); - } - } - return true; - } break; } case SPELLFAMILY_MAGE: { - switch (dummySpell->Id) - { - // Empowered Fire - case 31656: - case 31657: - case 31658: - { - *handled = true; - - SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(67545); - if (!spInfo) - return false; - - int32 bp0 = int32(CalculatePct(GetCreateMana(), spInfo->Effects[0].CalcValue())); - CastCustomSpell(this, 67545, &bp0, NULL, NULL, true, NULL, triggeredByAura->GetEffect(EFFECT_0), GetGUID()); - return true; - } - } break; } case SPELLFAMILY_DEATHKNIGHT: @@ -6565,8 +6438,11 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura // Item - Warrior T10 Protection 4P Bonus case 70844: { - int32 basepoints0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_1]. CalcValue()); - CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true); + if (SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(EFFECT_1)) + { + int32 basepoints0 = CalculatePct(GetMaxHealth(), effect->CalcValue()); + CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true); + } break; } // Recklessness @@ -6597,7 +6473,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg int32 triggerAmount = triggeredByAura->GetAmount(); // Set trigger spell id, target, custom basepoints - uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell; + uint32 trigger_spell_id = triggeredByAura->GetSpellEffectInfo()->TriggerSpell; Unit* target = NULL; int32 basepoints0 = 0; @@ -6617,11 +6493,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg case SPELLFAMILY_GENERIC: switch (auraSpellInfo->Id) { - case 43820: // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) - // Pct value stored in dummy - basepoints0 = victim->GetCreateHealth() * auraSpellInfo->Effects[1].CalcValue() / 100; - target = victim; - break; case 57345: // Darkmoon Card: Greatness { float stat = 0.0f; @@ -6722,19 +6593,9 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg } case SPELLFAMILY_HUNTER: { - if (auraSpellInfo->SpellIconID == 3247) // Piercing Shots + /*if (auraSpellInfo->SpellIconID == 3247) // Piercing Shots { - switch (auraSpellInfo->Id) - { - case 53234: // Rank 1 - case 53237: // Rank 2 - case 53238: // Rank 3 - trigger_spell_id = 63468; - break; - default: - TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Piercing Shots", auraSpellInfo->Id); - return false; - } + trigger_spell_id = 63468; // 6.x missing from dbc but it is in the tooltip SpellInfo const* TriggerPS = sSpellMgr->GetSpellInfo(trigger_spell_id); if (!TriggerPS) return false; @@ -6742,7 +6603,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg basepoints0 = CalculatePct(int32(damage), triggerAmount) / (TriggerPS->GetMaxDuration() / TriggerPS->Effects[0].ApplyAuraPeriod); basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_DAMAGE); break; - } + }*/ // Item - Hunter T9 4P Bonus if (auraSpellInfo->Id == 67151) { @@ -6865,7 +6726,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg } // not allow proc extra attack spell at extra attack - if (m_extraAttacks && triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) + if (m_extraAttacks && triggerEntry->HasEffect(GetMap()->GetDifficulty(), SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return false; // Custom requirements (not listed in procEx) Warning! damage dealing after this @@ -6945,10 +6806,9 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg break; } // Decimation - case 63156: - case 63158: + case 108869: // Can proc only if target has hp below 25% - if (!victim || !victim->HealthBelowPct(auraSpellInfo->Effects[EFFECT_1].CalcValue())) + if (!victim || !victim->HealthBelowPct(triggeredByAura->GetSpellEffectInfo()->CalcValue())) return false; break; // Deathbringer Saurfang - Blood Beast's Blood Link @@ -7082,7 +6942,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg return false; // extra attack should hit same target - if (triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) + if (triggerEntry->HasEffect(GetMap()->GetDifficulty(), SPELL_EFFECT_ADD_EXTRA_ATTACKS)) target = victim; // try detect target manually if not set @@ -7923,14 +7783,14 @@ void Unit::SetMinion(Minion *minion, bool apply) else if (minion->IsTotem()) { // All summoned by totem minions must disappear when it is removed. - if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell())) - for (int i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (spInfo->Effects[i].Effect != SPELL_EFFECT_SUMMON) - continue; + if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell())) + for (SpellEffectInfo const* effect : spInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) + { + if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) + continue; - RemoveAllMinionsByEntry(spInfo->Effects[i].MiscValue); - } + RemoveAllMinionsByEntry(effect->MiscValue); + } } if (GetTypeId() == TYPEID_PLAYER) @@ -8424,32 +8284,11 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin } // Custom scripted damage - switch (spellProto->SpellFamilyName) + /*switch (spellProto->SpellFamilyName) { case SPELLFAMILY_DEATHKNIGHT: - // Impurity (dummy effect) - if (GetTypeId() == TYPEID_PLAYER) - { - PlayerSpellMap playerSpells = ToPlayer()->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = playerSpells.begin(); itr != playerSpells.end(); ++itr) - { - if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) - continue; - switch (itr->first) - { - case 49220: - case 49633: - case 49635: - case 49636: - case 49638: - if (SpellInfo const* proto = sSpellMgr->GetSpellInfo(itr->first)) - AddPct(ApCoeffMod, proto->Effects[0].CalcValue()); - break; - } - } - } break; - } + }*/ // Done fixed damage bonus auras int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask()); @@ -9198,9 +9037,11 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - switch (spellProto->Effects[i].ApplyAuraName) + if (!effect) + continue; + switch (effect->ApplyAuraName) { // Bonus healing does not apply to these spells case SPELL_AURA_PERIODIC_LEECH: @@ -9208,7 +9049,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal = 0; break; } - if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH) + if (effect->Effect == SPELL_EFFECT_HEALTH_LEECH) DoneTotal = 0; } @@ -9363,17 +9204,19 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectingSpell(spellProto)) AddPct(TakenTotalMod, (*i)->GetAmount()); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - switch (spellProto->Effects[i].ApplyAuraName) + if (!effect) + continue; + switch (effect->ApplyAuraName) { // Bonus healing does not apply to these spells - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: - TakenTotal = 0; - break; + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + TakenTotal = 0; + break; } - if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH) + if (effect->Effect == SPELL_EFFECT_HEALTH_LEECH) TakenTotal = 0; } @@ -9406,7 +9249,7 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) const for (AuraEffectList::const_iterator i = mHealingDoneOfStatPercent.begin(); i != mHealingDoneOfStatPercent.end(); ++i) { // stat used dependent from misc value (stat index) - Stats usedStat = Stats((*i)->GetSpellInfo()->Effects[(*i)->GetEffIndex()].MiscValue); + Stats usedStat = Stats((*i)->GetSpellEffectInfo()->MiscValue); advertisedBenefit += int32(CalculatePct(GetStat(usedStat), (*i)->GetAmount())); } @@ -9504,13 +9347,13 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const } bool immuneToAllEffects = true; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { // State/effect immunities applied by aura expect full spell immunity // Ignore effects with mechanic, they are supposed to be checked separately - if (!spellInfo->Effects[i].IsEffect()) + if (!effect || !effect->IsEffect()) continue; - if (!IsImmunedToSpellEffect(spellInfo, i)) + if (!IsImmunedToSpellEffect(spellInfo, effect->EffectIndex)) { immuneToAllEffects = false; break; @@ -9538,20 +9381,24 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const { - if (!spellInfo || !spellInfo->Effects[index].IsEffect()) + if (!spellInfo) + return false; + + SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), index); + if (!effect || !effect->IsEffect()) return false; if (spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) return false; // If m_immuneToEffect type contain this effect type, IMMUNE effect. - uint32 effect = spellInfo->Effects[index].Effect; + uint32 eff = effect->Effect; SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT]; for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr) - if (itr->type == effect) + if (itr->type == eff) return true; - if (uint32 mechanic = spellInfo->Effects[index].Mechanic) + if (uint32 mechanic = effect->Mechanic) { SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) @@ -9559,7 +9406,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons return true; } - if (uint32 aura = spellInfo->Effects[index].ApplyAuraName) + if (uint32 aura = effect->ApplyAuraName) { SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE]; for (SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) @@ -9625,8 +9472,8 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType { bool normalized = false; if (spellProto) - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (spellProto->Effects[i].Effect == SPELL_EFFECT_NORMALIZED_WEAPON_DMG) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + if (effect && effect->Effect == SPELL_EFFECT_NORMALIZED_WEAPON_DMG) { normalized = true; break; @@ -10231,7 +10078,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo return false; // can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit. - if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))) + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficulty())) : !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficulty())))) return false; // can't attack dead @@ -10352,7 +10199,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co return false; // can't assist invisible - if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())) + if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficulty()))) return false; // can't assist dead @@ -11120,7 +10967,8 @@ float Unit::ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index // function uses real base points (typically value - 1) int32 Unit::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints) const { - return spellProto->Effects[effect_index].CalcValue(this, basePoints, target); + SpellEffectInfo const* effect = spellProto->GetEffect(GetMap()->GetDifficulty(), effect_index); + return effect ? effect->CalcValue(this, basePoints, target) : 0; } int32 Unit::CalcSpellDuration(SpellInfo const* spellProto) @@ -11208,7 +11056,8 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in sSpellMgr->IsSpellMemberOfSpellGroup(spellProto->Id, SPELL_GROUP_ELIXIR_BATTLE) || sSpellMgr->IsSpellMemberOfSpellGroup(spellProto->Id, SPELL_GROUP_ELIXIR_GUARDIAN))) { - if (target->HasAura(53042) && target->HasSpell(spellProto->Effects[0].TriggerSpell)) + SpellEffectInfo const* effect = spellProto->GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (target->HasAura(53042) && effect && target->HasSpell(effect->TriggerSpell)) duration *= 2; } } @@ -12456,10 +12305,17 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u SpellInfo const* spellProto = itr->second->GetBase()->GetSpellInfo(); // only auras that has triggered spell should proc from fully absorbed damage - if (procExtra & PROC_EX_ABSORB && isVictim) - if (damage || spellProto->Effects[EFFECT_0].TriggerSpell || spellProto->Effects[EFFECT_1].TriggerSpell || spellProto->Effects[EFFECT_2].TriggerSpell) - active = true; - + if (procExtra & PROC_EX_ABSORB && isVictim && damage) + { + for (SpellEffectInfo const* effect : itr->second->GetBase()->GetSpellEffectInfos()) + { + if (effect && effect->TriggerSpell) + { + active = true; + break; + } + } + } if (!IsTriggeredAtSpellProcEvent(target, triggerData.aura, procSpell, procFlag, procExtra, attType, isVictim, active, triggerData.spellProcEvent)) continue; @@ -12477,11 +12333,11 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u bool triggered = !(spellProto->AttributesEx3 & SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ? (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : itr->second->GetBase()->GetSpellEffectInfos()) { - if (itr->second->HasEffect(i)) + if (effect && effect->IsEffect()) { - AuraEffect* aurEff = itr->second->GetBase()->GetEffect(i); + AuraEffect* aurEff = itr->second->GetBase()->GetEffect(effect->EffectIndex); // Skip this auras if (isNonTriggerAura[aurEff->GetAuraType()]) continue; @@ -12490,7 +12346,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u continue; // Some spells must always trigger if (!triggered || isAlwaysTriggeredAura[aurEff->GetAuraType()]) - triggerData.effMask |= 1<<i; + triggerData.effMask |= 1<<effect->EffectIndex; } } if (triggerData.effMask) @@ -13133,9 +12989,11 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp bool DirectDamage = false; bool AreaEffect = false; - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; i++) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - switch (spellProto->Effects[i].Effect) + if (!effect) + continue; + switch (effect->Effect) { case SPELL_EFFECT_SCHOOL_DAMAGE: case SPELL_EFFECT_POWER_DRAIN: @@ -13146,7 +13004,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp DirectDamage = true; break; case SPELL_EFFECT_APPLY_AURA: - switch (spellProto->Effects[i].ApplyAuraName) + switch (effect->ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_HEAL: @@ -13163,7 +13021,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp break; } - if (spellProto->Effects[i].IsTargetingArea()) + if (effect->IsTargetingArea()) AreaEffect = true; } @@ -13190,10 +13048,12 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp CastingTime /= 2; // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if (spellProto->Effects[j].Effect == SPELL_EFFECT_HEALTH_LEECH || - (spellProto->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA && spellProto->Effects[j].ApplyAuraName == SPELL_AURA_PERIODIC_LEECH)) + if (!effect) + continue; + if (effect->Effect == SPELL_EFFECT_HEALTH_LEECH || + (effect->Effect == SPELL_EFFECT_APPLY_AURA && effect->ApplyAuraName == SPELL_AURA_PERIODIC_LEECH)) { CastingTime /= 2; break; @@ -13256,7 +13116,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect if (!spellInfo->IsChanneled() && DotDuration > 0) DotFactor = DotDuration / 15000.0f; - if (uint32 DotTicks = spellInfo->GetMaxTicks()) + if (uint32 DotTicks = spellInfo->GetMaxTicks(GetMap()->GetDifficulty())) DotFactor /= DotTicks; } @@ -13530,7 +13390,8 @@ bool Unit::HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura) { if (Unit* caster = triggeredByAura->GetCaster()) { - float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster); + SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(); + float radius = effect->CalcRadius(caster); if (Unit* target = GetNextRandomRaidMemberOrPet(radius)) { @@ -13582,7 +13443,8 @@ bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura) { if (Unit* caster = triggeredByAura->GetCaster()) { - float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster); + SpellEffectInfo const* effect = triggeredByAura->GetSpellEffectInfo(); + float radius = effect->CalcRadius(caster); if (Unit* target= GetNextRandomRaidMemberOrPet(radius)) { CastSpell(target, spellProto, true, NULL, triggeredByAura, caster_guid); @@ -14601,7 +14463,7 @@ Aura* Unit::AddAura(uint32 spellId, Unit* target) return AddAura(spellInfo, MAX_EFFECT_MASK, target); } -Aura* Unit::AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target) +Aura* Unit::AddAura(SpellInfo const* spellInfo, uint32 effMask, Unit* target) { if (!spellInfo) return NULL; @@ -15354,9 +15216,12 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) { uint8 i = 0; bool valid = false; - while (i < MAX_SPELL_EFFECTS && !valid) + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficulty())) { - if (spellEntry->Effects[i].ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE) + if (!effect) + continue; + + if (effect->ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE) { valid = true; break; @@ -15375,8 +15240,9 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) else // This can happen during Player::_LoadAuras { int32 bp0[MAX_SPELL_EFFECTS]; - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) - bp0[j] = spellEntry->Effects[j].BasePoints; + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + if (effect) + bp0[effect->EffectIndex] = effect->BasePoints; bp0[i] = seatId; Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, bp0, NULL, origCasterGUID); @@ -16588,9 +16454,9 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) // this also applies for transform auras if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(getTransForm())) - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (transform->Effects[i].IsAura(SPELL_AURA_TRANSFORM)) - if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(transform->Effects[i].MiscValue)) + for (SpellEffectInfo const* effect : transform->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + if (effect && effect->IsAura(SPELL_AURA_TRANSFORM)) + if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(effect->MiscValue)) { cinfo = transformInfo; break; @@ -16724,43 +16590,42 @@ int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEf bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications /*= false*/) { - for (uint32 i = 0 ; i < MAX_SPELL_EFFECTS; ++i) + for (AuraEffect* aurEff : aura->GetAuraEffects()) { - if (AuraEffect const* aurEff = aura->GetEffect(i)) + if (!aurEff) + continue; + AuraType const auraType = AuraType(aurEff->GetSpellEffectInfo()->ApplyAuraName); + AuraEffectList const& auras = GetAuraEffectsByType(auraType); + for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end();) { - AuraType const auraType = AuraType(aura->GetSpellInfo()->Effects[i].ApplyAuraName); - AuraEffectList const& auras = GetAuraEffectsByType(auraType); - for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end();) + AuraEffect const* existingAurEff = (*itr); + ++itr; + + if (sSpellMgr->CheckSpellGroupStackRules(aura->GetSpellInfo(), existingAurEff->GetSpellInfo()) + == SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST) { - AuraEffect const* existingAurEff = (*itr); - ++itr; + int32 diff = abs(aurEff->GetAmount()) - abs(existingAurEff->GetAmount()); + if (!diff) + diff = int32(aura->GetEffectMask()) - int32(existingAurEff->GetBase()->GetEffectMask()); - if (sSpellMgr->CheckSpellGroupStackRules(aura->GetSpellInfo(), existingAurEff->GetSpellInfo()) - == SPELL_GROUP_STACK_RULE_EXCLUSIVE_HIGHEST) + if (diff > 0) { - int32 diff = abs(aurEff->GetAmount()) - abs(existingAurEff->GetAmount()); - if (!diff) - diff = int32(aura->GetEffectMask()) - int32(existingAurEff->GetBase()->GetEffectMask()); - - if (diff > 0) + Aura const* base = existingAurEff->GetBase(); + // no removing of area auras from the original owner, as that completely cancels them + if (removeOtherAuraApplications && (!base->IsArea() || base->GetOwner() != this)) { - Aura const* base = existingAurEff->GetBase(); - // no removing of area auras from the original owner, as that completely cancels them - if (removeOtherAuraApplications && (!base->IsArea() || base->GetOwner() != this)) + if (AuraApplication* aurApp = existingAurEff->GetBase()->GetApplicationOfTarget(GetGUID())) { - if (AuraApplication* aurApp = existingAurEff->GetBase()->GetApplicationOfTarget(GetGUID())) - { - bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType); - uint32 removedAuras = m_removedAurasCount; - RemoveAura(aurApp); - if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras + 1) - itr = auras.begin(); - } + bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType, GetMap()->GetDifficulty()); + uint32 removedAuras = m_removedAurasCount; + RemoveAura(aurApp); + if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras + 1) + itr = auras.begin(); } } - else if (diff < 0) - return false; } + else if (diff < 0) + return false; } } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index de18ffeddab..95dfcc431f9 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -123,6 +123,36 @@ enum SpellValueMod SPELLVALUE_BASE_POINT0, SPELLVALUE_BASE_POINT1, SPELLVALUE_BASE_POINT2, + SPELLVALUE_BASE_POINT3, + SPELLVALUE_BASE_POINT4, + SPELLVALUE_BASE_POINT5, + SPELLVALUE_BASE_POINT6, + SPELLVALUE_BASE_POINT7, + SPELLVALUE_BASE_POINT8, + SPELLVALUE_BASE_POINT9, + SPELLVALUE_BASE_POINT10, + SPELLVALUE_BASE_POINT11, + SPELLVALUE_BASE_POINT12, + SPELLVALUE_BASE_POINT13, + SPELLVALUE_BASE_POINT14, + SPELLVALUE_BASE_POINT15, + SPELLVALUE_BASE_POINT16, + SPELLVALUE_BASE_POINT17, + SPELLVALUE_BASE_POINT18, + SPELLVALUE_BASE_POINT19, + SPELLVALUE_BASE_POINT20, + SPELLVALUE_BASE_POINT21, + SPELLVALUE_BASE_POINT22, + SPELLVALUE_BASE_POINT23, + SPELLVALUE_BASE_POINT24, + SPELLVALUE_BASE_POINT25, + SPELLVALUE_BASE_POINT26, + SPELLVALUE_BASE_POINT27, + SPELLVALUE_BASE_POINT28, + SPELLVALUE_BASE_POINT29, + SPELLVALUE_BASE_POINT30, + SPELLVALUE_BASE_POINT31, + SPELLVALUE_BASE_POINT_END, SPELLVALUE_RADIUS_MOD, SPELLVALUE_MAX_TARGETS, SPELLVALUE_AURA_STACK @@ -1604,7 +1634,7 @@ class Unit : public WorldObject void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* victim = NULL, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty); void CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* victim = NULL, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = NULL, AuraEffect const* triggeredByAura = NULL, ObjectGuid originalCaster = ObjectGuid::Empty); Aura* AddAura(uint32 spellId, Unit* target); - Aura* AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target); + Aura* AddAura(SpellInfo const* spellInfo, uint32 effMask, Unit* target); void SetAuraStack(uint32 spellId, Unit* target, uint32 stack); void SendPlaySpellVisualKit(uint32 id, uint32 unkParam); void BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown); @@ -1737,11 +1767,11 @@ class Unit : public WorldObject bool InitTamedPet(Pet* pet, uint8 level, uint32 spell_id); // aura apply/remove helpers - you should better not use these - Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); + Aura* _TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); void _AddAura(UnitAura* aura, Unit* caster); - AuraApplication * _CreateAuraApplication(Aura* aura, uint8 effMask); + AuraApplication * _CreateAuraApplication(Aura* aura, uint32 effMask); void _ApplyAuraEffect(Aura* aura, uint8 effIndex); - void _ApplyAura(AuraApplication * aurApp, uint8 effMask); + void _ApplyAura(AuraApplication * aurApp, uint32 effMask); void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode); void _UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode); void _RemoveNoStackAuraApplicationsDueToAura(Aura* aura); @@ -1754,21 +1784,21 @@ class Unit : public WorldObject AuraMap const& GetOwnedAuras() const { return m_ownedAuras; } void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - void RemoveOwnedAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void RemoveOwnedAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void RemoveOwnedAura(Aura* aura, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - Aura* GetOwnedAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, Aura* except = NULL) const; + Aura* GetOwnedAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, Aura* except = NULL) const; // m_appliedAuras container management AuraApplicationMap & GetAppliedAuras() { return m_appliedAuras; } AuraApplicationMap const& GetAppliedAuras() const { return m_appliedAuras; } void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); - void RemoveAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void RemoveAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(Aura* aur, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); - void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); void RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, ObjectGuid casterGUID, Unit* dispeller, uint8 chargesRemoved = 1); void RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, Unit* stealer); @@ -1803,17 +1833,17 @@ class Unit : public WorldObject AuraEffect* GetAuraEffect(AuraType type, SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID = ObjectGuid::Empty) const; AuraEffect* GetDummyAuraEffect(SpellFamilyNames name, uint32 iconId, uint8 effIndex) const; - AuraApplication * GetAuraApplication(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraApplication * except = NULL) const; - Aura* GetAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0) const; + AuraApplication * GetAuraApplication(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraApplication * except = NULL) const; + Aura* GetAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0) const; - AuraApplication * GetAuraApplicationOfRankedSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraApplication * except = NULL) const; - Aura* GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0) const; + AuraApplication * GetAuraApplicationOfRankedSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0, AuraApplication * except = NULL) const; + Aura* GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0) const; void GetDispellableAuraList(Unit* caster, uint32 dispelMask, DispelChargesList& dispelList); bool HasAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid caster = ObjectGuid::Empty) const; uint32 GetAuraCount(uint32 spellId) const; - bool HasAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0) const; + bool HasAura(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, ObjectGuid itemCasterGUID = ObjectGuid::Empty, uint32 reqEffMask = 0) const; bool HasAuraType(AuraType auraType) const; bool HasAuraTypeWithCaster(AuraType auratype, ObjectGuid caster) const; bool HasAuraTypeWithMiscvalue(AuraType auratype, int32 miscvalue) const; @@ -2035,7 +2065,7 @@ class Unit : public WorldObject bool IsImmunedToDamage(SpellInfo const* spellInfo) const; virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; // redefined in Creature - static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS); + bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS); uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK); uint32 CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const; void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 82f7ece4477..ae39c405e26 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -591,8 +591,8 @@ void ObjectMgr::LoadCreatureTemplateAddons() continue; } - if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr)); + if (AdditionalSpellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE)) + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_template_addon`.", entry, uint32(atol(*itr))); creatureAddon.auras[i++] = atoul(*itr); } @@ -1048,8 +1048,9 @@ void ObjectMgr::LoadCreatureAddons() continue; } - if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) - TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr)); + if (AdditionalSpellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_CONTROL_VEHICLE)) + TC_LOG_ERROR("sql.sql", "Creature (GUID: " UI64FMTD ") has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); + creatureAddon.auras[i++] = atoul(*itr); } @@ -3278,7 +3279,6 @@ void ObjectMgr::LoadPlayerInfo() } } - // Load playercreate skills TC_LOG_INFO("server.loading", "Loading Player Create Skill Data..."); { @@ -3353,8 +3353,8 @@ void ObjectMgr::LoadPlayerInfo() } } - // Load playercreate spells - TC_LOG_INFO("server.loading", "Loading Player Create Spell Data..."); + // Load playercreate custom spells + TC_LOG_INFO("server.loading", "Loading Player Create Custom Spell Data..."); { uint32 oldMSTime = getMSTime(); @@ -3362,7 +3362,7 @@ void ObjectMgr::LoadPlayerInfo() if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 player create spells. DB table `playercreateinfo_spell_custom` is empty."); + TC_LOG_ERROR("server.loading", ">> Loaded 0 player create custom spells. DB table `playercreateinfo_spell_custom` is empty."); } else { @@ -4529,12 +4529,12 @@ void ObjectMgr::LoadQuests() if (!spellInfo) continue; - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellInfo->Effects[j].Effect != SPELL_EFFECT_QUEST_COMPLETE) + if (!effect || effect->Effect != SPELL_EFFECT_QUEST_COMPLETE) continue; - uint32 quest_id = spellInfo->Effects[j].MiscValue; + uint32 quest_id = effect->MiscValue; Quest const* quest = GetQuestTemplate(quest_id); @@ -4939,7 +4939,8 @@ void ObjectMgr::LoadSpellScripts() uint8 i = (uint8)((uint32(itr->first) >> 24) & 0x000000FF); //check for correct spellEffect - if (!spellInfo->Effects[i].Effect || (spellInfo->Effects[i].Effect != SPELL_EFFECT_SCRIPT_EFFECT && spellInfo->Effects[i].Effect != SPELL_EFFECT_DUMMY)) + SpellEffectInfo const* effect = spellInfo->GetEffect(i); + if (effect && (!effect->Effect || (effect->Effect != SPELL_EFFECT_SCRIPT_EFFECT && effect->Effect != SPELL_EFFECT_DUMMY))) TC_LOG_ERROR("sql.sql", "Table `spell_scripts` - spell %u effect %u is not SPELL_EFFECT_SCRIPT_EFFECT or SPELL_EFFECT_DUMMY", spellId, i); } } @@ -4958,10 +4959,10 @@ void ObjectMgr::LoadEventScripts() // Load all possible script entries from spells for (uint32 i = 1; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(i)) - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) - if (spell->Effects[j].Effect == SPELL_EFFECT_SEND_EVENT) - if (spell->Effects[j].MiscValue) - evt_scripts.insert(spell->Effects[j].MiscValue); + for (SpellEffectInfo const* effect : spell->GetEffectsForDifficulty(DIFFICULTY_NONE)) + if (effect && effect->Effect == SPELL_EFFECT_SEND_EVENT) + if (effect->MiscValue) + evt_scripts.insert(effect->MiscValue); for (size_t path_idx = 0; path_idx < sTaxiPathNodesByPath.size(); ++path_idx) { @@ -8142,25 +8143,25 @@ void ObjectMgr::AddSpellToTrainer(uint32 ID, uint32 SpellID, uint32 MoneyCost, u // calculate learned spell for profession case when stored cast-spell trainerSpell.ReqAbility[0] = SpellID; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellinfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellinfo->Effects[i].Effect != SPELL_EFFECT_LEARN_SPELL) + if (!effect || effect->Effect != SPELL_EFFECT_LEARN_SPELL) continue; if (trainerSpell.ReqAbility[0] == SpellID) trainerSpell.ReqAbility[0] = 0; // player must be able to cast spell on himself - if (spellinfo->Effects[i].TargetA.GetTarget() != 0 && spellinfo->Effects[i].TargetA.GetTarget() != TARGET_UNIT_TARGET_ALLY - && spellinfo->Effects[i].TargetA.GetTarget() != TARGET_UNIT_TARGET_ANY && spellinfo->Effects[i].TargetA.GetTarget() != TARGET_UNIT_CASTER) + if (effect->TargetA.GetTarget() != 0 && effect->TargetA.GetTarget() != TARGET_UNIT_TARGET_ALLY + && effect->TargetA.GetTarget() != TARGET_UNIT_TARGET_ANY && effect->TargetA.GetTarget() != TARGET_UNIT_CASTER) { TC_LOG_ERROR("sql.sql", "Table `npc_trainer` has spell %u for trainer entry %u with learn effect which has incorrect target type, ignoring learn effect!", SpellID, ID); continue; } - trainerSpell.ReqAbility[i] = spellinfo->Effects[i].TriggerSpell; + trainerSpell.ReqAbility[effect->EffectIndex] = effect->TriggerSpell; - if (trainerSpell.ReqAbility[i]) + if (trainerSpell.ReqAbility[effect->EffectIndex]) { - SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(trainerSpell.ReqAbility[i]); + SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(trainerSpell.ReqAbility[effect->EffectIndex]); if (learnedSpellInfo && learnedSpellInfo->IsProfession()) data.trainerType = 2; } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 85e78071d01..9c4a2a5a2d1 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -54,7 +54,7 @@ Loot* Roll::getLoot() } Group::Group() : m_leaderGuid(), m_leaderName(""), m_groupType(GROUPTYPE_NORMAL), -m_dungeonDifficulty(DUNGEON_DIFFICULTY_NORMAL), m_raidDifficulty(RAID_DIFFICULTY_10MAN_NORMAL), +m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_10_N), m_bgGroup(NULL), m_bfGroup(NULL), m_lootMethod(FREE_FOR_ALL), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(), m_masterLooterGuid(), m_subGroupsCounts(NULL), m_guid(), m_counter(0), m_maxEnchantingLevel(0), m_dbStoreId(0) { @@ -111,8 +111,8 @@ bool Group::Create(Player* leader) m_looterGuid = leaderGuid; m_masterLooterGuid.Clear(); - m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL; - m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL; + m_dungeonDifficulty = DIFFICULTY_NORMAL; + m_raidDifficulty = DIFFICULTY_10_N; if (!isBGGroup() && !isBFGroup()) { @@ -182,13 +182,13 @@ void Group::LoadGroupFromDB(Field* fields) uint32 diff = fields[13].GetUInt8(); if (diff >= MAX_DUNGEON_DIFFICULTY) - m_dungeonDifficulty = DUNGEON_DIFFICULTY_NORMAL; + m_dungeonDifficulty = DIFFICULTY_NORMAL; else m_dungeonDifficulty = Difficulty(diff); uint32 r_diff = fields[14].GetUInt8(); if (r_diff >= MAX_RAID_DIFFICULTY) - m_raidDifficulty = RAID_DIFFICULTY_10MAN_NORMAL; + m_raidDifficulty = DIFFICULTY_10_N; else m_raidDifficulty = Difficulty(r_diff); @@ -2008,7 +2008,7 @@ void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo) if (method == INSTANCE_RESET_ALL) { // the "reset all instances" method can only reset normal maps - if (entry->IsRaid() || diff == DUNGEON_DIFFICULTY_HEROIC) + if (entry->IsRaid() || diff == DIFFICULTY_HEROIC) { ++itr; continue; diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index 097c47a228e..07258fbd976 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -1048,7 +1048,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke *data << uint32(aurApp->GetBase()->GetId()); *data << uint16(aurApp->GetFlags()); - if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) + if (aurApp->GetFlags() & AFLAG_SCALABLE) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { @@ -1150,7 +1150,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke *data << uint32(aurApp->GetBase()->GetId()); *data << uint16(aurApp->GetFlags()); - if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) + if (aurApp->GetFlags() & AFLAG_SCALABLE) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { @@ -1285,7 +1285,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) data << uint32(aurApp->GetBase()->GetId()); data << uint16(aurApp->GetFlags()); - if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) + if (aurApp->GetFlags() & AFLAG_SCALABLE) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { @@ -1338,7 +1338,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) data << uint32(aurApp->GetBase()->GetId()); data << uint16(aurApp->GetFlags()); - if (aurApp->GetFlags() & AFLAG_ANY_EFFECT_AMOUNT_SENT) + if (aurApp->GetFlags() & AFLAG_SCALABLE) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 3a48c29ce03..9598ce216fb 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -52,6 +52,7 @@ #include "Group.h" #include "AccountMgr.h" #include "Spell.h" +#include "SpellPackets.h" #include "BattlegroundMgr.h" #include "Battlefield.h" #include "BattlefieldMgr.h" @@ -1038,17 +1039,17 @@ int32 WorldSession::HandleEnableNagleAlgorithm() return 0; } -void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData) +void WorldSession::HandleSetActionButtonOpcode(WorldPackets::Spells::SetActionButton& packet) { - uint8 button; - uint32 packetData; - recvData >> button >> packetData; - TC_LOG_DEBUG("network", "CMSG_SET_ACTION_BUTTON Button: %u Data: %u", button, packetData); + uint32 action = ACTION_BUTTON_ACTION(packet.Action); + uint32 type = ACTION_BUTTON_TYPE(packet.Action); - if (!packetData) - GetPlayer()->removeActionButton(button); + TC_LOG_DEBUG("network", "CMSG_SET_ACTION_BUTTON Button: %u Action: %u Type: %u", packet.Index, action, type); + + if (!packet.Action) + GetPlayer()->removeActionButton(packet.Index); else - GetPlayer()->addActionButton(button, ACTION_BUTTON_ACTION(packetData), ACTION_BUTTON_TYPE(packetData)); + GetPlayer()->addActionButton(packet.Index, action, type); } void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/) diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 699d91c4cc9..652b548b3a2 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -312,9 +312,9 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe return; } - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect: spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) + if (effect && (effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY)) return; } @@ -752,10 +752,10 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) charmInfo->SetSpellAutocast(spellInfo, state != 0); } -void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) +void WorldSession::HandlePetCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest) { TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL"); - + /* ObjectGuid guid; uint8 castCount; uint32 spellId; @@ -835,7 +835,7 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) spell->finish(false); delete spell; - } + }*/ } void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName) diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index f0c1b28117b..278169c2d63 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -28,59 +28,22 @@ #include "WorldSession.h" #include "TalentPackets.h" -void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData) +void WorldSession::HandleLearnTalentOpcode(WorldPackets::Talent::LearnTalent& packet) { - /* TODO: 6.x update packet struct (note: LearnTalent no longer has rank argument) - uint32 talentId, requestedRank; - recvData >> talentId >> requestedRank; - - if (_player->LearnTalent(talentId, requestedRank)) - _player->SendTalentsInfoData(false);*/ + bool anythingLearned = false; + for (uint32 talentId : packet.Talents) + { + if (_player->LearnTalent(talentId)) + anythingLearned = true; + } + + if (anythingLearned) + _player->SendTalentsInfoData(); } void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) { - /* TODO: 6.x update packet struct TC_LOG_DEBUG("network", "CMSG_LEARN_PREVIEW_TALENTS"); - - int32 tabPage; - uint32 talentsCount; - recvPacket >> tabPage; // talent tree - - // prevent cheating (selecting new tree with points already in another) - if (tabPage >= 0) // -1 if player already has specialization - { - if (TalentTabEntry const* talentTabEntry = sTalentTabStore.LookupEntry(_player->GetPrimaryTalentTree(_player->GetActiveSpec()))) - { - if (talentTabEntry->tabpage != uint32(tabPage)) - { - recvPacket.rfinish(); - return; - } - } - } - - recvPacket >> talentsCount; - - uint32 talentId, talentRank; - - // Client has max 21 talents for tree for 3 trees, rounded up : 70 - uint32 const MaxTalentsCount = 70; - - for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i) - { - recvPacket >> talentId >> talentRank; - - if (!_player->LearnTalent(talentId, talentRank)) - { - recvPacket.rfinish(); - break; - } - } - - _player->SendTalentsInfoData(false); - - recvPacket.rfinish();*/ } void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index f7e6ae9349f..a6bd43f72c6 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -329,60 +329,71 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); } -void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) +void WorldSession::HandleCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest) { - uint32 spellId, glyphIndex; - uint8 castCount, castFlags; - recvPacket >> castCount; - recvPacket >> spellId; - recvPacket >> glyphIndex; - recvPacket >> castFlags; - - TC_LOG_DEBUG("network", "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u, data length = %u", castCount, spellId, castFlags, (uint32)recvPacket.size()); + TC_LOG_DEBUG("network", "WORLD: got cast spell packet, castCount: %u, spellId: %u, castFlags: %u", castRequest.CastID, castRequest.SpellID, castRequest.SendCastFlags); // ignore for remote control state (for player case) Unit* mover = _player->m_mover; if (mover != _player && mover->GetTypeId() == TYPEID_PLAYER) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(castRequest.SpellID); if (!spellInfo) { - TC_LOG_ERROR("network", "WORLD: unknown spell id %u", spellId); - recvPacket.rfinish(); // prevent spam at ignore packet + TC_LOG_ERROR("network", "WORLD: unknown spell id %u", castRequest.SpellID); return; } if (spellInfo->IsPassive()) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } Unit* caster = mover; - if (caster->GetTypeId() == TYPEID_UNIT && !caster->ToCreature()->HasSpell(spellId)) + if (caster->GetTypeId() == TYPEID_UNIT && !caster->ToCreature()->HasSpell(castRequest.SpellID)) { // If the vehicle creature does not have the spell but it allows the passenger to cast own spells // change caster to player and let him cast if (!_player->IsOnVehicle(caster) || spellInfo->CheckVehicle(_player) != SPELL_CAST_OK) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } caster = _player; } - if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(spellId)) + if (caster->GetTypeId() == TYPEID_PLAYER && !caster->ToPlayer()->HasActiveSpell(castRequest.SpellID)) { // not have spell in spellbook - recvPacket.rfinish(); // prevent spam at ignore packet return; } + + if (Player* plr = caster->ToPlayer()) + { + uint32 specId = plr->GetActiveTalentSpec(); + if (specId) + { + if (sSpecializationOverrideSpellMap.find(specId) != sSpecializationOverrideSpellMap.end()) + { + if (sSpecializationOverrideSpellMap[specId].find(castRequest.SpellID) != sSpecializationOverrideSpellMap[specId].end()) + { + SpellInfo const* newSpellInfo = sSpellMgr->GetSpellInfo(sSpecializationOverrideSpellMap[specId][castRequest.SpellID]); + if (newSpellInfo) + { + if (newSpellInfo->SpellLevel <= caster->getLevel()) + { + spellInfo = newSpellInfo; + castRequest.SpellID = newSpellInfo->Id; + } + } + } + } + } + } Unit::AuraEffectList swaps = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS); Unit::AuraEffectList const& swaps2 = mover->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2); @@ -398,7 +409,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) if (SpellInfo const* newInfo = sSpellMgr->GetSpellInfo((*itr)->GetAmount())) { spellInfo = newInfo; - spellId = newInfo->Id; + castRequest.SpellID = newInfo->Id; } break; } @@ -410,21 +421,20 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) if (spellInfo->IsAutoRepeatRangedSpell() && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) { - recvPacket.rfinish(); return; } // can't use our own spells when we're in possession of another unit, if (_player->isPossessing()) { - recvPacket.rfinish(); // prevent spam at ignore packet return; } // client provided targets - SpellCastTargets targets; - targets.Read(recvPacket, caster); - HandleClientCastFlags(recvPacket, castFlags, targets); + SpellCastTargets targets(caster, castRequest.TargetFlags, castRequest.UnitGuid, castRequest.ItemGuid, castRequest.SrcTransportGuid, castRequest.DstTransportGuid, castRequest.SrcPos, castRequest.DstPos, castRequest.Pitch, castRequest.Speed, castRequest.Name); + + + //HandleClientCastFlags(recvPacket, castFlags, targets); // auto-selection buff level base at target level (in spellInfo) if (targets.GetUnitTarget()) @@ -437,8 +447,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) } Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE, ObjectGuid::Empty, false); - spell->m_cast_count = castCount; // set count of casts - spell->m_glyphIndex = glyphIndex; + spell->m_cast_count = castRequest.CastID; // set count of casts + spell->m_glyphIndex = castRequest.Misc; // 6.x Misc is just a guess spell->prepare(&targets); } @@ -458,6 +468,10 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) uint32 spellId; recvPacket >> spellId; + ObjectGuid guid; + recvPacket >> guid; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) return; @@ -485,7 +499,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) _player->RemoveOwnedAura(spellId, ObjectGuid::Empty, 0, AURA_REMOVE_BY_CANCEL); // If spell being removed is a resource tracker, see if player was tracking both (herbs / minerals) and remove the other - if (sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES) && spellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES)) + if (sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES) && spellInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_TRACK_RESOURCES)) { Unit::AuraEffectList const& auraEffects = _player->GetAuraEffectsByType(SPELL_AURA_TRACK_RESOURCES); if (!auraEffects.empty()) @@ -760,14 +774,14 @@ void WorldSession::HandleRequestCategoryCooldowns(WorldPacket& /*recvPacket*/) void WorldSession::SendSpellCategoryCooldowns() { - WorldPackets::Spell::CategoryCooldown cooldowns; + WorldPackets::Spells::CategoryCooldown cooldowns; Unit::AuraEffectList const& categoryCooldownAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN); for (AuraEffect* aurEff : categoryCooldownAuras) { uint32 categoryId = aurEff->GetMiscValue(); auto cItr = std::find_if(cooldowns.CategoryCooldowns.begin(), cooldowns.CategoryCooldowns.end(), - [categoryId](WorldPackets::Spell::CategoryCooldown::CategoryCooldownInfo const& cooldown) + [categoryId](WorldPackets::Spells::CategoryCooldown::CategoryCooldownInfo const& cooldown) { return cooldown.Category == categoryId; }); diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 9aef1b62f7c..27b362faf90 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -96,7 +96,7 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance { // initialize reset time // for normal instances if no creatures are killed the instance will reset in two hours - if (entry->IsRaid() || difficulty > DUNGEON_DIFFICULTY_NORMAL) + if (entry->IsRaid() || difficulty > DIFFICULTY_NORMAL) resetTime = GetResetTimeFor(mapId, difficulty); else { @@ -213,7 +213,7 @@ time_t InstanceSave::GetResetTimeForDB() { // only save the reset time for normal instances const MapEntry* entry = sMapStore.LookupEntry(GetMapId()); - if (!entry || entry->IsRaid() || GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC) + if (!entry || entry->IsRaid() || GetDifficulty() == DIFFICULTY_HEROIC) return 0; else return GetResetTime(); diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index b2c86d5152b..70db53ced8d 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -175,7 +175,7 @@ class InstanceSaveManager uint16 mapid; uint16 instanceId; - InstResetEvent() : type(0), difficulty(DUNGEON_DIFFICULTY_NORMAL), mapid(0), instanceId(0) { } + InstResetEvent() : type(0), difficulty(DIFFICULTY_NORMAL), mapid(0), instanceId(0) { } InstResetEvent(uint8 t, uint32 _mapid, Difficulty d, uint16 _instanceid) : type(t), difficulty(d), mapid(_mapid), instanceId(_instanceid) { } bool operator == (const InstResetEvent& e) const { return e.instanceId == instanceId; } diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 091fbb95aa5..7b7a0d5558d 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -386,15 +386,15 @@ class Map : public GridRefManager<NGridType> // have meaning only for instanced map (that have set real difficulty) Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); } - bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; } + bool IsRegularDifficulty() const { return GetDifficulty() == DIFFICULTY_NONE; } MapDifficulty const* GetMapDifficulty() const; bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); } bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); } bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); } bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); } - bool IsRaidOrHeroicDungeon() const { return IsRaid() || i_spawnMode > DUNGEON_DIFFICULTY_NORMAL; } - bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; } + bool IsRaidOrHeroicDungeon() const { return IsRaid() || i_spawnMode > DIFFICULTY_NORMAL; } + bool IsHeroic() const { return IsRaid() ? i_spawnMode >= DIFFICULTY_10_HC : i_spawnMode >= DIFFICULTY_HEROIC; } bool Is25ManRaid() const { return IsRaid() && i_spawnMode & RAID_DIFFICULTY_MASK_25MAN; } // since 25man difficulties are 1 and 3, we can check them like that bool IsBattleground() const { return i_mapEntry && i_mapEntry->IsBattleground(); } bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 8dfa4449e12..48e5161bcf1 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -27,7 +27,7 @@ #include "Group.h" #include "Player.h" -MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DUNGEON_DIFFICULTY_NORMAL) +MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DIFFICULTY_NORMAL) { // fill with zero memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_GRIDS*sizeof(uint16)); @@ -227,7 +227,7 @@ BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battlegroun TC_LOG_DEBUG("maps", "MapInstanced::CreateBattleground: map bg %d for %d created.", InstanceId, GetId()); - BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, REGULAR_DIFFICULTY); + BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, DIFFICULTY_NONE); ASSERT(map->IsBattlegroundOrArena()); map->SetBG(bg); bg->SetBgMap(map); diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index ac9e5918442..92d7335c7de 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -78,7 +78,7 @@ Map* MapManager::CreateBaseMap(uint32 id) map = new MapInstanced(id, i_gridCleanUpDelay); else { - map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); + map = new Map(id, i_gridCleanUpDelay, 0, DIFFICULTY_NONE); map->LoadRespawnTimes(); } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 7b6ca00416c..bd91d9321ea 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -27,7 +27,36 @@ enum SpellEffIndex { EFFECT_0 = 0, EFFECT_1 = 1, - EFFECT_2 = 2 + EFFECT_2 = 2, + EFFECT_3 = 3, + EFFECT_4 = 4, + EFFECT_5 = 5, + EFFECT_6 = 6, + EFFECT_7 = 7, + EFFECT_8 = 8, + EFFECT_9 = 9, + EFFECT_10 = 10, + EFFECT_11 = 11, + EFFECT_12 = 12, + EFFECT_13 = 13, + EFFECT_14 = 14, + EFFECT_15 = 15, + EFFECT_16 = 16, + EFFECT_17 = 17, + EFFECT_18 = 18, + EFFECT_19 = 19, + EFFECT_20 = 20, + EFFECT_21 = 21, + EFFECT_22 = 22, + EFFECT_23 = 23, + EFFECT_24 = 24, + EFFECT_25 = 25, + EFFECT_26 = 26, + EFFECT_27 = 27, + EFFECT_28 = 28, + EFFECT_29 = 29, + EFFECT_30 = 30, + EFFECT_31 = 31 }; // used in script definitions @@ -975,7 +1004,7 @@ enum Team TEAM_OTHER = 0 // if ReputationListId > 0 && Flags != FACTION_FLAG_TEAM_HEADER }; -enum SpellEffects +enum SpellEffectName { SPELL_EFFECT_INSTAKILL = 1, SPELL_EFFECT_SCHOOL_DAMAGE = 2, @@ -1159,10 +1188,72 @@ enum SpellEffects SPELL_EFFECT_180 = 180, // Unused (4.3.4) SPELL_EFFECT_181 = 181, // Unused (4.3.4) SPELL_EFFECT_182 = 182, - TOTAL_SPELL_EFFECTS = 183, + SPELL_EFFECT_183 = 183, + SPELL_EFFECT_184 = 184, + SPELL_EFFECT_185 = 185, + SPELL_EFFECT_186 = 186, + SPELL_EFFECT_187 = 187, + SPELL_EFFECT_188 = 188, + SPELL_EFFECT_189 = 189, + SPELL_EFFECT_190 = 190, + SPELL_EFFECT_191 = 191, + SPELL_EFFECT_192 = 192, + SPELL_EFFECT_193 = 193, + SPELL_EFFECT_194 = 194, + SPELL_EFFECT_195 = 195, + SPELL_EFFECT_196 = 196, + SPELL_EFFECT_197 = 197, + SPELL_EFFECT_198 = 198, + SPELL_EFFECT_199 = 199, + SPELL_EFFECT_200 = 200, + SPELL_EFFECT_201 = 201, + SPELL_EFFECT_202 = 202, + SPELL_EFFECT_203 = 203, + SPELL_EFFECT_204 = 204, + SPELL_EFFECT_205 = 205, + SPELL_EFFECT_206 = 206, + SPELL_EFFECT_207 = 207, + SPELL_EFFECT_208 = 208, + SPELL_EFFECT_209 = 209, + SPELL_EFFECT_210 = 210, + SPELL_EFFECT_211 = 211, + SPELL_EFFECT_212 = 212, + SPELL_EFFECT_213 = 213, + SPELL_EFFECT_214 = 214, + SPELL_EFFECT_215 = 215, + SPELL_EFFECT_216 = 216, + SPELL_EFFECT_217 = 217, + SPELL_EFFECT_218 = 218, + SPELL_EFFECT_219 = 219, + SPELL_EFFECT_220 = 220, + SPELL_EFFECT_221 = 221, + SPELL_EFFECT_222 = 222, + SPELL_EFFECT_223 = 223, + SPELL_EFFECT_224 = 224, + SPELL_EFFECT_225 = 225, + SPELL_EFFECT_226 = 226, + SPELL_EFFECT_227 = 227, + SPELL_EFFECT_228 = 228, + SPELL_EFFECT_229 = 229, + SPELL_EFFECT_230 = 230, + SPELL_EFFECT_231 = 231, + SPELL_EFFECT_232 = 232, + SPELL_EFFECT_233 = 233, + SPELL_EFFECT_234 = 234, + SPELL_EFFECT_235 = 235, + SPELL_EFFECT_236 = 236, + SPELL_EFFECT_237 = 237, + SPELL_EFFECT_238 = 238, + SPELL_EFFECT_239 = 239, + SPELL_EFFECT_240 = 240, + SPELL_EFFECT_241 = 241, + SPELL_EFFECT_242 = 242, + SPELL_EFFECT_243 = 243, + SPELL_EFFECT_244 = 244, + TOTAL_SPELL_EFFECTS = 245, }; -enum SpellCastResult // (6.0) +enum SpellCastResult // 19116 { SPELL_FAILED_SUCCESS = 0, SPELL_FAILED_AFFECTING_COMBAT = 1, @@ -1208,203 +1299,224 @@ enum SpellCastResult // (6.0) SPELL_FAILED_GARRISON_OWNED = 41, SPELL_FAILED_GARRISON_MAX_LEVEL = 42, SPELL_FAILED_GARRISON_NOT_UPGRADEABLE = 43, - SPELL_FAILED_HIGHLEVEL = 44, - SPELL_FAILED_HUNGER_SATIATED = 45, - SPELL_FAILED_IMMUNE = 46, - SPELL_FAILED_INCORRECT_AREA = 47, - SPELL_FAILED_INTERRUPTED = 48, - SPELL_FAILED_INTERRUPTED_COMBAT = 49, - SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 50, - SPELL_FAILED_ITEM_GONE = 51, - SPELL_FAILED_ITEM_NOT_FOUND = 52, - SPELL_FAILED_ITEM_NOT_READY = 53, - SPELL_FAILED_LEVEL_REQUIREMENT = 54, - SPELL_FAILED_LINE_OF_SIGHT = 55, - SPELL_FAILED_LOWLEVEL = 56, - SPELL_FAILED_LOW_CASTLEVEL = 57, - SPELL_FAILED_MAINHAND_EMPTY = 58, - SPELL_FAILED_MOVING = 59, - SPELL_FAILED_NEED_AMMO = 60, - SPELL_FAILED_NEED_AMMO_POUCH = 61, - SPELL_FAILED_NEED_EXOTIC_AMMO = 62, - SPELL_FAILED_NEED_MORE_ITEMS = 63, - SPELL_FAILED_NOPATH = 64, - SPELL_FAILED_NOT_BEHIND = 65, - SPELL_FAILED_NOT_FISHABLE = 66, - SPELL_FAILED_NOT_FLYING = 67, - SPELL_FAILED_NOT_HERE = 68, - SPELL_FAILED_NOT_INFRONT = 69, - SPELL_FAILED_NOT_IN_CONTROL = 70, - SPELL_FAILED_NOT_KNOWN = 71, - SPELL_FAILED_NOT_MOUNTED = 72, - SPELL_FAILED_NOT_ON_TAXI = 73, - SPELL_FAILED_NOT_ON_TRANSPORT = 74, - SPELL_FAILED_NOT_READY = 75, - SPELL_FAILED_NOT_SHAPESHIFT = 76, - SPELL_FAILED_NOT_STANDING = 77, - SPELL_FAILED_NOT_TRADEABLE = 78, - SPELL_FAILED_NOT_TRADING = 79, - SPELL_FAILED_NOT_UNSHEATHED = 80, - SPELL_FAILED_NOT_WHILE_GHOST = 81, - SPELL_FAILED_NOT_WHILE_LOOTING = 82, - SPELL_FAILED_NO_AMMO = 83, - SPELL_FAILED_NO_CHARGES_REMAIN = 84, - SPELL_FAILED_NO_CHAMPION = 85, - SPELL_FAILED_NO_COMBO_POINTS = 86, - SPELL_FAILED_NO_DUELING = 87, - SPELL_FAILED_NO_ENDURANCE = 88, - SPELL_FAILED_NO_FISH = 89, - SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 90, - SPELL_FAILED_NO_MOUNTS_ALLOWED = 91, - SPELL_FAILED_NO_PET = 92, - SPELL_FAILED_NO_POWER = 93, - SPELL_FAILED_NOTHING_TO_DISPEL = 94, - SPELL_FAILED_NOTHING_TO_STEAL = 95, - SPELL_FAILED_ONLY_ABOVEWATER = 96, - SPELL_FAILED_ONLY_DAYTIME = 97, - SPELL_FAILED_ONLY_INDOORS = 98, - SPELL_FAILED_ONLY_MOUNTED = 99, - SPELL_FAILED_ONLY_NIGHTTIME = 100, - SPELL_FAILED_ONLY_OUTDOORS = 101, - SPELL_FAILED_ONLY_SHAPESHIFT = 102, - SPELL_FAILED_ONLY_STEALTHED = 103, - SPELL_FAILED_ONLY_UNDERWATER = 104, - SPELL_FAILED_OUT_OF_RANGE = 105, - SPELL_FAILED_PACIFIED = 106, - SPELL_FAILED_POSSESSED = 107, - SPELL_FAILED_REAGENTS = 108, - SPELL_FAILED_REQUIRES_AREA = 109, - SPELL_FAILED_REQUIRES_SPELL_FOCUS = 110, - SPELL_FAILED_ROOTED = 111, - SPELL_FAILED_SILENCED = 112, - SPELL_FAILED_SPELL_IN_PROGRESS = 113, - SPELL_FAILED_SPELL_LEARNED = 114, - SPELL_FAILED_SPELL_UNAVAILABLE = 115, - SPELL_FAILED_STUNNED = 116, - SPELL_FAILED_TARGETS_DEAD = 117, - SPELL_FAILED_TARGET_AFFECTING_COMBAT = 118, - SPELL_FAILED_TARGET_AURASTATE = 119, - SPELL_FAILED_TARGET_DUELING = 120, - SPELL_FAILED_TARGET_ENEMY = 121, - SPELL_FAILED_TARGET_ENRAGED = 122, - SPELL_FAILED_TARGET_FRIENDLY = 123, - SPELL_FAILED_TARGET_IN_COMBAT = 124, - SPELL_FAILED_TARGET_IN_PET_BATTLE = 125, - SPELL_FAILED_TARGET_IS_PLAYER = 126, - SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 127, - SPELL_FAILED_TARGET_NOT_DEAD = 128, - SPELL_FAILED_TARGET_NOT_IN_PARTY = 129, - SPELL_FAILED_TARGET_NOT_LOOTED = 130, - SPELL_FAILED_TARGET_NOT_PLAYER = 131, - SPELL_FAILED_TARGET_NO_POCKETS = 132, - SPELL_FAILED_TARGET_NO_WEAPONS = 133, - SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 134, - SPELL_FAILED_TARGET_UNSKINNABLE = 135, - SPELL_FAILED_THIRST_SATIATED = 136, - SPELL_FAILED_TOO_CLOSE = 137, - SPELL_FAILED_TOO_MANY_OF_ITEM = 138, - SPELL_FAILED_TOTEM_CATEGORY = 139, - SPELL_FAILED_TOTEMS = 140, - SPELL_FAILED_TRY_AGAIN = 141, - SPELL_FAILED_UNIT_NOT_BEHIND = 142, - SPELL_FAILED_UNIT_NOT_INFRONT = 143, - SPELL_FAILED_VISION_OBSCURED = 144, - SPELL_FAILED_WRONG_PET_FOOD = 145, - SPELL_FAILED_NOT_WHILE_FATIGUED = 146, - SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 147, - SPELL_FAILED_NOT_WHILE_TRADING = 148, - SPELL_FAILED_TARGET_NOT_IN_RAID = 149, - SPELL_FAILED_TARGET_FREEFORALL = 150, - SPELL_FAILED_NO_EDIBLE_CORPSES = 151, - SPELL_FAILED_ONLY_BATTLEGROUNDS = 152, - SPELL_FAILED_TARGET_NOT_GHOST = 153, - SPELL_FAILED_TRANSFORM_UNUSABLE = 154, - SPELL_FAILED_WRONG_WEATHER = 155, - SPELL_FAILED_DAMAGE_IMMUNE = 156, - SPELL_FAILED_PREVENTED_BY_MECHANIC = 157, - SPELL_FAILED_PLAY_TIME = 158, - SPELL_FAILED_REPUTATION = 159, - SPELL_FAILED_MIN_SKILL = 160, - SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND = 161, - SPELL_FAILED_NOT_ON_SHAPESHIFT = 162, - SPELL_FAILED_NOT_ON_STEALTHED = 163, - SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 164, - SPELL_FAILED_NOT_ON_MOUNTED = 165, - SPELL_FAILED_TOO_SHALLOW = 166, - SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 167, - SPELL_FAILED_TARGET_IS_TRIVIAL = 168, - SPELL_FAILED_BM_OR_INVISGOD = 169, - SPELL_FAILED_GROUND_MOUNT_NOT_ALLOWED = 170, - SPELL_FAILED_FLOATING_MOUNT_NOT_ALLOWED = 171, - SPELL_FAILED_UNDERWATER_MOUNT_NOT_ALLOWED = 172, - SPELL_FAILED_FLYING_MOUNT_NOT_ALLOWED = 173, - SPELL_FAILED_APPRENTICE_RIDING_REQUIREMENT = 174, - SPELL_FAILED_JOURNEYMAN_RIDING_REQUIREMENT = 175, - SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 176, - SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 177, - SPELL_FAILED_MASTER_RIDING_REQUIREMENT = 178, - SPELL_FAILED_COLD_RIDING_REQUIREMENT = 179, - SPELL_FAILED_FLIGHT_MASTER_RIDING_REQUIREMENT = 180, - SPELL_FAILED_CS_RIDING_REQUIREMENT = 181, - SPELL_FAILED_PANDA_RIDING_REQUIREMENT = 182, - SPELL_FAILED_MOUNT_NO_FLOAT_HERE = 183, - SPELL_FAILED_MOUNT_NO_UNDERWATER_HERE = 184, - SPELL_FAILED_MOUNT_ABOVE_WATER_HERE = 185, - SPELL_FAILED_MOUNT_COLLECTED_ON_OTHER_CHAR = 186, - SPELL_FAILED_NOT_IDLE = 187, - SPELL_FAILED_NOT_INACTIVE = 188, - SPELL_FAILED_PARTIAL_PLAYTIME = 189, - SPELL_FAILED_NO_PLAYTIME = 190, - SPELL_FAILED_NOT_IN_BATTLEGROUND = 191, - SPELL_FAILED_NOT_IN_RAID_INSTANCE = 192, - SPELL_FAILED_ONLY_IN_ARENA = 193, - SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 194, - SPELL_FAILED_ON_USE_ENCHANT = 195, - SPELL_FAILED_NOT_ON_GROUND = 196, - SPELL_FAILED_CUSTOM_ERROR = 197, - SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 198, - SPELL_FAILED_TOO_MANY_SOCKETS = 199, - SPELL_FAILED_INVALID_GLYPH = 200, - SPELL_FAILED_UNIQUE_GLYPH = 201, - SPELL_FAILED_GLYPH_SOCKET_LOCKED = 202, - SPELL_FAILED_GLYPH_EXCLUSIVE_CATEGORY = 203, - SPELL_FAILED_GLYPH_INVALID_SPEC = 204, - SPELL_FAILED_GLYPH_NO_SPEC = 205, - SPELL_FAILED_NO_VALID_TARGETS = 206, - SPELL_FAILED_ITEM_AT_MAX_CHARGES = 207, - SPELL_FAILED_NOT_IN_BARBERSHOP = 208, - SPELL_FAILED_FISHING_TOO_LOW = 209, - SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 210, - SPELL_FAILED_SUMMON_PENDING = 211, - SPELL_FAILED_MAX_SOCKETS = 212, - SPELL_FAILED_PET_CAN_RENAME = 213, - SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 214, - SPELL_FAILED_TARGET_HAS_RESURRECT_PENDING = 215, - SPELL_FAILED_NO_ACTIONS = 216, - SPELL_FAILED_CURRENCY_WEIGHT_MISMATCH = 217, - SPELL_FAILED_WEIGHT_NOT_ENOUGH = 218, - SPELL_FAILED_WEIGHT_TOO_MUCH = 219, - SPELL_FAILED_NO_VACANT_SEAT = 220, - SPELL_FAILED_NO_LIQUID = 221, - SPELL_FAILED_ONLY_NOT_SWIMMING = 222, - SPELL_FAILED_BY_NOT_MOVING = 223, - SPELL_FAILED_IN_COMBAT_RES_LIMIT_REACHED = 224, - SPELL_FAILED_NOT_IN_ARENA = 225, - SPELL_FAILED_TARGET_NOT_GROUNDED = 226, - SPELL_FAILED_EXCEEDED_WEEKLY_USAGE = 227, - SPELL_FAILED_NOT_IN_LFG_DUNGEON = 228, - SPELL_FAILED_BAD_TARGET_FILTER = 229, - SPELL_FAILED_NOT_ENOUGH_TARGETS = 230, - SPELL_FAILED_NO_SPEC = 231, - SPELL_FAILED_CANT_ADD_BATTLE_PET = 232, - SPELL_FAILED_CANT_UPGRADE_BATTLE_PET = 233, - SPELL_FAILED_WRONG_BATTLE_PET_TYPE = 234, - SPELL_FAILED_NO_DUNGEON_ENCOUNTER = 235, - SPELL_FAILED_NO_TELEPORT_FROM_DUNGEON = 236, - SPELL_FAILED_MAX_LEVEL_TOO_LOW = 237, - SPELL_FAILED_CANT_REPLACE_ITEM_BONUS = 238, - SPELL_FAILED_UNKNOWN = 254, // custom value, default case - SPELL_CAST_OK = 255 // custom value, must not be sent to client + SPELL_FAILED_GARRISON_FOLLOWER_ON_MISSION = 44, + SPELL_FAILED_GARRISON_FOLLOWER_IN_BUILDING = 45, + SPELL_FAILED_GARRISON_FOLLOWER_MAX_LEVEL = 46, + SPELL_FAILED_GARRISON_FOLLOWER_MAX_ITEM_LEVEL = 47, + SPELL_FAILED_GARRISON_FOLLOWER_MAX_QUALITY = 48, + SPELL_FAILED_GARRISON_FOLLOWER_NOT_MAX_LEVEL = 49, + SPELL_FAILED_GARRISON_FOLLOWER_HAS_ABILITY = 50, + SPELL_FAILED_GARRISON_FOLLOWER_NO_OVERRIDEABLE_ABILITY = 51, + SPELL_FAILED_HIGHLEVEL = 52, + SPELL_FAILED_HUNGER_SATIATED = 53, + SPELL_FAILED_IMMUNE = 54, + SPELL_FAILED_INCORRECT_AREA = 55, + SPELL_FAILED_INTERRUPTED = 56, + SPELL_FAILED_INTERRUPTED_COMBAT = 57, + SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 58, + SPELL_FAILED_ITEM_GONE = 59, + SPELL_FAILED_ITEM_NOT_FOUND = 60, + SPELL_FAILED_ITEM_NOT_READY = 61, + SPELL_FAILED_LEVEL_REQUIREMENT = 62, + SPELL_FAILED_LINE_OF_SIGHT = 63, + SPELL_FAILED_LOWLEVEL = 64, + SPELL_FAILED_LOW_CASTLEVEL = 65, + SPELL_FAILED_MAINHAND_EMPTY = 66, + SPELL_FAILED_MOVING = 67, + SPELL_FAILED_NEED_AMMO = 68, + SPELL_FAILED_NEED_AMMO_POUCH = 69, + SPELL_FAILED_NEED_EXOTIC_AMMO = 70, + SPELL_FAILED_NEED_MORE_ITEMS = 71, + SPELL_FAILED_NOPATH = 72, + SPELL_FAILED_NOT_BEHIND = 73, + SPELL_FAILED_NOT_FISHABLE = 74, + SPELL_FAILED_NOT_FLYING = 75, + SPELL_FAILED_NOT_HERE = 76, + SPELL_FAILED_NOT_INFRONT = 77, + SPELL_FAILED_NOT_IN_CONTROL = 78, + SPELL_FAILED_NOT_KNOWN = 79, + SPELL_FAILED_NOT_MOUNTED = 80, + SPELL_FAILED_NOT_ON_TAXI = 81, + SPELL_FAILED_NOT_ON_TRANSPORT = 82, + SPELL_FAILED_NOT_READY = 83, + SPELL_FAILED_NOT_SHAPESHIFT = 84, + SPELL_FAILED_NOT_STANDING = 85, + SPELL_FAILED_NOT_TRADEABLE = 86, + SPELL_FAILED_NOT_TRADING = 87, + SPELL_FAILED_NOT_UNSHEATHED = 88, + SPELL_FAILED_NOT_WHILE_GHOST = 89, + SPELL_FAILED_NOT_WHILE_LOOTING = 90, + SPELL_FAILED_NO_AMMO = 91, + SPELL_FAILED_NO_CHARGES_REMAIN = 92, + SPELL_FAILED_NO_CHAMPION = 93, + SPELL_FAILED_NO_COMBO_POINTS = 94, + SPELL_FAILED_NO_DUELING = 95, + SPELL_FAILED_NO_ENDURANCE = 96, + SPELL_FAILED_NO_FISH = 97, + SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 98, + SPELL_FAILED_NO_MOUNTS_ALLOWED = 99, + SPELL_FAILED_NO_PET = 100, + SPELL_FAILED_NO_POWER = 101, + SPELL_FAILED_NOTHING_TO_DISPEL = 102, + SPELL_FAILED_NOTHING_TO_STEAL = 103, + SPELL_FAILED_ONLY_ABOVEWATER = 104, + SPELL_FAILED_ONLY_DAYTIME = 105, + SPELL_FAILED_ONLY_INDOORS = 106, + SPELL_FAILED_ONLY_MOUNTED = 107, + SPELL_FAILED_ONLY_NIGHTTIME = 108, + SPELL_FAILED_ONLY_OUTDOORS = 109, + SPELL_FAILED_ONLY_SHAPESHIFT = 110, + SPELL_FAILED_ONLY_STEALTHED = 111, + SPELL_FAILED_ONLY_UNDERWATER = 112, + SPELL_FAILED_OUT_OF_RANGE = 113, + SPELL_FAILED_PACIFIED = 114, + SPELL_FAILED_POSSESSED = 115, + SPELL_FAILED_REAGENTS = 116, + SPELL_FAILED_REQUIRES_AREA = 117, + SPELL_FAILED_REQUIRES_SPELL_FOCUS = 118, + SPELL_FAILED_ROOTED = 119, + SPELL_FAILED_SILENCED = 120, + SPELL_FAILED_SPELL_IN_PROGRESS = 121, + SPELL_FAILED_SPELL_LEARNED = 122, + SPELL_FAILED_SPELL_UNAVAILABLE = 123, + SPELL_FAILED_STUNNED = 124, + SPELL_FAILED_TARGETS_DEAD = 125, + SPELL_FAILED_TARGET_AFFECTING_COMBAT = 126, + SPELL_FAILED_TARGET_AURASTATE = 127, + SPELL_FAILED_TARGET_DUELING = 128, + SPELL_FAILED_TARGET_ENEMY = 129, + SPELL_FAILED_TARGET_ENRAGED = 130, + SPELL_FAILED_TARGET_FRIENDLY = 131, + SPELL_FAILED_TARGET_IN_COMBAT = 132, + SPELL_FAILED_TARGET_IN_PET_BATTLE = 133, + SPELL_FAILED_TARGET_IS_PLAYER = 134, + SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 135, + SPELL_FAILED_TARGET_NOT_DEAD = 136, + SPELL_FAILED_TARGET_NOT_IN_PARTY = 137, + SPELL_FAILED_TARGET_NOT_LOOTED = 138, + SPELL_FAILED_TARGET_NOT_PLAYER = 139, + SPELL_FAILED_TARGET_NO_POCKETS = 140, + SPELL_FAILED_TARGET_NO_WEAPONS = 141, + SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 142, + SPELL_FAILED_TARGET_UNSKINNABLE = 143, + SPELL_FAILED_THIRST_SATIATED = 144, + SPELL_FAILED_TOO_CLOSE = 145, + SPELL_FAILED_TOO_MANY_OF_ITEM = 146, + SPELL_FAILED_TOTEM_CATEGORY = 147, + SPELL_FAILED_TOTEMS = 148, + SPELL_FAILED_TRY_AGAIN = 149, + SPELL_FAILED_UNIT_NOT_BEHIND = 150, + SPELL_FAILED_UNIT_NOT_INFRONT = 151, + SPELL_FAILED_VISION_OBSCURED = 152, + SPELL_FAILED_WRONG_PET_FOOD = 153, + SPELL_FAILED_NOT_WHILE_FATIGUED = 154, + SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 155, + SPELL_FAILED_NOT_WHILE_TRADING = 156, + SPELL_FAILED_TARGET_NOT_IN_RAID = 157, + SPELL_FAILED_TARGET_FREEFORALL = 158, + SPELL_FAILED_NO_EDIBLE_CORPSES = 159, + SPELL_FAILED_ONLY_BATTLEGROUNDS = 160, + SPELL_FAILED_TARGET_NOT_GHOST = 161, + SPELL_FAILED_TRANSFORM_UNUSABLE = 162, + SPELL_FAILED_WRONG_WEATHER = 163, + SPELL_FAILED_DAMAGE_IMMUNE = 164, + SPELL_FAILED_PREVENTED_BY_MECHANIC = 165, + SPELL_FAILED_PLAY_TIME = 166, + SPELL_FAILED_REPUTATION = 167, + SPELL_FAILED_MIN_SKILL = 168, + SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND = 169, + SPELL_FAILED_NOT_ON_SHAPESHIFT = 170, + SPELL_FAILED_NOT_ON_STEALTHED = 171, + SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 172, + SPELL_FAILED_NOT_ON_MOUNTED = 173, + SPELL_FAILED_TOO_SHALLOW = 174, + SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 175, + SPELL_FAILED_TARGET_IS_TRIVIAL = 176, + SPELL_FAILED_BM_OR_INVISGOD = 177, + SPELL_FAILED_GROUND_MOUNT_NOT_ALLOWED = 178, + SPELL_FAILED_FLOATING_MOUNT_NOT_ALLOWED = 179, + SPELL_FAILED_UNDERWATER_MOUNT_NOT_ALLOWED = 180, + SPELL_FAILED_FLYING_MOUNT_NOT_ALLOWED = 181, + SPELL_FAILED_APPRENTICE_RIDING_REQUIREMENT = 182, + SPELL_FAILED_JOURNEYMAN_RIDING_REQUIREMENT = 183, + SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 184, + SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 185, + SPELL_FAILED_MASTER_RIDING_REQUIREMENT = 186, + SPELL_FAILED_COLD_RIDING_REQUIREMENT = 187, + SPELL_FAILED_FLIGHT_MASTER_RIDING_REQUIREMENT = 188, + SPELL_FAILED_CS_RIDING_REQUIREMENT = 189, + SPELL_FAILED_PANDA_RIDING_REQUIREMENT = 190, + SPELL_FAILED_MOUNT_NO_FLOAT_HERE = 191, + SPELL_FAILED_MOUNT_NO_UNDERWATER_HERE = 192, + SPELL_FAILED_MOUNT_ABOVE_WATER_HERE = 193, + SPELL_FAILED_MOUNT_COLLECTED_ON_OTHER_CHAR = 194, + SPELL_FAILED_NOT_IDLE = 195, + SPELL_FAILED_NOT_INACTIVE = 196, + SPELL_FAILED_PARTIAL_PLAYTIME = 197, + SPELL_FAILED_NO_PLAYTIME = 198, + SPELL_FAILED_NOT_IN_BATTLEGROUND = 199, + SPELL_FAILED_NOT_IN_RAID_INSTANCE = 200, + SPELL_FAILED_ONLY_IN_ARENA = 201, + SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 202, + SPELL_FAILED_ON_USE_ENCHANT = 203, + SPELL_FAILED_NOT_ON_GROUND = 204, + SPELL_FAILED_CUSTOM_ERROR = 205, + SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 206, + SPELL_FAILED_TOO_MANY_SOCKETS = 207, + SPELL_FAILED_INVALID_GLYPH = 208, + SPELL_FAILED_UNIQUE_GLYPH = 209, + SPELL_FAILED_GLYPH_SOCKET_LOCKED = 210, + SPELL_FAILED_GLYPH_EXCLUSIVE_CATEGORY = 211, + SPELL_FAILED_GLYPH_INVALID_SPEC = 212, + SPELL_FAILED_GLYPH_NO_SPEC = 213, + SPELL_FAILED_NO_VALID_TARGETS = 214, + SPELL_FAILED_ITEM_AT_MAX_CHARGES = 215, + SPELL_FAILED_NOT_IN_BARBERSHOP = 216, + SPELL_FAILED_FISHING_TOO_LOW = 217, + SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW = 218, + SPELL_FAILED_SUMMON_PENDING = 219, + SPELL_FAILED_MAX_SOCKETS = 220, + SPELL_FAILED_PET_CAN_RENAME = 221, + SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED = 222, + SPELL_FAILED_TARGET_HAS_RESURRECT_PENDING = 223, + SPELL_FAILED_NO_ACTIONS = 224, + SPELL_FAILED_CURRENCY_WEIGHT_MISMATCH = 225, + SPELL_FAILED_WEIGHT_NOT_ENOUGH = 226, + SPELL_FAILED_WEIGHT_TOO_MUCH = 227, + SPELL_FAILED_NO_VACANT_SEAT = 228, + SPELL_FAILED_NO_LIQUID = 229, + SPELL_FAILED_ONLY_NOT_SWIMMING = 230, + SPELL_FAILED_BY_NOT_MOVING = 231, + SPELL_FAILED_IN_COMBAT_RES_LIMIT_REACHED = 232, + SPELL_FAILED_NOT_IN_ARENA = 233, + SPELL_FAILED_TARGET_NOT_GROUNDED = 234, + SPELL_FAILED_EXCEEDED_WEEKLY_USAGE = 235, + SPELL_FAILED_NOT_IN_LFG_DUNGEON = 236, + SPELL_FAILED_BAD_TARGET_FILTER = 237, + SPELL_FAILED_NOT_ENOUGH_TARGETS = 238, + SPELL_FAILED_NO_SPEC = 239, + SPELL_FAILED_CANT_ADD_BATTLE_PET = 240, + SPELL_FAILED_CANT_UPGRADE_BATTLE_PET = 241, + SPELL_FAILED_WRONG_BATTLE_PET_TYPE = 242, + SPELL_FAILED_NO_DUNGEON_ENCOUNTER = 243, + SPELL_FAILED_NO_TELEPORT_FROM_DUNGEON = 244, + SPELL_FAILED_MAX_LEVEL_TOO_LOW = 245, + SPELL_FAILED_CANT_REPLACE_ITEM_BONUS = 246, + SPELL_FAILED_GRANT_PET_LEVEL_FAIL = 247, + SPELL_FAILED_SKILL_LINE_NOT_KNOWN = 248, + SPELL_FAILED_BLUEPRINT_KNOWN = 249, + SPELL_FAILED_FOLLOWER_KNOWN = 250, + SPELL_FAILED_CANT_OVERRIDE_ENCHANT_VISUAL = 251, + SPELL_FAILED_ITEM_NOT_A_WEAPON = 252, + SPELL_FAILED_SAME_ENCHANT_VISUAL = 253, + SPELL_FAILED_TOY_USE_LIMIT_REACHED = 254, + SPELL_FAILED_SHIPMENTS_FULL = 255, + SPELL_FAILED_HAS_MISSION = 256, + SPELL_FAILED_BUILDING_ACTIVATE_NOT_READY = 257, + SPELL_FAILED_NOT_SOULBOUND = 258, + SPELL_FAILED_RIDING_VEHICLE = 259, + SPELL_FAILED_UNKNOWN = 260, // custom value, default case + SPELL_CAST_OK = 0xFFFF // custom value, must not be sent to client }; enum SpellCustomErrors diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index ac0b5bbf2e6..ff1978edce6 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -256,70 +256,73 @@ void ScriptMgr::FillSpellSummary() if (!pTempSpell) continue; - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : pTempSpell->GetEffectsForDifficulty(DIFFICULTY_NONE)) { + if (!effect) + continue; + // Spell targets self. - if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER) + if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1); // Spell targets a single enemy. - if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY) + if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || + effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1); // Spell targets AoE at enemy. - if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) + if (effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || + effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || + effect->TargetA.GetTarget() == TARGET_SRC_CASTER || + effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); // Spell targets an enemy. - if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) + if (effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY || + effect->TargetA.GetTarget() == TARGET_DEST_TARGET_ENEMY || + effect->TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || + effect->TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || + effect->TargetA.GetTarget() == TARGET_SRC_CASTER || + effect->TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); // Spell targets a single friend (or self). - if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY) + if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER || + effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || + effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1); // Spell targets AoE friends. - if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER) + if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || + effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || + effect->TargetA.GetTarget() == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); // Spell targets any friend (or self). - if (pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || - pTempSpell->Effects[j].TargetA.GetTarget() == TARGET_SRC_CASTER) + if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER || + effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_ALLY || + effect->TargetA.GetTarget() == TARGET_UNIT_TARGET_PARTY || + effect->TargetA.GetTarget() == TARGET_UNIT_CASTER_AREA_PARTY || + effect->TargetA.GetTarget() == TARGET_UNIT_LASTTARGET_AREA_PARTY || + effect->TargetA.GetTarget() == TARGET_SRC_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); // Make sure that this spell includes a damage effect. - if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_SCHOOL_DAMAGE || - pTempSpell->Effects[j].Effect == SPELL_EFFECT_INSTAKILL || - pTempSpell->Effects[j].Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || - pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEALTH_LEECH) + if (effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE || + effect->Effect == SPELL_EFFECT_INSTAKILL || + effect->Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE || + effect->Effect == SPELL_EFFECT_HEALTH_LEECH) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1); // Make sure that this spell includes a healing effect (or an apply aura with a periodic heal). - if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL || - pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL_MAX_HEALTH || - pTempSpell->Effects[j].Effect == SPELL_EFFECT_HEAL_MECHANICAL || - (pTempSpell->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA && pTempSpell->Effects[j].ApplyAuraName == 8)) + if (effect->Effect == SPELL_EFFECT_HEAL || + effect->Effect == SPELL_EFFECT_HEAL_MAX_HEALTH || + effect->Effect == SPELL_EFFECT_HEAL_MECHANICAL || + (effect->Effect == SPELL_EFFECT_APPLY_AURA && effect->ApplyAuraName == 8)) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1); // Make sure that this spell applies an aura. - if (pTempSpell->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA) + if (effect->Effect == SPELL_EFFECT_APPLY_AURA) SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1); } } diff --git a/src/server/game/Server/Packets/CombatLogPackets.cpp b/src/server/game/Server/Packets/CombatLogPackets.cpp new file mode 100644 index 00000000000..128cc0d342f --- /dev/null +++ b/src/server/game/Server/Packets/CombatLogPackets.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CombatLogPackets.h" +#include "SpellPackets.h" + +WorldPacket const* WorldPackets::CombatLog::SpellNonMeleeDamageLog::Write() +{ + _worldPacket << Me; + _worldPacket << CasterGUID; + _worldPacket << SpellID; + _worldPacket << Damage; + _worldPacket << Overkill; + _worldPacket << SchoolMask; + _worldPacket << ShieldBlock; + _worldPacket << Resisted; + _worldPacket << Absorbed; + + _worldPacket.WriteBit(Periodic); + _worldPacket.WriteBits(Flags, 9); + _worldPacket.WriteBit(false); // Debug info + _worldPacket.WriteBit(LogData.HasValue); + _worldPacket.FlushBits(); + + if (LogData.HasValue) + _worldPacket << LogData.Value; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/CombatLogPackets.h b/src/server/game/Server/Packets/CombatLogPackets.h new file mode 100644 index 00000000000..6cca0127ef6 --- /dev/null +++ b/src/server/game/Server/Packets/CombatLogPackets.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef CombatLogPackets_h__ +#define CombatLogPackets_h__ + +#include "Packet.h" +#include "SpellPackets.h" + +namespace WorldPackets +{ + namespace CombatLog + { + class SpellNonMeleeDamageLog final : public ServerPacket + { + public: + SpellNonMeleeDamageLog() : ServerPacket(SMSG_SPELLNONMELEEDAMAGELOG, 60) { } + + WorldPacket const* Write() override; + + int32 Absorbed; + int32 ShieldBlock; + ObjectGuid Me; + int32 SpellID; + int32 Resisted; + bool Periodic; + uint8 SchoolMask; + ObjectGuid CasterGUID; + Optional<Spells::SpellCastLogData> LogData; + int32 Damage; + // Optional<SpellNonMeleeDamageLogDebugInfo> Debug Info; + int32 Flags; + int32 Overkill; + }; + } +} + +#endif // CombatLogPackets_h__ diff --git a/src/server/game/Server/Packets/CombatPackets.h b/src/server/game/Server/Packets/CombatPackets.h index 14648297342..5b2347e3edb 100644 --- a/src/server/game/Server/Packets/CombatPackets.h +++ b/src/server/game/Server/Packets/CombatPackets.h @@ -150,7 +150,7 @@ namespace WorldPackets WorldPacket const* Write() override; - Optional<WorldPackets::Spell::SpellCastLogData> LogData; + Optional<WorldPackets::Spells::SpellCastLogData> LogData; uint32 HitInfo = 0; // Flags ObjectGuid AttackerGUID; ObjectGuid VictimGUID; diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index 2e345d5b9a4..233c35f7bbd 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -16,8 +16,10 @@ */ #include "SpellPackets.h" +#include "SpellAuraEffects.h" +#include "MovementPackets.h" -WorldPacket const* WorldPackets::Spell::CategoryCooldown::Write() +WorldPacket const* WorldPackets::Spells::CategoryCooldown::Write() { _worldPacket.reserve(4 + 8 * CategoryCooldowns.size()); @@ -32,7 +34,7 @@ WorldPacket const* WorldPackets::Spell::CategoryCooldown::Write() return &_worldPacket; } -WorldPacket const* WorldPackets::Spell::SendKnownSpells::Write() +WorldPacket const* WorldPackets::Spells::SendKnownSpells::Write() { _worldPacket.reserve(1 + 4 * KnownSpells.size()); @@ -45,7 +47,7 @@ WorldPacket const* WorldPackets::Spell::SendKnownSpells::Write() return &_worldPacket; } -WorldPacket const* WorldPackets::Spell::UpdateActionButtons::Write() +WorldPacket const* WorldPackets::Spells::UpdateActionButtons::Write() { for (uint32 i = 0; i < MAX_ACTION_BUTTONS; ++i) _worldPacket << ActionButtons[i]; @@ -55,7 +57,13 @@ WorldPacket const* WorldPackets::Spell::UpdateActionButtons::Write() return &_worldPacket; } -WorldPacket const* WorldPackets::Spell::SendUnlearnSpells::Write() +void WorldPackets::Spells::SetActionButton::Read() +{ + _worldPacket >> Action; + _worldPacket >> Index; +} + +WorldPacket const* WorldPackets::Spells::SendUnlearnSpells::Write() { _worldPacket << uint32(Spells.size()); for (uint32 spellId : Spells) @@ -64,13 +72,13 @@ WorldPacket const* WorldPackets::Spell::SendUnlearnSpells::Write() return &_worldPacket; } -ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spell::SpellCastLogData& spellCastLogData) +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastLogData const& spellCastLogData) { data << spellCastLogData.Health; data << spellCastLogData.AttackPower; data << spellCastLogData.SpellPower; data << int32(spellCastLogData.PowerData.size()); - for (WorldPackets::Spell::SpellLogPowerData const& powerData : spellCastLogData.PowerData) + for (WorldPackets::Spells::SpellLogPowerData const& powerData : spellCastLogData.PowerData) { data << powerData.PowerType; data << powerData.Amount; @@ -82,3 +90,404 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spell::SpellCastLogData& return data; } +WorldPacket const* WorldPackets::Spells::SendAuraUpdate::Write() +{ + return &_worldPacket; +} + +void WorldPackets::Spells::SendAuraUpdate::Init(bool IsFullUpdate, ObjectGuid Target, uint32 Count) +{ + _worldPacket.WriteBit(IsFullUpdate); + _worldPacket << Target; + _worldPacket << uint32(Count); +} + +void WorldPackets::Spells::SendAuraUpdate::BuildUpdatePacket(AuraApplication* aurApp, bool remove, uint16 level) +{ + _worldPacket << uint8(aurApp->GetSlot()); + _worldPacket.ResetBitPos(); + _worldPacket.WriteBit(!remove); + + if (remove) + { + _worldPacket.FlushBits(); + return; + } + Aura const* aura = aurApp->GetBase(); + _worldPacket << uint32(aura->GetId()); + + uint8 flags = aurApp->GetFlags(); + if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION)) + flags |= AFLAG_DURATION; + _worldPacket << uint8(flags); + + _worldPacket << uint32(aurApp->GetEffectMask()); + + _worldPacket << uint16(level); + + // send stack amount for aura which could be stacked (never 0 - causes incorrect display) or charges + // stack amount has priority over charges (checked on retail with spell 50262) + _worldPacket << uint8(aura->GetSpellInfo()->StackAmount ? aura->GetStackAmount() : aura->GetCharges()); + + uint32 int72 = 0; + _worldPacket << int72; + + size_t pos = _worldPacket.wpos(); + uint32 count = 0; + _worldPacket << count; + + //for (int72) + // float + + if (flags & AFLAG_SCALABLE) + { + for (AuraEffect const* effect : aura->GetAuraEffects()) + { + if (effect && aurApp->HasEffect(effect->GetEffIndex())) // Not all of aura's effects have to be applied on every target + { + _worldPacket << int32(effect->GetAmount()); + count++; + } + } + } + + _worldPacket.put<uint32>(pos, count); + + _worldPacket.ResetBitPos(); + + _worldPacket.WriteBit(!(flags & AFLAG_NOCASTER)); + _worldPacket.WriteBit(aura->GetDuration()); + _worldPacket.WriteBit(aura->GetMaxDuration()); + + if (!(flags & AFLAG_NOCASTER)) + _worldPacket << aura->GetCasterGUID().WriteAsPacked(); + + if (aura->GetDuration()) + { + _worldPacket << uint32(aura->GetDuration()); + } + + if (aura->GetMaxDuration()) + { + _worldPacket << uint32(aura->GetMaxDuration()); + } +} + +void WorldPackets::Spells::SpellCastRequest::Read() +{ + if (_worldPacket.GetOpcode() == CMSG_PET_CAST_SPELL) + _worldPacket >> PetGuid; + + _worldPacket >> CastID; + _worldPacket >> SpellID; + _worldPacket >> Misc; + + _worldPacket.ResetBitPos(); + + TargetFlags = _worldPacket.ReadBits(21); + bool HasSrcLocation = _worldPacket.ReadBit(); + bool HasDstLocation = _worldPacket.ReadBit(); + bool HasOrientation = _worldPacket.ReadBit(); + uint32 NameLen = _worldPacket.ReadBits(7); + + _worldPacket >> UnitGuid; + _worldPacket >> ItemGuid; + + if (HasSrcLocation) + { + _worldPacket >> SrcTransportGuid; + _worldPacket >> SrcPos.m_positionX; + _worldPacket >> SrcPos.m_positionY; + _worldPacket >> SrcPos.m_positionZ; + } + + if (HasDstLocation) + { + _worldPacket >> DstTransportGuid; + _worldPacket >> DstPos.m_positionX; + _worldPacket >> DstPos.m_positionY; + _worldPacket >> DstPos.m_positionZ; + } + + if (HasOrientation) + _worldPacket >> Orientation; + + Name = _worldPacket.ReadString(NameLen); + + _worldPacket >> Pitch; + _worldPacket >> Speed; + + _worldPacket >> Guid; + + _worldPacket.ResetBitPos(); + + SendCastFlags = _worldPacket.ReadBits(5); + + bool HasMoveUpdate = _worldPacket.ReadBit(); + uint32 SpellWeightCount = _worldPacket.ReadBits(2); + + if (HasMoveUpdate) + { + _worldPacket >> movementInfo; + } + + // SpellWeight + for (uint32 i = 0; i < SpellWeightCount; ++i) + { + _worldPacket.ResetBitPos(); + uint32 Type = _worldPacket.ReadBits(2); + uint32 ID; + _worldPacket >> ID; + uint32 Quantity; + _worldPacket >> Quantity; + } +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation const& targetLocation) +{ + data << targetLocation.Transport; + // data << targetLocation.Location.PositionXYZStream(); + data << targetLocation.Location.m_positionX; + data << targetLocation.Location.m_positionY; + data << targetLocation.Location.m_positionZ; + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData const& spellTargetData) +{ + data.WriteBits(spellTargetData.Flags, 21); + data.WriteBit(spellTargetData.SrcLocation.HasValue); + data.WriteBit(spellTargetData.DstLocation.HasValue); + data.WriteBit(spellTargetData.Orientation.HasValue); + data.WriteBits(spellTargetData.Name.size(), 7); + data.FlushBits(); + + data << spellTargetData.Unit; + data << spellTargetData.Item; + + if (spellTargetData.SrcLocation.HasValue) + data << spellTargetData.SrcLocation.Value; + + if (spellTargetData.DstLocation.HasValue) + data << spellTargetData.DstLocation.Value; + + if (spellTargetData.Orientation.HasValue) + data << spellTargetData.Orientation.Value; + + data.WriteString(spellTargetData.Name); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellMissStatus const& spellMissStatus) +{ + data.WriteBits(spellMissStatus.Reason, 4); + data.WriteBits(spellMissStatus.ReflectStatus, 4); + // No need to flush bits as we written exactly 8 bits (1 byte) + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellPowerData const& spellPowerData) +{ + data << spellPowerData.Cost; + data << spellPowerData.Type; + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::RuneData const& runeData) +{ + data << runeData.Start; + data << runeData.Count; + + data.WriteBits(runeData.Cooldowns.size(), 3); + data.FlushBits(); + + for (uint8 cd : runeData.Cooldowns) + data << cd; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::MissileTrajectoryResult const& missileTrajectory) +{ + data << missileTrajectory.TravelTime; + data << missileTrajectory.Pitch; + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellAmmo const& spellAmmo) +{ + data << spellAmmo.DisplayID; + data << spellAmmo.InventoryType; + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::ProjectileVisualData const& projectileVisual) +{ + data << projectileVisual.ID[0]; + data << projectileVisual.ID[1]; + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::CreatureImmunities const& immunities) +{ + data << immunities.School; + data << immunities.Value; + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellHealPrediction const& spellPred) +{ + data << spellPred.Points; + data << spellPred.Type; + data << spellPred.BeaconGUID; + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData const& spellCastData) +{ + data << spellCastData.CasterGUID; + data << spellCastData.CasterUnit; + data << spellCastData.CastID; + data << spellCastData.SpellID; + data << spellCastData.CastFlags; + data << spellCastData.CastTime; + data << uint32(spellCastData.HitTargets.size()); + data << uint32(spellCastData.MissTargets.size()); + data << uint32(spellCastData.MissStatus.size()); + data << spellCastData.Target; + data << uint32(spellCastData.RemainingPower.size()); + data << spellCastData.MissileTrajectory; + data << spellCastData.Ammo; + data << spellCastData.DestLocSpellCastIndex; + data << uint32(spellCastData.TargetPoints.size()); + data << spellCastData.Immunities; + data << spellCastData.Predict; + + for (ObjectGuid const& target : spellCastData.HitTargets) + data << target; + + for (ObjectGuid const& target : spellCastData.MissTargets) + data << target; + + for (WorldPackets::Spells::SpellMissStatus const& status : spellCastData.MissStatus) + data << status; + + for (WorldPackets::Spells::SpellPowerData const& power : spellCastData.RemainingPower) + data << power; + + for (WorldPackets::Spells::TargetLocation const& targetLoc : spellCastData.TargetPoints) + data << targetLoc; + + data.WriteBits(spellCastData.CastFlagsEx, 18); + data.WriteBit(spellCastData.RemainingRunes.HasValue); + data.WriteBit(spellCastData.ProjectileVisual.HasValue); + data.FlushBits(); + + if (spellCastData.RemainingRunes.HasValue) + data << spellCastData.RemainingRunes.Value; + + if (spellCastData.ProjectileVisual.HasValue) + data << spellCastData.ProjectileVisual.Value; + + return data; +} + +WorldPacket const* WorldPackets::Spells::SpellStart::Write() +{ + _worldPacket << Cast; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Spells::SpellGo::Write() +{ + _worldPacket << Cast; + + _worldPacket.WriteBit(LogData.HasValue); + _worldPacket.FlushBits(); + + if (LogData.HasValue) + _worldPacket << LogData.Value; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Spells::LearnedSpells::Write() +{ + _worldPacket << uint32(SpellID.size()); + for (int32 spell : SpellID) + _worldPacket << spell; + + _worldPacket.WriteBit(SuppressMessaging); + _worldPacket.FlushBits(); + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Spells::SpellFailure::Write() +{ + _worldPacket << CasterUnit; + _worldPacket << CastID; + _worldPacket << SpellID; + _worldPacket << Reason; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Spells::SpellFailedOther::Write() +{ + _worldPacket << CasterUnit; + _worldPacket << CastID; + _worldPacket << SpellID; + _worldPacket << Reason; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Spells::CastFailed::Write() +{ + _worldPacket << SpellID; + _worldPacket << Reason; + _worldPacket << FailedArg1; + _worldPacket << FailedArg2; + _worldPacket << CastID; + + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellModifierData const& spellModifierData) +{ + data << spellModifierData.ModifierValue; + data << spellModifierData.ClassIndex; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellModifier const& spellModifier) +{ + data << spellModifier.ModIndex; + data << uint32(spellModifier.ModifierData.size()); + for (WorldPackets::Spells::SpellModifierData const& modData : spellModifier.ModifierData) + data << modData; + + return data; +} + +WorldPacket const* WorldPackets::Spells::SetSpellModifier::Write() +{ + _worldPacket << uint32(Modifiers.size()); + for (WorldPackets::Spells::SpellModifier const& spellMod : Modifiers) + _worldPacket << spellMod; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Spells::SendRemovedSpell::Write() +{ + _worldPacket << uint32(Spells.size()); + for (uint32 spellId : Spells) + _worldPacket << uint32(spellId); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index 0bfd979b6ca..98882fc2e26 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -20,10 +20,12 @@ #include "Packet.h" #include "Player.h" +#include "SpellAuras.h" +#include "Spell.h" namespace WorldPackets { - namespace Spell + namespace Spells { class CategoryCooldown final : public ServerPacket { @@ -75,6 +77,17 @@ namespace WorldPackets */ }; + class SetActionButton final : public ClientPacket + { + public: + SetActionButton(WorldPacket&& packet) : ClientPacket(CMSG_SET_ACTION_BUTTON, std::move(packet)) {} + + void Read() override; + + uint64 Action = 0; ///< two packed uint32 (action and type) + uint8 Index = 0; + }; + class SendUnlearnSpells final : public ServerPacket { public: @@ -98,9 +111,259 @@ namespace WorldPackets int32 SpellPower = 0; std::vector<SpellLogPowerData> PowerData; }; + + class SendAuraUpdate final : public ServerPacket + { + public: + SendAuraUpdate() : ServerPacket(SMSG_AURA_UPDATE) { } + + WorldPacket const* Write() override; + void Init(bool IsFullUpdate, ObjectGuid Target, uint32 Count); + void BuildUpdatePacket(AuraApplication* aurApp, bool remove, uint16 level); + }; + + class SpellCastRequest final : public ClientPacket + { + public: + SpellCastRequest(WorldPacket&& packet) : ClientPacket(std::move(packet)) + { + ASSERT(packet.GetOpcode() == CMSG_CAST_SPELL || packet.GetOpcode() == CMSG_PET_CAST_SPELL); + } + + void Read() override; + + ObjectGuid PetGuid; + uint8 CastID; + uint32 SpellID; + uint32 Misc; + uint32 TargetFlags; + ObjectGuid UnitGuid; + ObjectGuid ItemGuid; + + ObjectGuid SrcTransportGuid; + ObjectGuid DstTransportGuid; + Position SrcPos; + Position DstPos; + float Orientation; + + std::string Name; + float Pitch; + float Speed; + ObjectGuid Guid; + uint32 SendCastFlags; + + MovementInfo movementInfo; + }; + + struct TargetLocation + { + ObjectGuid Transport; + Position Location; + }; + + struct SpellTargetData + { + uint32 Flags = 0; + ObjectGuid Unit; + ObjectGuid Item; + Optional<TargetLocation> SrcLocation; + Optional<TargetLocation> DstLocation; + Optional<float> Orientation; // Not found in JAM structures + std::string Name; + }; + + struct SpellMissStatus + { + uint8 Reason = 0; + uint8 ReflectStatus = 0; + }; + + struct SpellPowerData + { + int32 Cost = 0; + int8 Type = 0; + }; + + struct RuneData + { + uint8 Start = 0; + uint8 Count = 0; + std::vector<uint8> Cooldowns; + }; + + struct MissileTrajectoryResult + { + uint32 TravelTime = 0; + float Pitch = 0.0f; + }; + + struct SpellAmmo + { + int32 DisplayID = 0; + int8 InventoryType = 0; + }; + + struct ProjectileVisualData + { + int32 ID[2]; + }; + + struct CreatureImmunities + { + uint32 School = 0; + uint32 Value = 0; + }; + + struct SpellHealPrediction + { + ObjectGuid BeaconGUID; + uint32 Points = 0; + uint8 Type = 0; + }; + + struct SpellCastData + { + ObjectGuid CasterGUID; + ObjectGuid CasterUnit; + uint8 CastID = 0; + int32 SpellID = 0; + uint32 CastFlags = 0; + uint32 CastFlagsEx = 0; + uint32 CastTime = 0; + std::vector<ObjectGuid> HitTargets; + std::vector<ObjectGuid> MissTargets; + std::vector<SpellMissStatus> MissStatus; + SpellTargetData Target; + std::vector<SpellPowerData> RemainingPower; + Optional<RuneData> RemainingRunes; + MissileTrajectoryResult MissileTrajectory; + SpellAmmo Ammo; + Optional<ProjectileVisualData> ProjectileVisual; + uint8 DestLocSpellCastIndex = 0; + std::vector<TargetLocation> TargetPoints; + CreatureImmunities Immunities; + SpellHealPrediction Predict; + }; + + class SpellGo final : public ServerPacket + { + public: + SpellGo() : ServerPacket(SMSG_SPELL_GO) { } + + WorldPacket const* Write() override; + + Optional<SpellCastLogData> LogData; + SpellCastData Cast; + }; + + class SpellStart final : public ServerPacket + { + public: + SpellStart() : ServerPacket(SMSG_SPELL_START) { } + + WorldPacket const* Write() override; + + SpellCastData Cast; + }; + + class LearnedSpells final : public ServerPacket + { + public: + LearnedSpells() : ServerPacket(SMSG_LEARNED_SPELLS, 9) { } + + WorldPacket const* Write() override; + + std::vector<int32> SpellID; + bool SuppressMessaging = false; + }; + + class SpellFailure final : public ServerPacket + { + public: + SpellFailure() : ServerPacket(SMSG_SPELL_FAILURE, 16+4+1+1) { } + + WorldPacket const* Write() override; + + ObjectGuid CasterUnit; + uint32 SpellID = 0; + uint8 Reason = 0; + uint8 CastID = 0; + }; + + class SpellFailedOther final : public ServerPacket + { + public: + SpellFailedOther() : ServerPacket(SMSG_SPELL_FAILED_OTHER, 16+4+1+1) { } + + WorldPacket const* Write() override; + + ObjectGuid CasterUnit; + uint32 SpellID = 0; + uint16 Reason = 0; + uint8 CastID = 0; + }; + + class CastFailed final : public ServerPacket + { + public: + CastFailed(OpcodeServer opcode) : ServerPacket(opcode, 4+4+4+4+1) { } + + WorldPacket const* Write() override; + + int32 Reason = 0; + int32 FailedArg1 = -1; + int32 FailedArg2 = -1; + int32 SpellID = 0; + uint8 CastID = 0; + }; + + struct SpellModifierData + { + float ModifierValue = 0.0f; + uint8 ClassIndex = 0; + }; + + struct SpellModifier + { + uint8 ModIndex = 0; + std::vector<SpellModifierData> ModifierData; + }; + + class SetSpellModifier final : public ServerPacket + { + public: + SetSpellModifier(OpcodeServer opcode) : ServerPacket(opcode, 20) { } + + WorldPacket const* Write() override; + + std::vector<SpellModifier> Modifiers; + }; + + class SendRemovedSpell final : public ServerPacket + { + public: + SendRemovedSpell() : ServerPacket(SMSG_REMOVED_SPELL, 4) { } + + WorldPacket const* Write() override; + + std::vector<uint32> Spells; + }; } } -ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spell::SpellCastLogData& spellCastLogData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastLogData const& spellCastLogData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::TargetLocation const& targetLocation); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellTargetData const& spellTargetData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellMissStatus const& spellMissStatus); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellPowerData const& spellPowerData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::RuneData const& runeData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::MissileTrajectoryResult const& missileTrajectory); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellAmmo const& spellAmmo); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::ProjectileVisualData const& projectileVisual); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::CreatureImmunities const& immunities); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellHealPrediction const& spellPred); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellCastData const& spellCastData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellModifierData const& spellModifierData); +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Spells::SpellModifier const& spellModifier); #endif // SpellPackets_h__ diff --git a/src/server/game/Server/Packets/TalentPackets.cpp b/src/server/game/Server/Packets/TalentPackets.cpp index 4855f663662..d340b476cf9 100644 --- a/src/server/game/Server/Packets/TalentPackets.cpp +++ b/src/server/game/Server/Packets/TalentPackets.cpp @@ -41,3 +41,17 @@ void WorldPackets::Talent::SetSpecialization::Read() { _worldPacket >> SpecGroupIndex; } + + +void WorldPackets::Talent::LearnTalent::Read() +{ + uint32 count; + _worldPacket >> count; + + for (uint32 i = 0; i < count; ++i) + { + uint16 talent; + _worldPacket >> talent; + Talents.push_back(talent); + } +}
\ No newline at end of file diff --git a/src/server/game/Server/Packets/TalentPackets.h b/src/server/game/Server/Packets/TalentPackets.h index 21753e22c8d..2bc8b3934a8 100644 --- a/src/server/game/Server/Packets/TalentPackets.h +++ b/src/server/game/Server/Packets/TalentPackets.h @@ -57,6 +57,19 @@ namespace WorldPackets uint32 SpecGroupIndex = 0; }; + + class LearnTalent final : public ClientPacket + { + public: + LearnTalent(WorldPacket&& packet) : ClientPacket(std::move(packet)) + { + ASSERT(packet.GetOpcode() == CMSG_LEARN_TALENT); + } + + void Read() override; + std::vector<uint16> Talents; + + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index fdec9a43948..488ae53b4d7 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -202,7 +202,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_CALENDAR_GUILD_FILTER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarGuildFilter ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CALENDAR_REMOVE_EVENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarRemoveEvent ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CALENDAR_UPDATE_EVENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCalendarUpdateEvent ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_AURA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_AURA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAuraOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_AUTO_REPEAT_SPELL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelAutoRepeatSpellOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_CAST, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleCancelCastOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_CHANNELLING, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelChanneling ); @@ -211,7 +211,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode); DEFINE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, WorldPackets::Trade::CancelTrade, &WorldSession::HandleCancelTradeOpcode); - DEFINE_OPCODE_HANDLER_OLD(CMSG_CAST_SPELL, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode ); + DEFINE_HANDLER(CMSG_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Spells::SpellCastRequest, &WorldSession::HandleCastSpellOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGEPLAYER_DIFFICULTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANNEL_ANNOUNCEMENTS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChannelAnnouncements ); @@ -369,7 +369,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_KEEP_ALIVE, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LEARN_PREVIEW_TALENTS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalents ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LEARN_PREVIEW_TALENTS_PET, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnPreviewTalentsPet ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_LEARN_TALENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLearnTalentOpcode ); + DEFINE_HANDLER(CMSG_LEARN_TALENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Talent::LearnTalent, &WorldSession::HandleLearnTalentOpcode); DEFINE_HANDLER(CMSG_LEAVE_CHANNEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Channel::LeaveChannel, &WorldSession::HandleLeaveChannel); DEFINE_OPCODE_HANDLER_OLD(CMSG_LFG_GET_STATUS, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleLfgGetStatus ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LFG_JOIN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLfgJoinOpcode ); @@ -498,7 +498,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_ABANDON, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAbandon ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_ACTION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetAction ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_CANCEL_AURA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCancelAuraOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_CAST_SPELL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetCastSpellOpcode ); + DEFINE_HANDLER(CMSG_PET_CAST_SPELL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::SpellCastRequest, &WorldSession::HandlePetCastSpellOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_LEARN_TALENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetLearnTalent ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_NAME_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetNameQuery ); DEFINE_OPCODE_HANDLER_OLD(CMSG_PET_RENAME, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandlePetRename ); @@ -576,7 +576,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SETSHEATHED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleSetSheathedOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ACTIONBAR_TOGGLES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionBarToggles ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ACTION_BUTTON, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActionButtonOpcode ); + DEFINE_HANDLER(CMSG_SET_ACTION_BUTTON, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Spells::SetActionButton, &WorldSession::HandleSetActionButtonOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ACTIVE_MOVER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveMoverOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ACTIVE_VOICE_CHANNEL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetActiveVoiceChannel ); // STATUS_AUTHED DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ALLOW_LOW_LEVEL_RAID1, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -734,8 +734,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_OWNER_NOTIFICATION, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_REMOVED_NOTIFICATION, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_POINTS_DEPLETED, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_UPDATE_ALL, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_RESPONSE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AVAILABLE_VOICE_CHANNEL, STATUS_UNHANDLED); @@ -800,7 +799,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAMERA_SHAKE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_AUTO_REPEAT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CANCEL_COMBAT, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAST_FAILED, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CAST_FAILED, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_LIST, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_MEMBER_COUNT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_UNHANDLED); @@ -1032,7 +1031,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_ITEM_TIME_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_KICK_REASON, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_DANCE_MOVES, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELL, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEARNED_SPELLS, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LEVELUP_INFO, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_BOOT_PROPOSAL_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_UNHANDLED); @@ -1248,7 +1247,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFORGE_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFRESH_SPELL_HISTORY, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_REMOVED_SPELL, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_REMOVED_SPELL, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REPORT_PVP_AFK_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_CEMETERY_LIST_RESPONSE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REQUEST_PVP_REWARDS_RESPONSE, STATUS_UNHANDLED); @@ -1281,12 +1280,12 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_NOT_VISIBLE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_STANDING, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_VISIBLE, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FLAT_SPELL_MODIFIER, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FLAT_SPELL_MODIFIER, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FORCED_REACTIONS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_MAX_WEEKLY_QUANTITY, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_MELEE_ANIM_KIT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_MOVEMENT_ANIM_KIT, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PCT_SPELL_MODIFIER, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PCT_SPELL_MODIFIER, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PHASE_SHIFT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_UNHANDLED); @@ -1308,16 +1307,16 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELLINTERRUPTLOG, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELLLOGEXECUTE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELLLOGMISS, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELLNONMELEEDAMAGELOG, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELLNONMELEEDAMAGELOG, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELLORDAMAGE_IMMUNE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELLSTEALLOG, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_CATEGORY_COOLDOWN, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_COOLDOWN, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_DELAYED, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILED_OTHER, STATUS_NEVER); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_FAILURE, STATUS_NEVER); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_GO, STATUS_NEVER); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_DISABLE, STATUS_UNHANDLED); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index a4080371003..ee95bd840ab 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -144,7 +144,7 @@ enum OpcodeClient : uint32 CMSG_CANCEL_QUEUED_SPELL = 0xBADD, CMSG_CANCEL_TEMP_ENCHANTMENT = 0xBADD, CMSG_CANCEL_TRADE = 0x1159, - CMSG_CAST_SPELL = 0xBADD, + CMSG_CAST_SPELL = 0x08FE, CMSG_CHANGEPLAYER_DIFFICULTY = 0xBADD, CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0xBADD, CMSG_CHANNEL_ANNOUNCEMENTS = 0xBADD, @@ -314,7 +314,7 @@ enum OpcodeClient : uint32 CMSG_KEEP_ALIVE = 0xBADD, CMSG_LEARN_PREVIEW_TALENTS = 0xBADD, CMSG_LEARN_PREVIEW_TALENTS_PET = 0xBADD, - CMSG_LEARN_TALENT = 0xBADD, + CMSG_LEARN_TALENT = 0x0BB6, CMSG_LEAVE_CHANNEL = 0x19F2, CMSG_LFG_GET_STATUS = 0xBADD, CMSG_LFG_JOIN = 0xBADD, @@ -725,7 +725,6 @@ enum OpcodeServer : uint32 SMSG_AURACASTLOG = 0xBADD, SMSG_AURA_POINTS_DEPLETED = 0x093B, SMSG_AURA_UPDATE = 0x091C, - SMSG_AURA_UPDATE_ALL = 0xBADD, SMSG_AUTH_CHALLENGE = 0x1759, SMSG_AUTH_RESPONSE = 0x0DA9, SMSG_AVAILABLE_VOICE_CHANNEL = 0x04D4, @@ -1042,7 +1041,7 @@ enum OpcodeServer : uint32 SMSG_JOINED_BATTLEGROUND_QUEUE = 0xBADD, SMSG_KICK_REASON = 0xBADD, SMSG_LEARNED_DANCE_MOVES = 0xBADD, - SMSG_LEARNED_SPELL = 0xBADD, + SMSG_LEARNED_SPELLS = 0x08AB, SMSG_LEVELUP_INFO = 0xBADD, SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0xBADD, SMSG_LFG_DISABLED = 0xBADD, @@ -1270,7 +1269,7 @@ enum OpcodeServer : uint32 SMSG_REFER_A_FRIEND_FAILURE = 0xBADD, SMSG_REFORGE_RESULT = 0xBADD, SMSG_REFRESH_SPELL_HISTORY = 0x0A2A, - SMSG_REMOVED_SPELL = 0xBADD, + SMSG_REMOVED_SPELL = 0x0B3B, SMSG_REPORT_PVP_AFK_RESULT = 0xBADD, SMSG_REQUEST_CEMETERY_LIST_RESPONSE = 0x059E, SMSG_REQUEST_PVP_REWARDS_RESPONSE = 0xBADD, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index f7e85c2abab..910a8ad4aa6 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -138,9 +138,16 @@ namespace WorldPackets class QueryGuildInfo; } + namespace Spells + { + class SpellCastRequest; + class SetActionButton; + } + namespace Talent { class SetSpecialization; + class LearnTalent; } namespace Trade @@ -676,7 +683,7 @@ class WorldSession void HandleUpdateAccountData(WorldPackets::ClientConfig::UserClientUpdateAccountData& packet); void HandleRequestAccountData(WorldPackets::ClientConfig::RequestAccountData& request); - void HandleSetActionButtonOpcode(WorldPacket& recvPacket); + void HandleSetActionButtonOpcode(WorldPackets::Spells::SetActionButton& packet); void HandleGameObjectUseOpcode(WorldPacket& recPacket); void HandleMeetingStoneInfo(WorldPacket& recPacket); @@ -864,13 +871,13 @@ class WorldSession void HandleUseItemOpcode(WorldPacket& recvPacket); void HandleOpenItemOpcode(WorldPacket& recvPacket); - void HandleCastSpellOpcode(WorldPacket& recvPacket); + void HandleCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest); void HandleCancelCastOpcode(WorldPacket& recvPacket); void HandleCancelAuraOpcode(WorldPacket& recvPacket); void HandleCancelGrowthAuraOpcode(WorldPacket& recvPacket); void HandleCancelAutoRepeatSpellOpcode(WorldPacket& recvPacket); - void HandleLearnTalentOpcode(WorldPacket& recvPacket); + void HandleLearnTalentOpcode(WorldPackets::Talent::LearnTalent& packet); void HandleLearnPreviewTalents(WorldPacket& recvPacket); void HandleTalentWipeConfirmOpcode(WorldPacket& recvPacket); void HandleUnlearnSkillOpcode(WorldPacket& recvPacket); @@ -956,7 +963,7 @@ class WorldSession void HandlePetRename(WorldPacket& recvData); void HandlePetCancelAuraOpcode(WorldPacket& recvPacket); void HandlePetSpellAutocastOpcode(WorldPacket& recvPacket); - void HandlePetCastSpellOpcode(WorldPacket& recvPacket); + void HandlePetCastSpellOpcode(WorldPackets::Spells::SpellCastRequest& castRequest); void HandlePetLearnTalent(WorldPacket& recvPacket); void HandleLearnPreviewTalentsPet(WorldPacket& recvPacket); diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 628e4e0721d..e75a3424c2f 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -23,14 +23,12 @@ enum AURA_FLAGS { AFLAG_NONE = 0x00, - AFLAG_EFF_INDEX_0 = 0x01, - AFLAG_EFF_INDEX_1 = 0x02, - AFLAG_EFF_INDEX_2 = 0x04, - AFLAG_CASTER = 0x08, - AFLAG_POSITIVE = 0x10, - AFLAG_DURATION = 0x20, - AFLAG_ANY_EFFECT_AMOUNT_SENT = 0x40, // used with AFLAG_EFF_INDEX_0/1/2 - AFLAG_NEGATIVE = 0x80 + AFLAG_NOCASTER = 0x01, + AFLAG_POSITIVE = 0x02, + AFLAG_DURATION = 0x04, + AFLAG_SCALABLE = 0x08, + AFLAG_NEGATIVE = 0x10, + AFLAG_UNK20 = 0x20 }; // these are modes, in which aura effect handler may be called @@ -430,7 +428,114 @@ enum AuraType SPELL_AURA_368 = 368, // Not used in 4.3.4 SPELL_AURA_ENABLE_POWER_BAR_TIMER = 369, SPELL_AURA_SET_FAIR_FAR_CLIP = 370, // Overrides client's View Distance setting to max("Fair", current_setting) - TOTAL_AURAS = 371 // 4.3.4 + SPELL_AURA_371 = 371, + SPELL_AURA_372 = 372, + SPELL_AURA_373 = 373, + SPELL_AURA_374 = 374, + SPELL_AURA_375 = 375, + SPELL_AURA_376 = 376, + SPELL_AURA_377 = 377, + SPELL_AURA_378 = 378, + SPELL_AURA_379 = 379, + SPELL_AURA_380 = 380, + SPELL_AURA_381 = 381, + SPELL_AURA_382 = 382, + SPELL_AURA_383 = 383, + SPELL_AURA_384 = 384, + SPELL_AURA_385 = 385, + SPELL_AURA_386 = 386, + SPELL_AURA_387 = 387, + SPELL_AURA_388 = 388, + SPELL_AURA_389 = 389, + SPELL_AURA_390 = 390, + SPELL_AURA_391 = 391, + SPELL_AURA_392 = 392, + SPELL_AURA_393 = 393, + SPELL_AURA_394 = 394, + SPELL_AURA_395 = 395, + SPELL_AURA_396 = 396, + SPELL_AURA_397 = 397, + SPELL_AURA_398 = 398, + SPELL_AURA_399 = 399, + SPELL_AURA_400 = 400, + SPELL_AURA_401 = 401, + SPELL_AURA_402 = 402, + SPELL_AURA_403 = 403, + SPELL_AURA_404 = 404, + SPELL_AURA_405 = 405, + SPELL_AURA_406 = 406, + SPELL_AURA_407 = 407, + SPELL_AURA_408 = 408, + SPELL_AURA_409 = 409, + SPELL_AURA_410 = 410, + SPELL_AURA_411 = 411, + SPELL_AURA_412 = 412, + SPELL_AURA_413 = 413, + SPELL_AURA_414 = 414, + SPELL_AURA_415 = 415, + SPELL_AURA_416 = 416, + SPELL_AURA_417 = 417, + SPELL_AURA_418 = 418, + SPELL_AURA_419 = 419, + SPELL_AURA_420 = 420, + SPELL_AURA_421 = 421, + SPELL_AURA_422 = 422, + SPELL_AURA_423 = 423, + SPELL_AURA_424 = 424, + SPELL_AURA_425 = 425, + SPELL_AURA_426 = 426, + SPELL_AURA_427 = 427, + SPELL_AURA_428 = 428, + SPELL_AURA_429 = 429, + SPELL_AURA_430 = 430, + SPELL_AURA_431 = 431, + SPELL_AURA_432 = 432, + SPELL_AURA_433 = 433, + SPELL_AURA_434 = 434, + SPELL_AURA_435 = 435, + SPELL_AURA_436 = 436, + SPELL_AURA_437 = 437, + SPELL_AURA_438 = 438, + SPELL_AURA_439 = 439, + SPELL_AURA_440 = 440, + SPELL_AURA_441 = 441, + SPELL_AURA_442 = 442, + SPELL_AURA_443 = 443, + SPELL_AURA_444 = 444, + SPELL_AURA_445 = 445, + SPELL_AURA_446 = 446, + SPELL_AURA_447 = 447, + SPELL_AURA_448 = 448, + SPELL_AURA_449 = 449, + SPELL_AURA_450 = 450, + SPELL_AURA_451 = 451, + SPELL_AURA_452 = 452, + SPELL_AURA_453 = 453, + SPELL_AURA_454 = 454, + SPELL_AURA_455 = 455, + SPELL_AURA_456 = 456, + SPELL_AURA_457 = 457, + SPELL_AURA_458 = 458, + SPELL_AURA_459 = 459, + SPELL_AURA_460 = 460, + SPELL_AURA_461 = 461, + SPELL_AURA_462 = 462, + SPELL_AURA_463 = 463, + SPELL_AURA_464 = 464, + SPELL_AURA_465 = 465, + SPELL_AURA_466 = 466, + SPELL_AURA_467 = 467, + SPELL_AURA_468 = 468, + SPELL_AURA_469 = 469, + SPELL_AURA_471 = 471, + SPELL_AURA_472 = 472, + SPELL_AURA_473 = 473, + SPELL_AURA_474 = 474, + SPELL_AURA_475 = 475, + SPELL_AURA_476 = 476, + SPELL_AURA_477 = 477, + SPELL_AURA_478 = 478, + TOTAL_AURAS = 479 // 4.3.4 }; enum AuraObjectType diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index c55c92d296e..b008f1a42f0 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -429,11 +429,119 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleUnused, //368 unused (4.3.4) &AuraEffect::HandleNULL, //369 SPELL_AURA_ENABLE_POWER_BAR_TIMER &AuraEffect::HandleNULL, //370 SPELL_AURA_SET_FAIR_FAR_CLIP + &AuraEffect::HandleNULL, //371 + &AuraEffect::HandleNULL, //372 + &AuraEffect::HandleNULL, //373 + &AuraEffect::HandleNULL, //374 + &AuraEffect::HandleNULL, //375 + &AuraEffect::HandleNULL, //376 + &AuraEffect::HandleNULL, //377 + &AuraEffect::HandleNULL, //378 + &AuraEffect::HandleNULL, //379 + &AuraEffect::HandleNULL, //380 + &AuraEffect::HandleNULL, //381 + &AuraEffect::HandleNULL, //382 + &AuraEffect::HandleNULL, //383 + &AuraEffect::HandleNULL, //384 + &AuraEffect::HandleNULL, //385 + &AuraEffect::HandleNULL, //386 + &AuraEffect::HandleNULL, //387 + &AuraEffect::HandleNULL, //388 + &AuraEffect::HandleNULL, //389 + &AuraEffect::HandleNULL, //390 + &AuraEffect::HandleNULL, //391 + &AuraEffect::HandleNULL, //392 + &AuraEffect::HandleNULL, //393 + &AuraEffect::HandleNULL, //394 + &AuraEffect::HandleNULL, //395 + &AuraEffect::HandleNULL, //396 + &AuraEffect::HandleNULL, //397 + &AuraEffect::HandleNULL, //398 + &AuraEffect::HandleNULL, //399 + &AuraEffect::HandleNULL, //400 + &AuraEffect::HandleNULL, //401 + &AuraEffect::HandleNULL, //402 + &AuraEffect::HandleNULL, //403 + &AuraEffect::HandleNULL, //404 + &AuraEffect::HandleNULL, //405 + &AuraEffect::HandleNULL, //406 + &AuraEffect::HandleNULL, //407 + &AuraEffect::HandleNULL, //408 + &AuraEffect::HandleNULL, //409 + &AuraEffect::HandleNULL, //410 + &AuraEffect::HandleNULL, //411 + &AuraEffect::HandleNULL, //412 + &AuraEffect::HandleNULL, //413 + &AuraEffect::HandleNULL, //414 + &AuraEffect::HandleNULL, //415 + &AuraEffect::HandleNULL, //416 + &AuraEffect::HandleNULL, //417 + &AuraEffect::HandleNULL, //418 + &AuraEffect::HandleNULL, //419 + &AuraEffect::HandleNULL, //420 + &AuraEffect::HandleNULL, //421 + &AuraEffect::HandleNULL, //422 + &AuraEffect::HandleNULL, //423 + &AuraEffect::HandleNULL, //424 + &AuraEffect::HandleNULL, //425 + &AuraEffect::HandleNULL, //426 + &AuraEffect::HandleNULL, //427 + &AuraEffect::HandleNULL, //428 + &AuraEffect::HandleNULL, //429 + &AuraEffect::HandleNULL, //430 + &AuraEffect::HandleNULL, //431 + &AuraEffect::HandleNULL, //432 + &AuraEffect::HandleNULL, //433 + &AuraEffect::HandleNULL, //434 + &AuraEffect::HandleNULL, //435 + &AuraEffect::HandleNULL, //436 + &AuraEffect::HandleNULL, //437 + &AuraEffect::HandleNULL, //438 + &AuraEffect::HandleNULL, //439 + &AuraEffect::HandleNULL, //440 + &AuraEffect::HandleNULL, //441 + &AuraEffect::HandleNULL, //442 + &AuraEffect::HandleNULL, //443 + &AuraEffect::HandleNULL, //444 + &AuraEffect::HandleNULL, //445 + &AuraEffect::HandleNULL, //446 + &AuraEffect::HandleNULL, //447 + &AuraEffect::HandleNULL, //448 + &AuraEffect::HandleNULL, //449 + &AuraEffect::HandleNULL, //450 + &AuraEffect::HandleNULL, //451 + &AuraEffect::HandleNULL, //452 + &AuraEffect::HandleNULL, //453 + &AuraEffect::HandleNULL, //454 + &AuraEffect::HandleNULL, //455 + &AuraEffect::HandleNULL, //456 + &AuraEffect::HandleNULL, //457 + &AuraEffect::HandleNULL, //458 + &AuraEffect::HandleNULL, //459 + &AuraEffect::HandleNULL, //460 + &AuraEffect::HandleNULL, //461 + &AuraEffect::HandleNULL, //462 + &AuraEffect::HandleNULL, //463 + &AuraEffect::HandleNULL, //464 + &AuraEffect::HandleNULL, //465 + &AuraEffect::HandleNULL, //466 + &AuraEffect::HandleNULL, //467 + &AuraEffect::HandleNULL, //468 + &AuraEffect::HandleNULL, //469 + &AuraEffect::HandleNULL, //471 + &AuraEffect::HandleNULL, //472 + &AuraEffect::HandleNULL, //473 + &AuraEffect::HandleNULL, //474 + &AuraEffect::HandleNULL, //475 + &AuraEffect::HandleNULL, //476 + &AuraEffect::HandleNULL, //477 + &AuraEffect::HandleNULL, //478 }; -AuraEffect::AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster): +AuraEffect::AuraEffect(Aura* base, uint32 effIndex, int32 *baseAmount, Unit* caster) : m_base(base), m_spellInfo(base->GetSpellInfo()), -m_baseAmount(baseAmount ? *baseAmount : m_spellInfo->Effects[effIndex].BasePoints), +_effectInfo(base->GetSpellEffectInfo(effIndex)), +m_baseAmount(baseAmount ? *baseAmount : base->GetSpellEffectInfo(effIndex)->BasePoints), m_damage(0), m_critChance(0.0f), m_donePct(1.0f), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), m_canBeRecalculated(true), m_isPeriodic(false) @@ -476,10 +584,10 @@ int32 AuraEffect::CalculateAmount(Unit* caster) // default amount calculation int32 amount = 0; - if (!(m_spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(m_spellInfo->Effects[m_effIndex].BonusCoefficient, 0.0f)) - amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit()); + if (!(m_spellInfo->AttributesEx8 & SPELL_ATTR8_MASTERY_SPECIALIZATION) || G3D::fuzzyEq(GetSpellEffectInfo()->BonusCoefficient, 0.0f)) + amount = GetSpellEffectInfo()->CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit()); else if (caster && caster->GetTypeId() == TYPEID_PLAYER) - amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * m_spellInfo->Effects[m_effIndex].BonusCoefficient); + amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * GetSpellEffectInfo()->BonusCoefficient); // check item enchant aura cast if (!amount && caster) @@ -604,7 +712,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster) void AuraEffect::CalculatePeriodic(Unit* caster, bool resetPeriodicTimer /*= true*/, bool load /*= false*/) { - m_period = m_spellInfo->Effects[m_effIndex].ApplyAuraPeriod; + m_period = GetSpellEffectInfo()->ApplyAuraPeriod; // prepare periodics switch (GetAuraType()) @@ -694,7 +802,7 @@ void AuraEffect::CalculateSpellMod() m_spellmod->type = SpellModType(uint32(GetAuraType())); // SpellModType value == spell aura types m_spellmod->spellId = GetId(); - m_spellmod->mask = GetSpellInfo()->Effects[GetEffIndex()].SpellClassMask; + m_spellmod->mask = GetSpellEffectInfo()->SpellClassMask; m_spellmod->charges = GetBase()->GetCharges(); } m_spellmod->value = GetAmount(); @@ -764,7 +872,7 @@ void AuraEffect::HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply) prevented = GetBase()->CallScriptEffectApplyHandlers(this, aurApp, (AuraEffectHandleModes)mode); else prevented = GetBase()->CallScriptEffectRemoveHandlers(this, aurApp, (AuraEffectHandleModes)mode); - + // check if script events have removed the aura or if default effect prevention was requested if ((apply && aurApp->GetRemoveMode()) || prevented) return; @@ -1021,7 +1129,7 @@ bool AuraEffect::IsAffectingSpell(SpellInfo const* spell) const return false; // Check EffectClassMask - if (m_spellInfo->Effects[m_effIndex].SpellClassMask & spell->SpellFamilyFlags) + if (GetSpellEffectInfo()->SpellClassMask & spell->SpellFamilyFlags) return true; return false; } @@ -1114,7 +1222,7 @@ void AuraEffect::HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo) void AuraEffect::CleanupTriggeredSpells(Unit* target) { - uint32 tSpellId = m_spellInfo->Effects[GetEffIndex()].TriggerSpell; + uint32 tSpellId = GetSpellEffectInfo()->TriggerSpell; if (!tSpellId) return; @@ -1127,8 +1235,8 @@ void AuraEffect::CleanupTriggeredSpells(Unit* target) // needed for spell 43680, maybe others /// @todo is there a spell flag, which can solve this in a more sophisticated way? - if (m_spellInfo->Effects[GetEffIndex()].ApplyAuraName == SPELL_AURA_PERIODIC_TRIGGER_SPELL && - uint32(m_spellInfo->GetDuration()) == m_spellInfo->Effects[GetEffIndex()].ApplyAuraPeriod) + if (GetSpellEffectInfo()->ApplyAuraName == SPELL_AURA_PERIODIC_TRIGGER_SPELL && + uint32(m_spellInfo->GetDuration()) == GetSpellEffectInfo()->ApplyAuraPeriod) return; target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID()); @@ -1268,30 +1376,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const target->CastSpell(target, 24932, true, NULL, this); } - // Heart of the Wild - if (AuraEffect const* heartOfTheWild = target->GetAuraEffectOfRankedSpell(17003, EFFECT_0)) - { - uint32 heartOfTheWildSpellId = 0; - int32 heartOfTheWildAmount = 0; - - switch (GetMiscValue()) - { - case FORM_CAT: - heartOfTheWildSpellId = 24900; - heartOfTheWildAmount = heartOfTheWild->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); - break; - case FORM_BEAR: - heartOfTheWildSpellId = 24899; - heartOfTheWildAmount = heartOfTheWild->GetSpellInfo()->Effects[EFFECT_2].CalcValue(); - break; - default: - break; - } - - if (heartOfTheWildSpellId) - target->CastCustomSpell(target, heartOfTheWildSpellId, &heartOfTheWildAmount, NULL, NULL, true, NULL, this); - } - switch (GetMiscValue()) { case FORM_CAT: @@ -1327,12 +1411,6 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const int32 bp = aurEff->GetAmount(); target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true); } - // Survival of the Fittest - if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, EFFECT_0)) - { - int32 bp = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster()); - target->CastCustomSpell(target, 62069, &bp, NULL, NULL, true, 0, this); - } break; case FORM_MOONKIN: // Master Shapeshifter - Moonkin @@ -2594,9 +2672,8 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo vehicleId = creatureInfo->VehicleId; //some spell has one aura of mount and one of vehicle - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (GetSpellInfo()->Effects[i].Effect == SPELL_EFFECT_SUMMON - && GetSpellInfo()->Effects[i].MiscValue == GetMiscValue()) + for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos()) + if (effect && effect->Effect == SPELL_EFFECT_SUMMON && effect->MiscValue == GetMiscValue()) displayId = 0; } @@ -4598,8 +4675,9 @@ void AuraEffect::HandleNoReagentUseAura(AuraApplication const* aurApp, uint8 mod flag128 mask; Unit::AuraEffectList const& noReagent = target->GetAuraEffectsByType(SPELL_AURA_NO_REAGENT_USE); - for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) - mask |= (*i)->m_spellInfo->Effects[(*i)->m_effIndex].SpellClassMask; + for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) + if (SpellEffectInfo const* effect = (*i)->GetSpellEffectInfo()) + mask |= effect->SpellClassMask; target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); @@ -5021,11 +5099,11 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod if (GetAmount() <= 0) return; - if (GetSpellInfo()->Effects[m_effIndex].ItemType == 0) + if (GetSpellEffectInfo()->ItemType == 0) return; // Soul Shard - if (GetSpellInfo()->Effects[m_effIndex].ItemType == 6265) + if (GetSpellEffectInfo()->ItemType == 6265) { // Soul Shard only from units that grant XP or honor if (!plCaster->isHonorOrXPTarget(target) || @@ -5038,16 +5116,16 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod uint32 count = m_amount; ItemPosCountVec dest; - InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellInfo()->Effects[m_effIndex].ItemType, count, &noSpaceForCount); + InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellEffectInfo()->ItemType, count, &noSpaceForCount); if (msg != EQUIP_ERR_OK) { count-=noSpaceForCount; - plCaster->SendEquipError(msg, NULL, NULL, GetSpellInfo()->Effects[m_effIndex].ItemType); + plCaster->SendEquipError(msg, NULL, NULL, GetSpellEffectInfo()->ItemType); if (count == 0) return; } - Item* newitem = plCaster->StoreNewItem(dest, GetSpellInfo()->Effects[m_effIndex].ItemType, true); + Item* newitem = plCaster->StoreNewItem(dest, GetSpellEffectInfo()->ItemType, true); if (!newitem) { plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); @@ -5186,19 +5264,19 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo { Unit* target = aurApp->GetTarget(); - uint32 triggeredSpellId = sSpellMgr->GetSpellIdForDifficulty(m_spellInfo->Effects[m_effIndex].TriggerSpell, target); + uint32 triggeredSpellId = GetSpellEffectInfo()->TriggerSpell; SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggeredSpellId); if (!triggeredSpellInfo) return; + Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? GetCaster() : target; + if (!caster) + return; + if (mode & AURA_EFFECT_HANDLE_REAL) { if (apply) { - Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCaster() : target; - - if (!caster) - return; // If amount avalible cast with basepoints (Crypt Fever for example) if (GetAmount()) caster->CastCustomSpell(target, triggeredSpellId, &m_amount, NULL, NULL, true, NULL, this); @@ -5207,13 +5285,13 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo } else { - ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID(); + ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficulty()) ? GetCasterGUID() : target->GetGUID(); target->RemoveAura(triggeredSpellId, casterGUID, 0, aurApp->GetRemoveMode()); } } else if (mode & AURA_EFFECT_HANDLE_REAPPLY && apply) { - ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID(); + ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficulty()) ? GetCasterGUID() : target->GetGUID(); // change the stack amount to be equal to stack amount of our aura if (Aura* triggeredAura = target->GetAura(triggeredSpellId, casterGUID)) triggeredAura->ModStackAmount(GetBase()->GetStackAmount() - triggeredAura->GetStackAmount()); @@ -5384,7 +5462,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const } case 62292: // Blaze (Pool of Tar) // should we use custom damage? - target->CastSpell((Unit*)NULL, m_spellInfo->Effects[m_effIndex].TriggerSpell, true); + target->CastSpell((Unit*)NULL, GetSpellEffectInfo()->TriggerSpell, true); break; case 62399: // Overload Circuit if (target->GetMap()->IsDungeon() && int(target->GetAppliedAuras().count(62399)) >= (target->GetMap()->IsHeroic() ? 4 : 2)) @@ -5408,7 +5486,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const // Mirror Image if (GetId() == 55342) // Set name of summons to name of caster - target->CastSpell((Unit*)NULL, m_spellInfo->Effects[m_effIndex].TriggerSpell, true); + target->CastSpell((Unit*)NULL, GetSpellEffectInfo()->TriggerSpell, true); break; } case SPELLFAMILY_DRUID: @@ -5501,7 +5579,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const { // generic casting code with custom spells and target/caster customs - uint32 triggerSpellId = GetSpellInfo()->Effects[GetEffIndex()].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId); SpellInfo const* auraSpellInfo = GetSpellInfo(); @@ -5765,7 +5843,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) if (triggeredSpellInfo) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? caster : target) { triggerCaster->CastSpell(target, triggeredSpellInfo, true, NULL, this); TC_LOG_DEBUG("spells", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id); @@ -5782,10 +5860,10 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const { - uint32 triggerSpellId = GetSpellInfo()->Effects[m_effIndex].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? caster : target) { int32 basepoints = GetAmount(); triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints, &basepoints, &basepoints, true, nullptr, this); @@ -5808,7 +5886,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const } // Consecrate ticks can miss and will not show up in the combat log - if (GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -5827,11 +5905,14 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const break; case 38772: // Grievous Wound { - uint32 percent = GetSpellInfo()->Effects[EFFECT_1].CalcValue(caster); - if (!target->HealthBelowPct(percent)) + if (SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(DIFFICULTY_NONE, EFFECT_1)) { - target->RemoveAurasDueToSpell(GetSpellInfo()->Id); - return; + uint32 percent = effect->CalcValue(caster); + if (!target->HealthBelowPct(percent)) + { + target->RemoveAurasDueToSpell(GetSpellInfo()->Id); + return; + } } break; } @@ -5843,7 +5924,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); // AOE spells are not affected by the new periodic system. - bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; @@ -5858,7 +5939,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (caster->IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) { uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo()); cleanDamage.mitigated_damage += damage - damageReductedArmor; @@ -5902,7 +5983,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = uint32(target->CountPctFromMaxHealth(damage)); if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) - if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura) + if (GetSpellEffectInfo()->IsTargetingArea() || isAreaAura) { damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); if (caster->GetTypeId() != TYPEID_PLAYER) @@ -5950,6 +6031,18 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true); } +bool AuraEffect::IsAreaAuraEffect() const +{ + if (_effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PET || + _effectInfo->Effect == SPELL_EFFECT_APPLY_AREA_AURA_OWNER) + return true; + return false; +} + void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const { if (!caster || !target->IsAlive()) @@ -5961,7 +6054,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c return; } - if (GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -5969,7 +6062,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c uint32 resist = 0; CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL); - bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage uint32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; @@ -5982,7 +6075,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); // Calculate armor mitigation - if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) + if (caster->IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex())) { uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellInfo()); cleanDamage.mitigated_damage += damage - damageReductedArmor; @@ -5990,7 +6083,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c } if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE)) - if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura) + if (GetSpellEffectInfo()->IsTargetingArea() || isAreaAura) { damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); if (caster->GetTypeId() != TYPEID_PLAYER) @@ -6032,7 +6125,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), false); if (caster->IsAlive()) { - float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); uint32 heal = uint32(caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount())); heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount())); @@ -6063,7 +6156,7 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) caster->ModifyHealth(-(int32)damage); TC_LOG_DEBUG("spells", "PeriodicTick: donator %u target %u damage %u.", caster->GetEntry(), target->GetEntry(), damage); - float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); damage = int32(damage * gainMultiplier); @@ -6089,7 +6182,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const if (GetBase()->IsPermanent() && target->IsFullHealth()) return; - bool isAreaAura = m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); + bool isAreaAura = GetSpellEffectInfo()->IsAreaAuraEffect() || GetSpellEffectInfo()->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA); // ignore negative values (can be result apply spellmods to aura damage int32 damage = isAreaAura ? std::max(GetAmount(), 0) : m_damage; @@ -6196,7 +6289,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con return; } - if (GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && + if (GetSpellEffectInfo()->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA && caster->SpellHitResult(target, GetSpellInfo(), false) != SPELL_MISS_NONE) return; @@ -6219,7 +6312,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con int32 drainedAmount = -target->ModifyPower(powerType, -drainAmount); - float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float gainMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); SpellPeriodicAuraLogInfo pInfo(this, drainedAmount, 0, 0, 0, gainMultiplier, false); target->SendPeriodicAuraLog(&pInfo); @@ -6336,7 +6429,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con uint32 gain = uint32(-target->ModifyPower(powerType, -damage)); - float dmgMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster); + float dmgMultiplier = GetSpellEffectInfo()->CalcValueMultiplier(caster); SpellInfo const* spellProto = GetSpellInfo(); // maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG @@ -6365,7 +6458,7 @@ void AuraEffect::HandleProcTriggerSpellAuraProc(AuraApplication* aurApp, ProcEve Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellInfo()->Effects[GetEffIndex()].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { TC_LOG_DEBUG("spells", "AuraEffect::HandleProcTriggerSpellAuraProc: Triggering spell %u from aura %u proc", triggeredSpellInfo->Id, GetId()); @@ -6380,7 +6473,7 @@ void AuraEffect::HandleProcTriggerSpellWithValueAuraProc(AuraApplication* aurApp Unit* triggerCaster = aurApp->GetTarget(); Unit* triggerTarget = eventInfo.GetProcTarget(); - uint32 triggerSpellId = GetSpellInfo()->Effects[m_effIndex].TriggerSpell; + uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { int32 basepoints0 = GetAmount(); @@ -6438,7 +6531,7 @@ void AuraEffect::HandleRaidProcFromChargeAuraProc(AuraApplication* aurApp, ProcE { if (Unit* caster = GetCaster()) { - float radius = GetSpellInfo()->Effects[GetEffIndex()].CalcRadius(caster); + float radius = GetSpellEffectInfo()->CalcRadius(caster); if (Unit* triggerTarget = target->GetNextRandomRaidMemberOrPet(radius)) { @@ -6479,7 +6572,7 @@ void AuraEffect::HandleRaidProcFromChargeWithValueAuraProc(AuraApplication* aurA { if (Unit* caster = GetCaster()) { - float radius = GetSpellInfo()->Effects[GetEffIndex()].CalcRadius(caster); + float radius = GetSpellEffectInfo()->CalcRadius(caster); if (Unit* triggerTarget = target->GetNextRandomRaidMemberOrPet(radius)) { diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 22571f4851e..3e48fef140a 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -29,13 +29,13 @@ typedef void(AuraEffect::*pAuraEffectHandler)(AuraApplication const* aurApp, uin class AuraEffect { - friend void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount); - friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID); + friend void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount); + friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); friend Aura::~Aura(); - private: - ~AuraEffect(); - explicit AuraEffect(Aura* base, uint8 effIndex, int32 *baseAmount, Unit* caster); + public: + ~AuraEffect(); + AuraEffect(Aura* base, uint32 effIndex, int32 *baseAmount, Unit* caster); Unit* GetCaster() const { return GetBase()->GetCaster(); } ObjectGuid GetCasterGUID() const { return GetBase()->GetCasterGUID(); } Aura* GetBase() const { return m_base; } @@ -49,9 +49,9 @@ class AuraEffect int32 GetBaseAmount() const { return m_baseAmount; } int32 GetPeriod() const { return m_period; } - int32 GetMiscValueB() const { return m_spellInfo->Effects[m_effIndex].MiscValueB; } - int32 GetMiscValue() const { return m_spellInfo->Effects[m_effIndex].MiscValue; } - AuraType GetAuraType() const { return (AuraType)m_spellInfo->Effects[m_effIndex].ApplyAuraName; } + int32 GetMiscValueB() const { return GetSpellEffectInfo()->MiscValueB; } + int32 GetMiscValue() const { return GetSpellEffectInfo()->MiscValue; } + AuraType GetAuraType() const { return (AuraType)GetSpellEffectInfo()->ApplyAuraName; } int32 GetAmount() const { return m_amount; } void SetAmount(int32 amount) { m_amount = amount; m_canBeRecalculated = false;} @@ -87,7 +87,7 @@ class AuraEffect bool IsPeriodic() const { return m_isPeriodic; } void SetPeriodic(bool isPeriodic) { m_isPeriodic = isPeriodic; } bool IsAffectingSpell(SpellInfo const* spell) const; - bool HasSpellClassMask() const { return m_spellInfo->Effects[m_effIndex].SpellClassMask; } + bool HasSpellClassMask() const { return GetSpellEffectInfo()->SpellClassMask; } void SendTickImmune(Unit* target, Unit* caster) const; void PeriodicTick(AuraApplication * aurApp, Unit* caster) const; @@ -98,10 +98,18 @@ class AuraEffect // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras void HandleShapeshiftBoosts(Unit* target, bool apply) const; + + SpellEffectInfo const* GetSpellEffectInfo() const { return _effectInfo; } + + bool IsEffect() const { return _effectInfo->Effect != 0; } + bool IsEffect(SpellEffectName effectName) const { return _effectInfo->Effect == uint32(effectName); } + bool IsAreaAuraEffect() const; + private: Aura* const m_base; SpellInfo const* const m_spellInfo; + SpellEffectInfo const* _effectInfo; int32 const m_baseAmount; int32 m_amount; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 67df56d892e..015ce3224a3 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -26,6 +26,7 @@ #include "Unit.h" #include "Spell.h" #include "SpellAuraEffects.h" +#include "SpellPackets.h" #include "DynamicObject.h" #include "ObjectAccessor.h" #include "Util.h" @@ -37,9 +38,9 @@ #include "Vehicle.h" #include "Config.h" -AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint8 effMask): +AuraApplication::AuraApplication(Unit* target, Unit* caster, Aura* aura, uint32 effMask): _target(target), _base(aura), _removeMode(AURA_REMOVE_NONE), _slot(MAX_AURAS), -_flags(AFLAG_NONE), _effectsToApply(effMask), _needClientUpdate(false) +_flags(AFLAG_NONE), _effectsToApply(effMask), _needClientUpdate(false), _effectMask(0) { ASSERT(GetTarget() && GetBase()); @@ -113,19 +114,19 @@ void AuraApplication::_Remove() } } -void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) +void AuraApplication::_InitFlags(Unit* caster, uint32 effMask) { // mark as selfcast if needed - _flags |= (GetBase()->GetCasterGUID() == GetTarget()->GetGUID()) ? AFLAG_CASTER : AFLAG_NONE; + _flags |= (GetBase()->GetCasterGUID() == GetTarget()->GetGUID()) ? AFLAG_NONE : AFLAG_NOCASTER; // aura is cast by self or an enemy // one negative effect and we know aura is negative if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget())) { bool negativeFound = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos()) { - if (((1<<i) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(i)) + if (effect && ((1 << effect->EffectIndex) & effMask) && !GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) { negativeFound = true; break; @@ -138,9 +139,9 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) else { bool positiveFound = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetBase()->GetSpellEffectInfos()) { - if (((1<<i) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(i)) + if (effect && ((1 << effect->EffectIndex) & effMask) && GetBase()->GetSpellInfo()->IsPositiveEffect(effect->EffectIndex)) { positiveFound = true; break; @@ -150,12 +151,17 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) } if (GetBase()->GetSpellInfo()->AttributesEx8 & SPELL_ATTR8_AURA_SEND_AMOUNT) - _flags |= AFLAG_ANY_EFFECT_AMOUNT_SENT; + _flags |= AFLAG_SCALABLE; } void AuraApplication::_HandleEffect(uint8 effIndex, bool apply) { AuraEffect* aurEff = GetBase()->GetEffect(effIndex); + if (!aurEff) + { + TC_LOG_ERROR("spells", "Aura %u has no effect at effectIndex %u but _HandleEffect was called", GetBase()->GetSpellInfo()->Id, uint32(effIndex)); + return; + } ASSERT(aurEff); ASSERT(HasEffect(effIndex) == (!apply)); ASSERT((1<<effIndex) & _effectsToApply); @@ -163,14 +169,14 @@ void AuraApplication::_HandleEffect(uint8 effIndex, bool apply) if (apply) { - ASSERT(!(_flags & (1<<effIndex))); - _flags |= 1<<effIndex; + ASSERT(!(_effectMask & (1<<effIndex))); + _effectMask |= 1<<effIndex; aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, true); } else { - ASSERT(_flags & (1<<effIndex)); - _flags &= ~(1<<effIndex); + ASSERT(_effectMask & (1<<effIndex)); + _effectMask &= ~(1<<effIndex); aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, false); // Remove all triggered by aura spells vs unlimited duration @@ -193,7 +199,7 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const Aura const* aura = GetBase(); data << uint32(aura->GetId()); - uint32 flags = _flags; + uint8 flags = _flags; if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION)) flags |= AFLAG_DURATION; data << uint16(flags); @@ -202,7 +208,7 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const // stack amount has priority over charges (checked on retail with spell 50262) data << uint8(aura->GetSpellInfo()->StackAmount ? aura->GetStackAmount() : aura->GetCharges()); - if (!(flags & AFLAG_CASTER)) + if (!(flags & AFLAG_NOCASTER)) data << aura->GetCasterGUID().WriteAsPacked(); if (flags & AFLAG_DURATION) @@ -211,44 +217,43 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const data << uint32(aura->GetDuration()); } - if (flags & AFLAG_ANY_EFFECT_AMOUNT_SENT) - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (AuraEffect const* eff = aura->GetEffect(i)) - if (HasEffect(i)) // Not all of aura's effects have to be applied on every target - data << int32(eff->GetAmount()); + if (flags & AFLAG_SCALABLE) + for (AuraEffect const* effect : GetBase()->GetAuraEffects()) + if (effect && HasEffect(effect->GetEffIndex())) // Not all of aura's effects have to be applied on every target + data << int32(effect->GetAmount()); } void AuraApplication::ClientUpdate(bool remove) { _needClientUpdate = false; - WorldPacket data(SMSG_AURA_UPDATE); - data << GetTarget()->GetPackGUID(); - BuildUpdatePacket(data, remove); + WorldPackets::Spells::SendAuraUpdate update; + update.Init(false, GetTarget()->GetGUID(), 1); + update.BuildUpdatePacket(this, remove, GetTarget()->getLevel()); // TODO 6.x should be caster's level - _target->SendMessageToSet(&data, true); + _target->SendMessageToSet(const_cast<WorldPacket*>(update.Write()), true); } -uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleEffectMask, WorldObject* owner) +uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 avalibleEffectMask, WorldObject* owner) { ASSERT(spellProto); ASSERT(owner); - uint8 effMask = 0; + uint32 effMask = 0; switch (owner->GetTypeId()) { case TYPEID_UNIT: case TYPEID_PLAYER: - for (uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficulty())) { - if (spellProto->Effects[i].IsUnitOwnedAuraEffect()) - effMask |= 1 << i; + if (effect && effect->IsUnitOwnedAuraEffect()) + effMask |= 1 << effect->EffectIndex; } break; case TYPEID_DYNAMICOBJECT: - for (uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficulty())) { - if (spellProto->Effects[i].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) - effMask |= 1 << i; + if (effect && effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) + effMask |= 1 << effect->EffectIndex; } break; default: @@ -257,7 +262,7 @@ uint8 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleE return effMask & avalibleEffectMask; } -Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= NULL*/) +Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool* refresh /*= NULL*/) { ASSERT(spellproto); ASSERT(owner); @@ -265,9 +270,10 @@ Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMas ASSERT(tryEffMask <= MAX_EFFECT_MASK); if (refresh) *refresh = false; - uint8 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner); + uint32 effMask = Aura::BuildEffectMaskForOwner(spellproto, tryEffMask, owner); if (!effMask) return NULL; + if (Aura* foundAura = owner->ToUnit()->_TryStackingOrRefreshingExistingAura(spellproto, effMask, caster, baseAmount, castItem, casterGUID)) { // we've here aura, which script triggered removal after modding stack amount @@ -283,7 +289,7 @@ Aura* Aura::TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMas return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID); } -Aura* Aura::TryCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/) +Aura* Aura::TryCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount /*= NULL*/, Item* castItem /*= NULL*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/) { ASSERT(spellproto); ASSERT(owner); @@ -295,7 +301,7 @@ Aura* Aura::TryCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject return Create(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID); } -Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID) +Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) { ASSERT(effMask); ASSERT(spellproto); @@ -354,7 +360,6 @@ m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEven m_duration = m_maxDuration; m_procCharges = CalcMaxCharges(caster); m_isUsingCharges = m_procCharges != 0; - memset(m_effects, 0, sizeof(m_effects)); // m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs } @@ -366,15 +371,27 @@ AuraScript* Aura::GetScriptByName(std::string const& scriptName) const return NULL; } -void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount) +SpellEffectInfo const* Aura::GetSpellEffectInfo(uint32 index) const +{ + if (index >= _spelEffectInfos.size()) + return nullptr; + + return _spelEffectInfos[index]; +} + +void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount) { // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + _spelEffectInfos = m_spellInfo->GetEffectsForDifficulty(GetOwner()->GetMap()->GetDifficulty()); + + ASSERT(!_spelEffectInfos.empty()); + + _effects.resize(MAX_SPELL_EFFECTS); + + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) { - if (effMask & (uint8(1) << i)) - m_effects[i] = new AuraEffect(this, i, baseAmount ? baseAmount + i : NULL, caster); - else - m_effects[i] = NULL; + if (effect && effMask & (uint8(1) << effect->EffectIndex)) + _effects[effect->EffectIndex] = new AuraEffect(this, effect->EffectIndex, baseAmount ? baseAmount + effect->EffectIndex : NULL, caster); } } @@ -389,9 +406,9 @@ Aura::~Aura() m_loadedScripts.erase(itr); } - // free effects memory - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - delete m_effects[i]; + // free effects memory todo 6.x + //for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + // delete m_effects[i]; ASSERT(m_applications.empty()); _DeleteRemovedApplications(); @@ -407,6 +424,14 @@ Unit* Aura::GetCaster() const return ObjectAccessor::GetUnit(*GetOwner(), GetCasterGUID()); } +AuraEffect* Aura::GetEffect(uint32 index) const +{ + if (index >= _effects.size()) + return nullptr; + + return _effects[index]; +} + AuraObjectType Aura::GetType() const { return (m_owner->GetTypeId() == TYPEID_DYNAMICOBJECT) ? DYNOBJ_AURA_TYPE : UNIT_AURA_TYPE; @@ -494,7 +519,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) // fill up to date target list // target, effMask - std::map<Unit*, uint8> targets; + std::map<Unit*, uint32> targets; FillTargetMap(targets, caster); @@ -503,7 +528,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) // mark all auras as ready to remove for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end();++appIter) { - std::map<Unit*, uint8>::iterator existing = targets.find(appIter->second->GetTarget()); + std::map<Unit*, uint32>::iterator existing = targets.find(appIter->second->GetTarget()); // not found in current area - remove the aura if (existing == targets.end()) targetsToRemove.push_back(appIter->second->GetTarget()); @@ -520,7 +545,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) } // register auras for units - for (std::map<Unit*, uint8>::iterator itr = targets.begin(); itr!= targets.end();) + for (std::map<Unit*, uint32>::iterator itr = targets.begin(); itr!= targets.end();) { // aura mustn't be already applied on target if (AuraApplication * aurApp = GetApplicationOfTarget(itr->first->GetGUID())) @@ -613,7 +638,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) return; // apply aura effects for units - for (std::map<Unit*, uint8>::iterator itr = targets.begin(); itr!= targets.end();++itr) + for (std::map<Unit*, uint32>::iterator itr = targets.begin(); itr!= targets.end();++itr) { if (AuraApplication * aurApp = GetApplicationOfTarget(itr->first->GetGUID())) { @@ -674,9 +699,9 @@ void Aura::UpdateOwner(uint32 diff, WorldObject* owner) m_updateTargetMapInterval -= diff; // update aura effects - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_effects[i]) - m_effects[i]->Update(diff, caster); + for (AuraEffect* effect : GetAuraEffects()) + if (effect) + effect->Update(diff, caster); // remove spellmods after effects update if (modSpell) @@ -880,9 +905,9 @@ void Aura::SetStackAmount(uint8 stackAmount) if (!(*apptItr)->GetRemoveMode()) HandleAuraSpecificMods(*apptItr, caster, false, true); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i)) - m_effects[i]->ChangeAmount(m_effects[i]->CalculateAmount(caster), false, true); + for (AuraEffect* effect : GetAuraEffects()) + if (effect) + effect->ChangeAmount(effect->CalculateAmount(caster), false, true); for (std::list<AuraApplication*>::const_iterator apptItr = applications.begin(); apptItr != applications.end(); ++apptItr) if (!(*apptItr)->GetRemoveMode()) @@ -945,11 +970,11 @@ void Aura::RefreshSpellMods() player->RestoreAllSpellMods(0, this); } -bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const +bool Aura::HasMoreThanOneEffectForType(AuraType auraType, uint32 difficulty) const { uint32 count = 0; - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i) && AuraType(GetSpellInfo()->Effects[i].ApplyAuraName) == auraType) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) + if (effect && HasEffect(effect->EffectIndex) && AuraType(effect->ApplyAuraName) == auraType) ++count; return count > 1; @@ -957,8 +982,8 @@ bool Aura::HasMoreThanOneEffectForType(AuraType auraType) const bool Aura::IsArea() const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i) && GetSpellInfo()->Effects[i].IsAreaAuraEffect()) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) + if (effect && HasEffect(effect->EffectIndex) && effect->IsAreaAuraEffect()) return true; return false; @@ -1020,7 +1045,7 @@ bool Aura::CanBeSaved() const bool Aura::CanBeSentToClient() const { - return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect() || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING); + return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect(GetOwner() ? GetOwner()->GetMap()->GetDifficulty() : DIFFICULTY_NONE) || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING); } bool Aura::IsSingleTargetWith(Aura const* aura) const @@ -1080,7 +1105,7 @@ int32 Aura::CalcDispelChance(Unit* auraTarget, bool offensive) const return 100 - resistChance; } -void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount) +void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 *amount) { m_maxDuration = maxduration; m_duration = duration; @@ -1088,22 +1113,23 @@ void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint m_isUsingCharges = m_procCharges != 0; m_stackAmount = stackamount; Unit* caster = GetCaster(); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_effects[i]) - { - m_effects[i]->SetAmount(amount[i]); - m_effects[i]->SetCanBeRecalculated((recalculateMask & (1 << i)) != 0); - m_effects[i]->CalculatePeriodic(caster, false, true); - m_effects[i]->CalculateSpellMod(); - m_effects[i]->RecalculateAmount(caster); - } + for (AuraEffect* effect : GetAuraEffects()) + { + if (!effect) + continue; + effect->SetAmount(amount[effect->GetEffIndex()]); + effect->SetCanBeRecalculated((recalculateMask & (1 << effect->GetEffIndex())) != 0); + effect->CalculatePeriodic(caster, false, true); + effect->CalculateSpellMod(); + effect->RecalculateAmount(caster); + } } bool Aura::HasEffectType(AuraType type) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (AuraEffect* effect : GetAuraEffects()) { - if (HasEffect(i) && m_effects[i]->GetAuraType() == type) + if (effect && effect->GetAuraType() == type) return true; } return false; @@ -1113,17 +1139,26 @@ void Aura::RecalculateAmountOfEffects() { ASSERT (!IsRemoved()); Unit* caster = GetCaster(); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (HasEffect(i)) - m_effects[i]->RecalculateAmount(caster); + for (AuraEffect* effect : GetAuraEffects()) + if (effect && !IsRemoved()) + effect->RecalculateAmount(caster); } void Aura::HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply) { ASSERT (!IsRemoved()); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_effects[i] && !IsRemoved()) - m_effects[i]->HandleEffect(aurApp, mode, apply); + for (AuraEffect* effect : GetAuraEffects()) + if (effect && !IsRemoved()) + effect->HandleEffect(aurApp, mode, apply); +} + +uint32 Aura::GetEffectMask() const +{ + uint32 effMask = 0; + for (AuraEffect* effect : GetAuraEffects()) + if (effect) + effMask |= 1 << effect->GetEffIndex(); + return effMask; } void Aura::GetApplicationList(std::list<AuraApplication*> & applicationList) const @@ -1517,47 +1552,40 @@ void Aura::HandleAuraSpecificPeriodics(AuraApplication const* aurApp, Unit* cast if (!caster || aurApp->GetRemoveMode()) return; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (AuraEffect* effect : GetAuraEffects()) { - if (!HasEffect(i)) + if (!effect || effect->IsAreaAuraEffect() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) continue; - if (m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) - continue; - - switch (m_spellInfo->Effects[i].ApplyAuraName) + switch (effect->GetSpellEffectInfo()->ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: case SPELL_AURA_PERIODIC_LEECH: { - AuraEffect* aurEff = GetEffect(i); - // ignore non positive values (can be result apply spellmods to aura damage - uint32 damage = std::max(aurEff->GetAmount(), 0); + uint32 damage = std::max(effect->GetAmount(), 0); // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); - aurEff->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT)); // Calculate done percentage first! - aurEff->SetDamage(caster->SpellDamageBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct()); - aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); + effect->SetDonePct(caster->SpellDamagePctDone(target, m_spellInfo, DOT)); // Calculate done percentage first! + effect->SetDamage(caster->SpellDamageBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * effect->GetDonePct()); + effect->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); break; } case SPELL_AURA_PERIODIC_HEAL: case SPELL_AURA_OBS_MOD_HEALTH: { - AuraEffect* aurEff = GetEffect(i); - // ignore non positive values (can be result apply spellmods to aura damage - uint32 damage = std::max(aurEff->GetAmount(), 0); + uint32 damage = std::max(effect->GetAmount(), 0); // Script Hook For HandlePeriodicDamageAurasTick -- Allow scripts to change the Damage pre class mitigation calculations sScriptMgr->ModifyPeriodicDamageAurasTick(target, caster, damage); - aurEff->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo)); // Calculate done percentage first! - aurEff->SetDamage(caster->SpellHealingBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * aurEff->GetDonePct()); - aurEff->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); + effect->SetDonePct(caster->SpellHealingPctDone(target, m_spellInfo)); // Calculate done percentage first! + effect->SetDamage(caster->SpellHealingBonusDone(target, m_spellInfo, damage, DOT, GetStackAmount()) * effect->GetDonePct()); + effect->SetCritChance(caster->GetUnitSpellCriticalChance(target, m_spellInfo, m_spellInfo->GetSchoolMask())); break; } default: @@ -1605,12 +1633,17 @@ bool Aura::CanStackWith(Aura const* existingAura) const if (IsPassive() && sameCaster && m_spellInfo->IsDifferentRankOf(existingSpellInfo)) return false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : existingAura->GetSpellEffectInfos()) { // prevent remove triggering aura by triggered aura - if (existingSpellInfo->Effects[i].TriggerSpell == GetId() - // prevent remove triggered aura by triggering aura refresh - || m_spellInfo->Effects[i].TriggerSpell == existingAura->GetId()) + if (effect && effect->TriggerSpell == GetId()) + return true; + } + + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) + { + // prevent remove triggered aura by triggering aura refresh + if (effect && effect->TriggerSpell == existingAura->GetId()) return true; } @@ -1620,7 +1653,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const // * The minimap tracking list will only show a check mark next to the last skill activated // Sometimes this bugs out and doesn't switch the check mark. It has no effect on the actual tracking though. // * The minimap dots are yellow for both resources - if (m_spellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(SPELL_AURA_TRACK_RESOURCES)) + if (m_spellInfo->HasAura(GetOwner()->GetMap()->GetDifficulty(), SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(GetOwner()->GetMap()->GetDifficulty(), SPELL_AURA_TRACK_RESOURCES)) return sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES); // check spell specific stack rules @@ -1659,7 +1692,10 @@ bool Aura::CanStackWith(Aura const* existingAura) const // check same periodic auras for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - switch (m_spellInfo->Effects[i].ApplyAuraName) + SpellEffectInfo const* effect = GetSpellEffectInfo(i); + if (!effect) + continue; + switch (effect->ApplyAuraName) { // DOT or HOT from different casters will stack case SPELL_AURA_PERIODIC_DAMAGE: @@ -1673,9 +1709,12 @@ bool Aura::CanStackWith(Aura const* existingAura) const case SPELL_AURA_OBS_MOD_POWER: case SPELL_AURA_OBS_MOD_HEALTH: case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - // periodic auras which target areas are not allowed to stack this way (replenishment for example) - if (m_spellInfo->Effects[i].IsTargetingArea() || existingSpellInfo->Effects[i].IsTargetingArea()) - break; + { + SpellEffectInfo const* existingEffect = GetSpellEffectInfo(i); + // periodic auras which target areas are not allowed to stack this way (replenishment for example) + if (effect->IsTargetingArea() || (existingEffect && existingEffect->IsTargetingArea())) + break; + } return true; default: break; @@ -2246,7 +2285,7 @@ void Aura::CallScriptAfterEffectProcHandlers(AuraEffect const* aurEff, AuraAppli } } -UnitAura::UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) +UnitAura::UnitAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) : Aura(spellproto, owner, caster, castItem, casterGUID) { m_AuraDRGroup = DIMINISHING_NONE; @@ -2280,31 +2319,31 @@ void UnitAura::Remove(AuraRemoveMode removeMode) GetUnitOwner()->RemoveOwnedAura(this, removeMode); } -void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) +void UnitAura::FillTargetMap(std::map<Unit*, uint32> & targets, Unit* caster) { - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) { - if (!HasEffect(effIndex)) + if (!effect || !HasEffect(effect->EffectIndex)) continue; UnitList targetList; // non-area aura - if (GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AURA) + if (effect->Effect == SPELL_EFFECT_APPLY_AURA) { targetList.push_back(GetUnitOwner()); } else { - float radius = GetSpellInfo()->Effects[effIndex].CalcRadius(caster); + float radius = effect->CalcRadius(caster); if (!GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED)) { - switch (GetSpellInfo()->Effects[effIndex].Effect) + switch (effect->Effect) { case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: case SPELL_EFFECT_APPLY_AREA_AURA_RAID: { targetList.push_back(GetUnitOwner()); - Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID); + Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID); Trinity::UnitListSearcher<Trinity::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; @@ -2340,16 +2379,16 @@ void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) for (UnitList::iterator itr = targetList.begin(); itr!= targetList.end();++itr) { - std::map<Unit*, uint8>::iterator existing = targets.find(*itr); + std::map<Unit*, uint32>::iterator existing = targets.find(*itr); if (existing != targets.end()) - existing->second |= 1<<effIndex; + existing->second |= 1 << effect->EffectIndex; else - targets[*itr] = 1<<effIndex; + targets[*itr] = 1 << effect->EffectIndex; } } } -DynObjAura::DynObjAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) +DynObjAura::DynObjAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID) : Aura(spellproto, owner, caster, castItem, casterGUID) { LoadScripts(); @@ -2374,18 +2413,18 @@ void DynObjAura::Remove(AuraRemoveMode removeMode) _Remove(removeMode); } -void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster*/) +void DynObjAura::FillTargetMap(std::map<Unit*, uint32> & targets, Unit* /*caster*/) { Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster(); float radius = GetDynobjOwner()->GetRadius(); - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetSpellEffectInfos()) { - if (!HasEffect(effIndex)) + if (!effect || !HasEffect(effect->EffectIndex)) continue; UnitList targetList; - if (GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY - || GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY) + if (effect->TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY + || effect->TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY) { Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targetList, u_check); @@ -2400,11 +2439,11 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster* for (UnitList::iterator itr = targetList.begin(); itr!= targetList.end();++itr) { - std::map<Unit*, uint8>::iterator existing = targets.find(*itr); + std::map<Unit*, uint32>::iterator existing = targets.find(*itr); if (existing != targets.end()) - existing->second |= 1<<effIndex; + existing->second |= 1 << effect->EffectIndex; else - targets[*itr] = 1<<effIndex; + targets[*itr] = 1 << effect->EffectIndex; } } } diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index f69d9baafe0..c2c356efa4b 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -41,24 +41,25 @@ class ChargeDropEvent; class AuraApplication { - friend void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask); + friend void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask); friend void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode); friend void Unit::_ApplyAuraEffect(Aura* aura, uint8 effIndex); friend void Unit::RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode); - friend AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint8 effMask); + friend AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 effMask); private: Unit* const _target; Aura* const _base; AuraRemoveMode _removeMode:8; // Store info for know remove aura reason uint8 _slot; // Aura slot on unit uint8 _flags; // Aura info flag - uint8 _effectsToApply; // Used only at spell hit to determine which effect should be applied + uint32 _effectsToApply; // Used only at spell hit to determine which effect should be applied bool _needClientUpdate:1; + uint32 _effectMask; - explicit AuraApplication(Unit* target, Unit* caster, Aura* base, uint8 effMask); + explicit AuraApplication(Unit* target, Unit* caster, Aura* base, uint32 effMask); void _Remove(); private: - void _InitFlags(Unit* caster, uint8 effMask); + void _InitFlags(Unit* caster, uint32 effMask); void _HandleEffect(uint8 effIndex, bool apply); public: @@ -67,10 +68,10 @@ class AuraApplication uint8 GetSlot() const { return _slot; } uint8 GetFlags() const { return _flags; } - uint8 GetEffectMask() const { return _flags & (AFLAG_EFF_INDEX_0 | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2); } - bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return (_flags & (1 << effect)) != 0; } + uint32 GetEffectMask() const { return _effectMask; } + bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return (_effectMask & (1 << effect)) != 0; } bool IsPositive() const { return (_flags & AFLAG_POSITIVE) != 0; } - bool IsSelfcast() const { return (_flags & AFLAG_CASTER) != 0; } + bool IsSelfcast() const { return (_flags & AFLAG_NOCASTER) == 0; } uint8 GetEffectsToApply() const { return _effectsToApply; } void SetRemoveMode(AuraRemoveMode mode) { _removeMode = mode; } @@ -84,16 +85,16 @@ class AuraApplication class Aura { - friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint32 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); public: typedef std::map<ObjectGuid, AuraApplication*> ApplicationMap; - static uint8 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint8 avalibleEffectMask, WorldObject* owner); - static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, uint8 tryEffMask, WorldObject* owner, Unit* caster, int32* baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = NULL); - static Aura* TryCreate(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); - static Aura* Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID); + static uint32 BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 avalibleEffectMask, WorldObject* owner); + static Aura* TryRefreshStackOrCreate(SpellInfo const* spellproto, uint32 tryEffMask, WorldObject* owner, Unit* caster, int32 *baseAmount = NULL, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty, bool* refresh = NULL); + static Aura* TryCreate(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem = NULL, ObjectGuid casterGUID = ObjectGuid::Empty); + static Aura* Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); explicit Aura(SpellInfo const* spellproto, WorldObject* owner, Unit* caster, Item* castItem, ObjectGuid casterGUID); - void _InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount); + void _InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount); virtual ~Aura(); SpellInfo const* GetSpellInfo() const { return m_spellInfo; } @@ -113,7 +114,7 @@ class Aura void _Remove(AuraRemoveMode removeMode); virtual void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) = 0; - virtual void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) = 0; + virtual void FillTargetMap(std::map<Unit*, uint32> & targets, Unit* caster) = 0; void UpdateTargetMap(Unit* caster, bool apply = true); void _RegisterForTargets() {Unit* caster = GetCaster(); UpdateTargetMap(caster, false);} @@ -152,7 +153,7 @@ class Aura uint8 GetCasterLevel() const { return m_casterLevel; } - bool HasMoreThanOneEffectForType(AuraType auraType) const; + bool HasMoreThanOneEffectForType(AuraType auraType, uint32 difficulty) const; bool IsArea() const; bool IsPassive() const; bool IsDeathPersistent() const; @@ -175,13 +176,14 @@ class Aura void UnregisterSingleTarget(); int32 CalcDispelChance(Unit* auraTarget, bool offensive) const; - void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount); + void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 *baseAmount); // helpers for aura effects bool HasEffect(uint8 effIndex) const { return GetEffect(effIndex) != NULL; } bool HasEffectType(AuraType type) const; - AuraEffect* GetEffect(uint8 effIndex) const { ASSERT (effIndex < MAX_SPELL_EFFECTS); return m_effects[effIndex]; } - uint8 GetEffectMask() const { uint8 effMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (m_effects[i]) effMask |= 1<<i; return effMask; } + //AuraEffect* GetEffect(uint8 effIndex) const { ASSERT (effIndex < MAX_SPELL_EFFECTS); return Effects[effIndex]; } + AuraEffect* GetEffect(uint32 index) const; + uint32 GetEffectMask() const; void RecalculateAmountOfEffects(); void HandleAllEffects(AuraApplication * aurApp, uint8 mode, bool apply); @@ -242,6 +244,12 @@ class Aura AuraScript* GetScriptByName(std::string const& scriptName) const; std::list<AuraScript*> m_loadedScripts; + + AuraEffectVector GetAuraEffects() const { return _effects; } + + SpellEffectInfoVector GetSpellEffectInfos() const { return _spelEffectInfos; } + SpellEffectInfo const* GetSpellEffectInfo(uint32 index) const; + private: void _DeleteRemovedApplications(); protected: @@ -260,7 +268,7 @@ class Aura uint8 m_procCharges; // Aura charges (0 for infinite) uint8 m_stackAmount; // Aura stack amount - AuraEffect* m_effects[3]; + //AuraEffect* m_effects[3]; ApplicationMap m_applications; bool m_isRemoved:1; @@ -271,20 +279,23 @@ class Aura private: Unit::AuraApplicationList m_removedApplications; + + AuraEffectVector _effects; + SpellEffectInfoVector _spelEffectInfos; }; class UnitAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); - protected: - explicit UnitAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); public: + explicit UnitAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + void _ApplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; void _UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * aurApp) override; void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override; - void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override; + void FillTargetMap(std::map<Unit*, uint32> & targets, Unit* caster) override; // Allow Apply Aura Handler to modify and access m_AuraDRGroup void SetDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } @@ -296,13 +307,13 @@ class UnitAura : public Aura class DynObjAura : public Aura { - friend Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); - protected: - explicit DynObjAura(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + friend Aura* Aura::Create(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); public: + explicit DynObjAura(SpellInfo const* spellproto, uint32 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID); + void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override; - void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override; + void FillTargetMap(std::map<Unit*, uint32> & targets, Unit* caster) override; }; class ChargeDropEvent : public BasicEvent diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 714284651b2..304852b3176 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -57,6 +57,7 @@ #include "DB2Stores.h" #include "Battlefield.h" #include "BattlefieldMgr.h" +#include "SpellPackets.h" extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; @@ -118,6 +119,28 @@ SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0), m_strTarget() m_targetMask = 0; } +SpellCastTargets::SpellCastTargets(Unit* caster, uint32 targetMask, ObjectGuid targetGuid, ObjectGuid itemTargetGuid, ObjectGuid srcTransportGuid, ObjectGuid destTransportGuid, Position srcPos, Position destPos, float elevation, float missileSpeed, std::string targetString) : + m_targetMask(targetMask), m_objectTargetGUID(targetGuid), m_itemTargetGUID(itemTargetGuid), m_elevation(elevation), m_speed(missileSpeed), m_strTarget(targetString) +{ + m_objectTarget = NULL; + m_itemTarget = NULL; + m_itemTargetEntry = 0; + + m_src._transportGUID = srcTransportGuid; + if (m_src._transportGUID != ObjectGuid::Empty) + m_src._transportOffset.Relocate(srcPos); + else + m_src._position.Relocate(srcPos); + + m_dst._transportGUID = destTransportGuid; + if (m_dst._transportGUID != ObjectGuid::Empty) + m_dst._transportOffset.Relocate(destPos); + else + m_dst._position.Relocate(destPos); + + Update(caster); +} + SpellCastTargets::~SpellCastTargets() { } void SpellCastTargets::Read(ByteBuffer& data, Unit* caster) @@ -173,9 +196,41 @@ void SpellCastTargets::Read(ByteBuffer& data, Unit* caster) Update(caster); } -void SpellCastTargets::Write(ByteBuffer& data) +void SpellCastTargets::Write(WorldPackets::Spells::SpellTargetData& data) { - data << uint32(m_targetMask); + data.Flags = m_targetMask; + + if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET)) + data.Unit = m_objectTargetGUID; + + if (m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM) && m_itemTarget) + data.Item = m_itemTarget->GetGUID(); + + if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION) + { + WorldPackets::Spells::TargetLocation& target = data.SrcLocation.Value; + target.Transport = m_src._transportGUID; // relative position guid here - transport for example + if (!m_src._transportGUID.IsEmpty()) + target.Location = m_src._transportOffset; + else + target.Location = m_src._position; + data.SrcLocation.HasValue = true; + } + + if (m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + WorldPackets::Spells::TargetLocation& target = data.DstLocation.Value; + target.Transport = m_dst._transportGUID; // relative position guid here - transport for example + if (!m_dst._transportGUID.IsEmpty()) + target.Location = m_dst._transportOffset; + else + target.Location = m_dst._position; + data.DstLocation.HasValue = true; + } + + if (m_targetMask & TARGET_FLAG_STRING) + data.Name = m_strTarget; + /*data << uint32(m_targetMask); if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_MINIPET)) data << m_objectTargetGUID.WriteAsPacked(); @@ -207,7 +262,7 @@ void SpellCastTargets::Write(ByteBuffer& data) } if (m_targetMask & TARGET_FLAG_STRING) - data << m_strTarget; + data << m_strTarget;*/ } ObjectGuid SpellCastTargets::GetOrigUnitTargetGUID() const @@ -509,18 +564,20 @@ void SpellCastTargets::OutDebug() const SpellValue::SpellValue(SpellInfo const* proto) { - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - EffectBasePoints[i] = proto->Effects[i].BasePoints; + // todo 6.x + //for (uint32 i = 0; i < proto->Effects.size(); ++i) + // EffectBasePoints[i] = proto->Effects[i].BasePoints; MaxAffectedTargets = proto->MaxAffectedTargets; RadiusMod = 1.0f; AuraStackAmount = 1; } Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) : -m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)), -m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster) -, m_spellValue(new SpellValue(m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster)) +m_spellInfo(info), m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster), +m_spellValue(new SpellValue(m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster)) { + _effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficulty()); + m_customError = SPELL_CUSTOM_ERROR_NONE; m_skipCheck = skipCheck; m_selfContainer = NULL; @@ -764,36 +821,40 @@ void Spell::SelectSpellTargets() SelectExplicitTargets(); uint32 processedAreaEffectsMask = 0; - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + + for (SpellEffectInfo const* effect : GetEffects()) { + if (!effect) + continue; + // not call for empty effect. // Also some spells use not used effect targets for store targets for dummy effect in triggered spells - if (!m_spellInfo->Effects[i].IsEffect()) + if (!effect->IsEffect()) continue; // set expected type of implicit targets to be sent to client - uint32 implicitTargetMask = GetTargetFlagMask(m_spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(m_spellInfo->Effects[i].TargetB.GetObjectType()); + uint32 implicitTargetMask = GetTargetFlagMask(effect->TargetA.GetObjectType()) | GetTargetFlagMask(effect->TargetB.GetObjectType()); if (implicitTargetMask & TARGET_FLAG_UNIT) m_targets.SetTargetFlag(TARGET_FLAG_UNIT); if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM)) m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT); - SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetA, processedAreaEffectsMask); - SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetB, processedAreaEffectsMask); + SelectEffectImplicitTargets(SpellEffIndex(effect->EffectIndex), effect->TargetA, processedAreaEffectsMask); + SelectEffectImplicitTargets(SpellEffIndex(effect->EffectIndex), effect->TargetB, processedAreaEffectsMask); // Select targets of effect based on effect type // those are used when no valid target could be added for spell effect based on spell target type // some spell effects use explicit target as a default target added to target map (like SPELL_EFFECT_LEARN_SPELL) // some spell effects add target to target map only when target type specified (like SPELL_EFFECT_WEAPON) // some spell effects don't add anything to target map (confirmed with sniffs) (like SPELL_EFFECT_DESTROY_ALL_TOTEMS) - SelectEffectTypeImplicitTargets(i); + SelectEffectTypeImplicitTargets(effect->EffectIndex); if (m_targets.HasDst()) - AddDestTarget(*m_targets.GetDst(), i); + AddDestTarget(*m_targets.GetDst(), effect->EffectIndex); if (m_spellInfo->IsChanneled()) { - uint8 mask = (1 << i); + uint32 mask = (1 << effect->EffectIndex); for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { if (ihit->effectMask & mask) @@ -864,17 +925,19 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar if (effectMask & processedEffectMask) return; // choose which targets we can select at once - for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { - SpellEffectInfo const* effects = GetSpellInfo()->Effects; - if (effects[j].IsEffect() && - effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() && - effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() && - effects[effIndex].ImplicitTargetConditions == effects[j].ImplicitTargetConditions && - effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) && - CheckScriptEffectImplicitTargets(effIndex, j)) + //for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) + if (!effect || effect->EffectIndex <= uint32(effIndex)) + continue; + if (effect->IsEffect() && + effect->TargetA.GetTarget() == effect->TargetA.GetTarget() && + effect->TargetB.GetTarget() == effect->TargetB.GetTarget() && + effect->ImplicitTargetConditions == effect->ImplicitTargetConditions && + effect->CalcRadius(m_caster) == effect->CalcRadius(m_caster) && + CheckScriptEffectImplicitTargets(effIndex, effect->EffectIndex)) { - effectMask |= 1 << j; + effectMask |= 1 << effect->EffectIndex; } } processedEffectMask |= effectMask; @@ -1009,6 +1072,10 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar return; } + SpellEffectInfo const* effect = GetEffect(effIndex); + if (!effect) + return; + float range = 0.0f; switch (targetType.GetCheckType()) { @@ -1030,7 +1097,7 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar break; } - ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions; + ConditionList* condList = effect->ImplicitTargetConditions; // handle emergency case - try to use other provided targets if no conditions provided if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty())) @@ -1116,9 +1183,12 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge std::list<WorldObject*> targets; SpellTargetObjectTypes objectType = targetType.GetObjectType(); SpellTargetCheckTypes selectionType = targetType.GetCheckType(); - ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions; + SpellEffectInfo const* effect = GetEffect(effIndex); + if (!effect) + return; + ConditionList* condList = effect->ImplicitTargetConditions; float coneAngle = float(M_PI) / 2; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod; + float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList)) { @@ -1199,8 +1269,11 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge } std::list<WorldObject*> targets; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod; - SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions); + SpellEffectInfo const* effect = GetEffect(effIndex); + if (!effect) + return; + float radius = effect->CalcRadius(m_caster) * m_spellValue->RadiusMod; + SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), effect->ImplicitTargetConditions); CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); @@ -1236,7 +1309,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex)) { /// @todo fix this check - if (m_spellInfo->HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || m_spellInfo->HasEffect(SPELL_EFFECT_BIND)) + if (HasEffect(SPELL_EFFECT_TELEPORT_UNITS) || HasEffect(SPELL_EFFECT_BIND)) dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId); else if (st->target_mapId == m_caster->GetMapId()) dest = SpellDestination(st->target_X, st->target_Y, st->target_Z, st->target_Orientation); @@ -1284,23 +1357,26 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici } default: { - float dist; - float angle = targetType.CalcDirectionAngle(); - float objSize = m_caster->GetObjectSize(); - if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON) - dist = PET_FOLLOW_DIST; - else - dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + if (SpellEffectInfo const* effect = GetEffect(effIndex)) + { + float dist; + float angle = targetType.CalcDirectionAngle(); + float objSize = m_caster->GetObjectSize(); + if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON) + dist = PET_FOLLOW_DIST; + else + dist = effect->CalcRadius(m_caster); - if (dist < objSize) - dist = objSize; - else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM) - dist = objSize + (dist - objSize) * float(rand_norm()); + if (dist < objSize) + dist = objSize; + else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM) + dist = objSize + (dist - objSize) * float(rand_norm()); - Position pos = dest._position; - m_caster->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + m_caster->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); + dest.Relocate(pos); + } break; } } @@ -1323,18 +1399,21 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplici break; default: { - float angle = targetType.CalcDirectionAngle(); - float objSize = target->GetObjectSize(); - float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); - if (dist < objSize) - dist = objSize; - else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) - dist = objSize + (dist - objSize) * float(rand_norm()); - - Position pos = dest._position; - target->MovePositionToFirstCollision(pos, dist, angle); - - dest.Relocate(pos); + if (SpellEffectInfo const* effect = GetEffect(effIndex)) + { + float angle = targetType.CalcDirectionAngle(); + float objSize = target->GetObjectSize(); + float dist = effect->CalcRadius(m_caster); + if (dist < objSize) + dist = objSize; + else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM) + dist = objSize + (dist - objSize) * float(rand_norm()); + + Position pos = dest._position; + target->MovePositionToFirstCollision(pos, dist, angle); + + dest.Relocate(pos); + } break; } } @@ -1365,15 +1444,18 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT return; default: { - float angle = targetType.CalcDirectionAngle(); - float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); - if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) - dist *= float(rand_norm()); + if (SpellEffectInfo const* effect = GetEffect(effIndex)) + { + float angle = targetType.CalcDirectionAngle(); + float dist = effect->CalcRadius(m_caster); + if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM) + dist *= float(rand_norm()); - Position pos = dest._position; - m_caster->MovePositionToFirstCollision(pos, dist, angle); + Position pos = dest._position; + m_caster->MovePositionToFirstCollision(pos, dist, angle); - dest.Relocate(pos); + dest.Relocate(pos); + } break; } } @@ -1451,21 +1533,25 @@ void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImpli void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) { - uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTargets; + SpellEffectInfo const* effect = GetEffect(effIndex); + if (!effect) + return; + + uint32 maxTargets = effect->ChainTargets; if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); if (maxTargets > 1) { // mark damage multipliers as used - for (uint32 k = effIndex; k < MAX_SPELL_EFFECTS; ++k) - if (effMask & (1 << k)) - m_damageMultipliers[k] = 1.0f; + for (SpellEffectInfo const* eff : GetEffects()) + if (eff && (effMask & (1 << eff->EffectIndex))) + m_damageMultipliers[eff->EffectIndex] = 1.0f; m_applyMultiplierMask |= effMask; std::list<WorldObject*> targets; SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType() - , m_spellInfo->Effects[effIndex].ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); + , effect->ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); // Chain primary target is added earlier CallScriptObjectAreaTargetSelectHandlers(targets, effIndex, targetType); @@ -1644,11 +1730,14 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex) veh->SetLastShootPos(*m_targets.GetDstPos()); } -void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) +void Spell::SelectEffectTypeImplicitTargets(uint32 effIndex) { // special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER /// @todo this is a workaround - target shouldn't be stored in target map for those spells - switch (m_spellInfo->Effects[effIndex].Effect) + SpellEffectInfo const* effect = GetEffect(effIndex); + if (!effect) + return; + switch (effect->Effect) { case SPELL_EFFECT_SUMMON_RAF_FRIEND: case SPELL_EFFECT_SUMMON_PLAYER: @@ -1667,17 +1756,17 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) } // select spell implicit targets based on effect type - if (!m_spellInfo->Effects[effIndex].GetImplicitTargetType()) + if (!effect->GetImplicitTargetType()) return; - uint32 targetMask = m_spellInfo->Effects[effIndex].GetMissingTargetMask(); + uint32 targetMask = effect->GetMissingTargetMask(); if (!targetMask) return; WorldObject* target = NULL; - switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType()) + switch (effect->GetImplicitTargetType()) { // add explicit object target or self to the target map case EFFECT_IMPLICIT_TARGET_EXPLICIT: @@ -2012,9 +2101,9 @@ void Spell::CleanupTargetList() void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/, Position const* losPosition /*= nullptr*/) { - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (!m_spellInfo->Effects[effIndex].IsEffect() || !CheckEffectTarget(target, effIndex, losPosition)) - effectMask &= ~(1 << effIndex); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (!effect->IsEffect() || !CheckEffectTarget(target, effect->EffectIndex, losPosition))) + effectMask &= ~(1 << effect->EffectIndex); // no effects left if (!effectMask) @@ -2025,9 +2114,9 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= return; // Check for effect immune skip if immuned - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (target->IsImmunedToSpellEffect(m_spellInfo, effIndex)) - effectMask &= ~(1 << effIndex); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && target->IsImmunedToSpellEffect(m_spellInfo, effect->EffectIndex)) + effectMask &= ~(1 << effect->EffectIndex); ObjectGuid targetGUID = target->GetGUID(); @@ -2120,19 +2209,22 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= void Spell::AddGOTarget(GameObject* go, uint32 effectMask) { - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetEffects()) { - if (!m_spellInfo->Effects[effIndex].IsEffect()) - effectMask &= ~(1 << effIndex); + if (!effect) + continue; + + if (!effect->IsEffect()) + effectMask &= ~(1 << effect->EffectIndex); else { - switch (m_spellInfo->Effects[effIndex].Effect) + switch (effect->Effect) { case SPELL_EFFECT_GAMEOBJECT_DAMAGE: case SPELL_EFFECT_GAMEOBJECT_REPAIR: case SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE: if (go->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) - effectMask &= ~(1 << effIndex); + effectMask &= ~(1 << effect->EffectIndex); break; default: break; @@ -2187,9 +2279,9 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) void Spell::AddItemTarget(Item* item, uint32 effectMask) { - for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) - if (!m_spellInfo->Effects[effIndex].IsEffect()) - effectMask &= ~(1 << effIndex); + for (SpellEffectInfo const* effect : GetEffects()) + if (!effect || !effect->IsEffect()) + effectMask &= ~(1 << effect->EffectIndex); // no effects left if (!effectMask) @@ -2234,10 +2326,10 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) { uint8 farMask = 0; // create far target mask - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_spellInfo->Effects[i].IsFarUnitTargetEffect()) - if ((1 << i) & mask) - farMask |= (1 << i); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && effect->IsFarUnitTargetEffect()) + if ((1 << effect->EffectIndex) & mask) + farMask |= (1 << effect->EffectIndex); if (!farMask) return; @@ -2248,9 +2340,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // do far effects on the unit // can't use default call because of threading, do stuff as fast as possible - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (farMask & (1 << i)) - HandleEffects(unit, NULL, NULL, i, SPELL_EFFECT_HANDLE_HIT_TARGET); + for(SpellEffectInfo const* effect : GetEffects()) + if (effect && (farMask & (1 << effect->EffectIndex))) + HandleEffects(unit, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); return; } @@ -2433,7 +2525,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } } - if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL))) + if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || HasEffect(SPELL_EFFECT_DISPEL))) { m_caster->CombatStart(unit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO)); @@ -2474,10 +2566,10 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA // disable effects to which unit is immune SpellMissInfo returnVal = SPELL_MISS_IMMUNE; - for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) - if (effectMask & (1 << effectNumber)) - if (unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) - effectMask &= ~(1 << effectNumber); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (effectMask & (1 << effect->EffectIndex))) + if (unit->IsImmunedToSpellEffect(m_spellInfo, effect->EffectIndex)) + effectMask &= ~(1 << effect->EffectIndex); if (!effectMask) return returnVal; @@ -2535,9 +2627,9 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA } uint8 aura_effmask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (effectMask & (1 << i) && m_spellInfo->Effects[i].IsUnitOwnedAuraEffect()) - aura_effmask |= 1 << i; + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (effectMask & (1 << effect->EffectIndex) && effect->IsUnitOwnedAuraEffect())) + aura_effmask |= 1 << effect->EffectIndex; // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo, m_triggeredByAuraSpell != nullptr); @@ -2557,18 +2649,21 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA // Select rank for aura with level requirements only in specific cases // Unit has to be target only of aura effect, both caster and target have to be players, target has to be other than unit target SpellInfo const* aurSpellInfo = m_spellInfo; - int32 basePoints[3]; + int32 basePoints[MAX_SPELL_EFFECTS]; if (scaleAura) { aurSpellInfo = m_spellInfo->GetAuraRankForLevel(unitTarget->getLevel()); ASSERT(aurSpellInfo); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : aurSpellInfo->GetEffectsForDifficulty(0)) { - basePoints[i] = aurSpellInfo->Effects[i].BasePoints; - if (m_spellInfo->Effects[i].Effect != aurSpellInfo->Effects[i].Effect) + basePoints[effect->EffectIndex] = effect->BasePoints; + if (SpellEffectInfo const* myEffect = GetEffect(effect->EffectIndex)) { - aurSpellInfo = m_spellInfo; - break; + if (myEffect->Effect != effect->Effect) + { + aurSpellInfo = m_spellInfo; + break; + } } } } @@ -2577,7 +2672,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA { bool refresh = false; m_spellAura = Aura::TryRefreshStackOrCreate(aurSpellInfo, effectMask, unit, - m_originalCaster, (aurSpellInfo == m_spellInfo) ? &m_spellValue->EffectBasePoints[0] : &basePoints[0], m_CastItem, ObjectGuid::Empty, &refresh); + m_originalCaster, (aurSpellInfo == m_spellInfo) ? m_spellValue->EffectBasePoints : basePoints, m_CastItem, ObjectGuid::Empty, &refresh); if (m_spellAura) { // Set aura stack amount to desired value @@ -2599,8 +2694,8 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA { m_spellAura->Remove(); bool found = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (effectMask & (1 << i) && m_spellInfo->Effects[i].Effect != SPELL_EFFECT_APPLY_AURA) + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (effectMask & (1 << effect->EffectIndex) && effect->Effect != SPELL_EFFECT_APPLY_AURA)) found = true; if (!found) return SPELL_MISS_IMMUNE; @@ -2624,10 +2719,11 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA { int32 origDuration = duration; duration = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (AuraEffect const* eff = m_spellAura->GetEffect(i)) - if (int32 period = eff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED - duration = std::max(std::max(origDuration / period, 1) * period, duration); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect) + if (AuraEffect const* eff = m_spellAura->GetEffect(effect->EffectIndex)) + if (int32 period = eff->GetPeriod()) // period is hastened by UNIT_MOD_CAST_SPEED + duration = std::max(std::max(origDuration / period, 1) * period, duration); // if there is no periodic effect if (!duration) @@ -2646,9 +2742,9 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA } } - for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) - if (effectMask & (1 << effectNumber)) - HandleEffects(unit, NULL, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (effectMask & (1 << effect->EffectIndex))) + HandleEffects(unit, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); return SPELL_MISS_NONE; } @@ -2742,9 +2838,9 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo* target) PrepareScriptHitHandlers(); CallScriptBeforeHitHandlers(); - for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) - if (effectMask & (1 << effectNumber)) - HandleEffects(NULL, NULL, go, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (effectMask & (1 << effect->EffectIndex))) + HandleEffects(NULL, NULL, go, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); CallScriptOnHitHandlers(); CallScriptAfterHitHandlers(); @@ -2759,9 +2855,9 @@ void Spell::DoAllEffectOnTarget(ItemTargetInfo* target) PrepareScriptHitHandlers(); CallScriptBeforeHitHandlers(); - for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) - if (effectMask & (1 << effectNumber)) - HandleEffects(NULL, target->item, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (effectMask & (1 << effect->EffectIndex))) + HandleEffects(NULL, target->item, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT_TARGET); CallScriptOnHitHandlers(); @@ -2776,9 +2872,9 @@ bool Spell::UpdateChanneledTargetList() uint8 channelTargetEffectMask = m_channelTargetEffectMask; uint8 channelAuraMask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) - channelAuraMask |= 1<<i; + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) + channelAuraMask |= 1 << effect->EffectIndex; channelAuraMask &= channelTargetEffectMask; @@ -2843,15 +2939,15 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered // Fill aura scaling information if (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) + if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) { // Change aura with ranks only if basepoints are taken from spellInfo and aura is positive - if (m_spellInfo->IsPositiveEffect(i)) + if (m_spellInfo->IsPositiveEffect(effect->EffectIndex)) { - m_auraScaleMask |= (1 << i); - if (m_spellValue->EffectBasePoints[i] != m_spellInfo->Effects[i].BasePoints) + m_auraScaleMask |= (1 << effect->EffectIndex); + if (m_spellValue->EffectBasePoints[effect->EffectIndex] != effect->BasePoints) { m_auraScaleMask = 0; break; @@ -2966,8 +3062,8 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered if (!(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS) && m_spellInfo->IsBreakingStealth()) { m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST); - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_spellInfo->Effects[i].GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT) + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && effect->GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT) { m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK); break; @@ -3296,10 +3392,6 @@ void Spell::handle_immediate() // Remove used for cast item if need (it can be already NULL after TakeReagents call TakeCastItem(); - // handle ammo consumption for thrown weapons - if (m_spellInfo->IsRangedWeaponSpell() && m_spellInfo->IsChanneled()) - TakeAmmo(); - if (m_spellState != SPELL_STATE_CASTING) finish(true); // successfully finish spell cast (not last in case autorepeat or channel spell) } @@ -3391,14 +3483,14 @@ void Spell::_handle_immediate_phase() PrepareScriptHitHandlers(); // handle effects with SPELL_EFFECT_HANDLE_HIT mode - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { // don't do anything for empty effect - if (!m_spellInfo->Effects[j].IsEffect()) + if (!effect || !effect->IsEffect()) continue; // call effect handlers to handle destination hit - HandleEffects(NULL, NULL, NULL, j, SPELL_EFFECT_HANDLE_HIT); + HandleEffects(NULL, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_HIT); } // process items @@ -3436,7 +3528,7 @@ void Spell::_handle_finish_phase() HandleHolyPower(m_caster->m_movedPlayer); } - if (m_caster->m_extraAttacks && m_spellInfo->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) + if (m_caster->m_extraAttacks && HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) { if (Unit* victim = ObjectAccessor::FindUnit(m_targets.GetOrigUnitTargetGUID())) m_caster->HandleProcExtraAttackFor(victim); @@ -3494,9 +3586,10 @@ void Spell::update(uint32 difftime) // check if the player caster has moved before the spell finished // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect + SpellEffectInfo const* effect = GetEffect(EFFECT_0); if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) && m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) && - (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && + ((effect && effect->Effect != SPELL_EFFECT_STUCK) || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) { // don't cancel for melee, autorepeat, triggered and instant spells @@ -3671,17 +3764,18 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas if (result == SPELL_CAST_OK) return; - WorldPacket data(opcode, (4+1+1)); - data << uint8(cast_count); - data << uint32(spellInfo->Id); - data << uint8(result); // problem + WorldPackets::Spells::CastFailed packet(opcode); + packet.CastID = cast_count; + packet.SpellID = spellInfo->Id; + packet.Reason = result; + switch (result) { case SPELL_FAILED_NOT_READY: - data << uint32(0); // unknown (value 1 update cooldowns on client flag) + packet.FailedArg1 = 0; // unknown (value 1 update cooldowns on client flag) break; case SPELL_FAILED_REQUIRES_SPELL_FOCUS: - data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id + packet.FailedArg1 = spellInfo->RequiresSpellFocus; // SpellFocusObject.dbc id break; case SPELL_FAILED_REQUIRES_AREA: // AreaTable.dbc id // hardcode areas limitation case @@ -3689,71 +3783,71 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas { case 41617: // Cenarion Mana Salve case 41619: // Cenarion Healing Salve - data << uint32(3905); + packet.FailedArg1 = 3905; break; case 41618: // Bottled Nethergon Energy case 41620: // Bottled Nethergon Vapor - data << uint32(3842); + packet.FailedArg1 = 3842; break; case 45373: // Bloodberry Elixir - data << uint32(4075); + packet.FailedArg1 = 4075; break; default: // default case (don't must be) - data << uint32(0); + packet.FailedArg1 = 0; break; } break; case SPELL_FAILED_TOTEMS: if (spellInfo->Totem[0]) - data << uint32(spellInfo->Totem[0]); + packet.FailedArg1 = spellInfo->Totem[0]; if (spellInfo->Totem[1]) - data << uint32(spellInfo->Totem[1]); + packet.FailedArg2 = spellInfo->Totem[1]; break; case SPELL_FAILED_TOTEM_CATEGORY: if (spellInfo->TotemCategory[0]) - data << uint32(spellInfo->TotemCategory[0]); + packet.FailedArg1 = spellInfo->TotemCategory[0]; if (spellInfo->TotemCategory[1]) - data << uint32(spellInfo->TotemCategory[1]); + packet.FailedArg2 = spellInfo->TotemCategory[1]; break; case SPELL_FAILED_EQUIPPED_ITEM_CLASS: case SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND: case SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND: - data << uint32(spellInfo->EquippedItemClass); - data << uint32(spellInfo->EquippedItemSubClassMask); + packet.FailedArg1 = spellInfo->EquippedItemClass; + packet.FailedArg2 = spellInfo->EquippedItemSubClassMask; break; case SPELL_FAILED_TOO_MANY_OF_ITEM: { - uint32 item = 0; - for (int8 eff = 0; eff < MAX_SPELL_EFFECTS; eff++) - if (spellInfo->Effects[eff].ItemType) - item = spellInfo->Effects[eff].ItemType; - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); - if (proto && proto->ItemLimitCategory) - data << uint32(proto->ItemLimitCategory); - break; + uint32 item = 0; + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) + if (effect->ItemType) + item = effect->ItemType; + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); + if (proto && proto->ItemLimitCategory) + packet.FailedArg1 = proto->ItemLimitCategory; + break; } case SPELL_FAILED_PREVENTED_BY_MECHANIC: - data << uint32(spellInfo->GetAllEffectsMechanicMask()); // SpellMechanic.dbc id + packet.FailedArg1 = spellInfo->GetAllEffectsMechanicMask(); // SpellMechanic.dbc id break; case SPELL_FAILED_NEED_EXOTIC_AMMO: - data << uint32(spellInfo->EquippedItemSubClassMask); // seems correct... + packet.FailedArg1 = spellInfo->EquippedItemSubClassMask; // seems correct... break; case SPELL_FAILED_NEED_MORE_ITEMS: - data << uint32(0); // Item id - data << uint32(0); // Item count? + packet.FailedArg1 = 0; // Item id + packet.FailedArg2 = 0; // Item count? break; case SPELL_FAILED_MIN_SKILL: - data << uint32(0); // SkillLine.dbc id - data << uint32(0); // required skill value + packet.FailedArg1 = 0; // SkillLine.dbc id + packet.FailedArg2 = 0; // required skill value break; case SPELL_FAILED_FISHING_TOO_LOW: - data << uint32(0); // required fishing skill + packet.FailedArg1 = 0; // required fishing skill break; case SPELL_FAILED_CUSTOM_ERROR: - data << uint32(customError); + packet.FailedArg1 = customError; break; case SPELL_FAILED_SILENCED: - data << uint32(0); // Unknown + packet.FailedArg1 = 0; // Unknown break; case SPELL_FAILED_REAGENTS: { @@ -3773,14 +3867,15 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas } } - data << uint32(missingItem); // first missing item + packet.FailedArg1 = missingItem; // first missing item break; } // TODO: SPELL_FAILED_NOT_STANDING default: break; } - caster->GetSession()->SendPacket(&data); + + caster->GetSession()->SendPacket(packet.Write()); } void Spell::SendSpellStart() @@ -3788,7 +3883,7 @@ void Spell::SendSpellStart() if (!IsNeedSendToClient()) return; - //TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id); + TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_START id=%u", m_spellInfo->Id); uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY; @@ -3803,7 +3898,81 @@ void Spell::SendSpellStart() if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNES) castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it - WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); + WorldPackets::Spells::SpellStart packet; + WorldPackets::Spells::SpellCastData& castData = packet.Cast; + + if (m_CastItem) + castData.CasterGUID = m_CastItem->GetGUID(); + else + castData.CasterGUID = m_caster->GetGUID(); + + castData.CasterUnit = m_caster->GetGUID(); + castData.CastID = m_cast_count; // pending spell cast? + castData.SpellID = m_spellInfo->Id; + castData.CastFlags = castFlags; + castData.CastTime = m_casttime; + + m_targets.Write(castData.Target); + + if (castFlags & CAST_FLAG_POWER_LEFT_SELF) + { + /// @todo Implement multiple power types + WorldPackets::Spells::SpellPowerData powerData; + powerData.Type = m_spellInfo->PowerType; + powerData.Cost = m_caster->GetPower((Powers)m_spellInfo->PowerType); + castData.RemainingPower.push_back(powerData); + } + + if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list + { + WorldPackets::Spells::RuneData& runeData = castData.RemainingRunes.Value; + //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature + //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster + if (Player* player = m_caster->ToPlayer()) + { + runeData.Start = m_runesState; // runes state before + runeData.Count = player->GetRunesState(); // runes state after + for (uint8 i = 0; i < MAX_RUNES; ++i) + { + // float casts ensure the division is performed on floats as we need float result + float baseCd = float(player->GetRuneBaseCooldown(i)); + runeData.Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed + } + } + else + { + runeData.Start = 0; + runeData.Count = 0; + for (uint8 i = 0; i < MAX_RUNES; ++i) + runeData.Cooldowns.push_back(0); + } + + castData.RemainingRunes.HasValue = true; + } + + /** @todo implement spell ammo packet data + if (castFlags & CAST_FLAG_PROJECTILE) + { + castData.Ammo.DisplayID = 0; + castData.Ammo.InventoryType = 0; + }**/ + + /** @todo implement spell immunity packet data + if (castFlags & CAST_FLAG_IMMUNITY) + { + castData.Immunities.School = 0; + castData.Immunities.Value = 0; + }**/ + + /** @todo implement heal prediction packet data + if (castFlags & CAST_FLAG_HEAL_PREDICTION) + { + castData.Predict.BeconGUID = ?? + castData.Predict.Points = 0; + castData.Predict.Type = 0; + }**/ + + /*WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); if (m_CastItem) data << m_CastItem->GetPackGUID(); else @@ -3863,9 +4032,9 @@ void Spell::SendSpellStart() data << uint8(0); // unkByte // if (unkByte == 2) // data.append(0); - } + }*/ - m_caster->SendMessageToSet(&data, true); + m_caster->SendMessageToSet(packet.Write(), true); } void Spell::SendSpellGo() @@ -3874,7 +4043,7 @@ void Spell::SendSpellGo() if (!IsNeedSendToClient()) return; - //TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id); + TC_LOG_DEBUG("spells", "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id); uint32 castFlags = CAST_FLAG_UNKNOWN_9; @@ -3897,7 +4066,7 @@ void Spell::SendSpellGo() castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list } - if (m_spellInfo->HasEffect(SPELL_EFFECT_ACTIVATE_RUNE)) + if (HasEffect(SPELL_EFFECT_ACTIVATE_RUNE)) castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list if (m_targets.HasTraj()) @@ -3906,7 +4075,68 @@ void Spell::SendSpellGo() if (!m_spellInfo->StartRecoveryTime) castFlags |= CAST_FLAG_NO_GCD; - WorldPacket data(SMSG_SPELL_GO, 50); // guess size + WorldPackets::Spells::SpellGo packet; + WorldPackets::Spells::SpellCastData& castData = packet.Cast; + + if (m_CastItem) + castData.CasterGUID = m_CastItem->GetGUID(); + else + castData.CasterGUID = m_caster->GetGUID(); + + castData.CasterUnit = m_caster->GetGUID(); + castData.CastID = m_cast_count; // pending spell cast? + castData.SpellID = m_spellInfo->Id; + castData.CastFlags = castFlags; + castData.CastTime = getMSTime(); + + /// @todo implement multiple targets + if (m_targets.GetUnitTarget()) + castData.HitTargets.push_back(m_targets.GetUnitTargetGUID()); + + m_targets.Write(castData.Target); + + if (castFlags & CAST_FLAG_POWER_LEFT_SELF) + { + /// @todo Implement multiple power types + WorldPackets::Spells::SpellPowerData powerData; + powerData.Type = m_spellInfo->PowerType; + powerData.Cost = m_caster->GetPower((Powers)m_spellInfo->PowerType); + castData.RemainingPower.push_back(powerData); + } + + if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list + { + WorldPackets::Spells::RuneData& runeData = castData.RemainingRunes.Value; + //TODO: There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature + //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster + if (Player* player = m_caster->ToPlayer()) + { + runeData.Start = m_runesState; // runes state before + runeData.Count = player->GetRunesState(); // runes state after + for (uint8 i = 0; i < MAX_RUNES; ++i) + { + // float casts ensure the division is performed on floats as we need float result + float baseCd = float(player->GetRuneBaseCooldown(i)); + runeData.Cooldowns.push_back((baseCd - float(player->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed + } + } + else + { + runeData.Start = 0; + runeData.Count = 0; + for (uint8 i = 0; i < MAX_RUNES; ++i) + runeData.Cooldowns.push_back(0); + } + + castData.RemainingRunes.HasValue = true; + } + + if (castFlags & CAST_FLAG_ADJUST_MISSILE) + { + castData.MissileTrajectory.TravelTime = m_delayMoment; + castData.MissileTrajectory.Pitch = m_targets.GetElevation(); + } + /*WorldPacket data(SMSG_SPELL_GO, 50); // guess size if (m_CastItem) data << m_CastItem->GetPackGUID(); @@ -3922,7 +4152,7 @@ void Spell::SendSpellGo() WriteSpellGoTargets(&data); - m_targets.Write(data); + //m_targets.Write(data); if (castFlags & CAST_FLAG_POWER_LEFT_SELF) data << uint32(m_caster->GetPower((Powers)m_spellInfo->PowerType)); @@ -3970,7 +4200,7 @@ void Spell::SendSpellGo() if (m_targets.GetTargetMask() & TARGET_FLAG_EXTRA_TARGETS) { data << uint32(0); // Extra targets count - /* + for (uint8 i = 0; i < count; ++i) { data << float(0); // Target Position X @@ -3978,10 +4208,10 @@ void Spell::SendSpellGo() data << float(0); // Target Position Z data << uint64(0); // Target Guid } - */ - } + + }*/ - m_caster->SendMessageToSet(&data, true); + m_caster->SendMessageToSet(packet.Write(), true); } /// Writes miss and hit targets for a SMSG_SPELL_GO packet @@ -4052,9 +4282,9 @@ void Spell::SendLogExecute() data << uint32(m_spellInfo->Id); uint8 effCount = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - if (m_effectExecuteData[i]) + if (effect && m_effectExecuteData[effect->EffectIndex]) ++effCount; } @@ -4062,17 +4292,17 @@ void Spell::SendLogExecute() return; data << uint32(effCount); - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - if (!m_effectExecuteData[i]) + if (!effect || !m_effectExecuteData[effect->EffectIndex]) continue; - data << uint32(m_spellInfo->Effects[i].Effect); // spell effect + data << uint32(effect->Effect); // spell effect - data.append(*m_effectExecuteData[i]); + data.append(*m_effectExecuteData[effect->EffectIndex]); - delete m_effectExecuteData[i]; - m_effectExecuteData[i] = NULL; + delete m_effectExecuteData[effect->EffectIndex]; + m_effectExecuteData[effect->EffectIndex] = NULL; } m_caster->SendMessageToSet(&data, true); } @@ -4184,19 +4414,19 @@ void Spell::ExecuteLogEffectResurrect(uint8 effIndex, Unit* target) void Spell::SendInterrupted(uint8 result) { - WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1)); - data << m_caster->GetPackGUID(); - data << uint8(m_cast_count); - data << uint32(m_spellInfo->Id); - data << uint8(result); - m_caster->SendMessageToSet(&data, true); + WorldPackets::Spells::SpellFailure failurePacket; + failurePacket.CasterUnit = m_caster->GetGUID(); + failurePacket.CastID = m_cast_count; + failurePacket.SpellID = m_spellInfo->Id; + failurePacket.Reason = result; + m_caster->SendMessageToSet(failurePacket.Write(), true); - data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4)); - data << m_caster->GetPackGUID(); - data << uint8(m_cast_count); - data << uint32(m_spellInfo->Id); - data << uint8(result); - m_caster->SendMessageToSet(&data, true); + WorldPackets::Spells::SpellFailedOther failedPacket; + failedPacket.CasterUnit = m_caster->GetGUID(); + failedPacket.CastID = m_cast_count; + failedPacket.SpellID = m_spellInfo->Id; + failedPacket.Reason = result; + m_caster->SendMessageToSet(failedPacket.Write(), true); } void Spell::SendChannelUpdate(uint32 time) @@ -4301,7 +4531,7 @@ void Spell::TakeCastItem() bool expendable = false; bool withoutCharges = false; - for (uint32 i = 0; i < proto->Effects.size(); ++i) + for (int i = 0; i < proto->Effects.size(); ++i) { // item has limited charges if (proto->Effects[i].Charges) @@ -4407,36 +4637,6 @@ void Spell::TakePower() m_caster->ModifyPower(powerType, -irand(0, m_powerCost/4)); } -void Spell::TakeAmmo() -{ - if (m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) - { - Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(RANGED_ATTACK); - - // wands don't have ammo - if (!pItem || pItem->IsBroken() || pItem->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_WAND) - return; - - if ((pItem->GetTemplate()->InventoryType == INVTYPE_THROWN || - pItem->GetTemplate()->InventoryType == INVTYPE_RANGED || - pItem->GetTemplate()->InventoryType == INVTYPE_RANGEDRIGHT) - && roll_chance_f(sWorld->getRate(RATE_DURABILITY_LOSS_DAMAGE))) - { - if (pItem->GetMaxStackCount() == 1) - { - // decrease durability for non-stackable throw weapon - m_caster->ToPlayer()->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); - } - else - { - // decrease items amount for stackable throw weapon - uint32 count = 1; - m_caster->ToPlayer()->DestroyItemCount(pItem, count, true); - } - } - } -} - SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) { if (m_spellInfo->PowerType != POWER_RUNES || !runeCostID) @@ -4573,7 +4773,7 @@ void Spell::TakeReagents() // if CastItem is also spell reagent if (castItemTemplate && castItemTemplate->ItemId == itemid) { - for (uint32 s = 0; s < castItemTemplate->Effects.size(); ++s) + for (int s = 0; s < castItemTemplate->Effects.size(); ++s) { // CastItem will be used up and does not count as reagent int32 charges = m_CastItem->GetSpellCharges(s); @@ -4693,9 +4893,15 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT gameObjTarget = pGOTarget; destTarget = &m_destTargets[i]._position; - uint8 eff = m_spellInfo->Effects[i].Effect; + SpellEffectInfo const* effect = GetEffect(i); + if (!effect) + { + TC_LOG_ERROR("spells", "Spell: %u HandleEffects at EffectIndex: %u missing effect", m_spellInfo->Id, i); + return; + } + uint8 eff = effect->Effect; - TC_LOG_DEBUG("spells", "Spell: %u Effect : %u", m_spellInfo->Id, eff); + TC_LOG_DEBUG("spells", "Spell: %u Effect: %u", m_spellInfo->Id, eff); damage = CalculateDamage(i, unitTarget); @@ -4816,9 +5022,9 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_CASTER_AURASTATE; // Note: spell 62473 requres casterAuraSpell = triggering spell - if (m_spellInfo->CasterAuraSpell && !m_caster->HasAura(sSpellMgr->GetSpellIdForDifficulty(m_spellInfo->CasterAuraSpell, m_caster))) + if (m_spellInfo->CasterAuraSpell && !m_caster->HasAura(m_spellInfo->CasterAuraSpell)) return SPELL_FAILED_CASTER_AURASTATE; - if (m_spellInfo->ExcludeCasterAuraSpell && m_caster->HasAura(sSpellMgr->GetSpellIdForDifficulty(m_spellInfo->ExcludeCasterAuraSpell, m_caster))) + if (m_spellInfo->ExcludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->ExcludeCasterAuraSpell)) return SPELL_FAILED_CASTER_AURASTATE; if (reqCombat && m_caster->IsInCombat() && !m_spellInfo->CanBeUsedInCombat()) @@ -4831,7 +5037,8 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving() && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) { // skip stuck spell to allow use it in falling case and apply spell limitations at movement - if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) && + SpellEffectInfo const* effect = GetEffect(EFFECT_0); + if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || (effect && effect->Effect != SPELL_EFFECT_STUCK)) && (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0)) return SPELL_FAILED_MOVING; } @@ -4916,9 +5123,9 @@ SpellCastResult Spell::CheckCast(bool strict) } // check pet presence - for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { - if (m_spellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_PET) + if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_PET) { if (!m_caster->GetGuardianPet()) { @@ -5009,10 +5216,12 @@ SpellCastResult Spell::CheckCast(bool strict) if (castResult != SPELL_CAST_OK) return castResult; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { + if (!effect) + continue; // for effects of spells that have only one target - switch (m_spellInfo->Effects[i].Effect) + switch (effect->Effect) { case SPELL_EFFECT_DUMMY: { @@ -5039,7 +5248,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; - if (m_spellInfo->Effects[i].TargetA.GetTarget() != TARGET_UNIT_PET) + if (effect->TargetA.GetTarget() != TARGET_UNIT_PET) break; Pet* pet = m_caster->ToPlayer()->GetPet(); @@ -5047,7 +5256,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (!pet) return SPELL_FAILED_NO_PET; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[i].TriggerSpell); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5078,7 +5287,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (!pet || pet->GetOwner() != m_caster) return SPELL_FAILED_BAD_TARGETS; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[i].TriggerSpell); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(effect->TriggerSpell); if (!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; @@ -5090,7 +5299,7 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_EFFECT_APPLY_GLYPH: { - uint32 glyphId = m_spellInfo->Effects[i].MiscValue; + uint32 glyphId = effect->MiscValue; if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyphId)) if (m_caster->HasAura(gp->SpellID)) return SPELL_FAILED_UNIQUE_GLYPH; @@ -5127,7 +5336,7 @@ SpellCastResult Spell::CheckCast(bool strict) // Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects) if (m_caster->GetTypeId() == TYPEID_PLAYER) if (Unit* target = m_targets.GetUnitTarget()) - if (target != m_caster && target->getPowerType() != Powers(m_spellInfo->Effects[i].MiscValue)) + if (target != m_caster && target->getPowerType() != Powers(effect->MiscValue)) return SPELL_FAILED_BAD_TARGETS; break; } @@ -5200,13 +5409,13 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_EFFECT_OPEN_LOCK: { - if (m_spellInfo->Effects[i].TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET && - m_spellInfo->Effects[i].TargetA.GetTarget() != TARGET_GAMEOBJECT_ITEM_TARGET) + if (effect->TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET && + effect->TargetA.GetTarget() != TARGET_GAMEOBJECT_ITEM_TARGET) break; if (m_caster->GetTypeId() != TYPEID_PLAYER // only players can open locks, gather etc. // we need a go target in case of TARGET_GAMEOBJECT_TARGET - || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget())) + || (effect->TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget())) return SPELL_FAILED_BAD_TARGETS; Item* pTempItem = NULL; @@ -5219,7 +5428,7 @@ SpellCastResult Spell::CheckCast(bool strict) pTempItem = m_caster->ToPlayer()->GetItemByGuid(m_targets.GetItemTargetGUID()); // we need a go target, or an openable item target in case of TARGET_GAMEOBJECT_ITEM_TARGET - if (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && + if (effect->TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET && !m_targets.GetGOTarget() && (!pTempItem || !pTempItem->GetTemplate()->LockID || !pTempItem->IsLocked())) return SPELL_FAILED_BAD_TARGETS; @@ -5246,7 +5455,7 @@ SpellCastResult Spell::CheckCast(bool strict) int32 skillValue = 0; // check lock compatibility - SpellCastResult res = CanOpenLock(i, lockId, skillId, reqSkillValue, skillValue); + SpellCastResult res = CanOpenLock(effect->EffectIndex, lockId, skillId, reqSkillValue, skillValue); if (res != SPELL_CAST_OK) return res; @@ -5274,7 +5483,7 @@ SpellCastResult Spell::CheckCast(bool strict) // This is generic summon effect case SPELL_EFFECT_SUMMON: { - SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(m_spellInfo->Effects[i].MiscValueB); + SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(effect->MiscValueB); if (!SummonProperties) break; switch (SummonProperties->Category) @@ -5408,9 +5617,11 @@ SpellCastResult Spell::CheckCast(bool strict) } } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - switch (m_spellInfo->Effects[i].ApplyAuraName) + if (!effect) + continue; + switch (effect->ApplyAuraName) { case SPELL_AURA_MOD_POSSESS_PET: { @@ -5432,8 +5643,8 @@ SpellCastResult Spell::CheckCast(bool strict) if (!m_caster->GetCharmerGUID().IsEmpty()) return SPELL_FAILED_CHARMED; - if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_CHARM - || m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_POSSESS) + if (effect->ApplyAuraName == SPELL_AURA_MOD_CHARM + || effect->ApplyAuraName == SPELL_AURA_MOD_POSSESS) { if (!m_caster->GetPetGUID().IsEmpty()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -5456,7 +5667,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (target->GetOwner() && target->GetOwner()->GetTypeId() == TYPEID_PLAYER) return SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED; - int32 damage = CalculateDamage(i, target); + int32 damage = CalculateDamage(effect->EffectIndex, target); if (damage && int32(target->getLevel()) > damage) return SPELL_FAILED_HIGHLEVEL; } @@ -5508,7 +5719,7 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_AURA_PERIODIC_MANA_LEECH: { - if (m_spellInfo->Effects[i].IsTargetingArea()) + if (effect->IsTargetingArea()) break; if (!m_targets.GetUnitTarget()) @@ -5608,14 +5819,17 @@ SpellCastResult Spell::CheckCasterAuras() const // We use bitmasks so the loop is done only once and not on every aura check below. if (m_spellInfo->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_SCHOOL_IMMUNITY) - school_immune |= uint32(m_spellInfo->Effects[i].MiscValue); - else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MECHANIC_IMMUNITY) - mechanic_immune |= 1 << uint32(m_spellInfo->Effects[i].MiscValue); - else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_DISPEL_IMMUNITY) - dispel_immune |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue)); + if (!effect) + continue; + + if (effect->ApplyAuraName == SPELL_AURA_SCHOOL_IMMUNITY) + school_immune |= uint32(effect->MiscValue); + else if (effect->ApplyAuraName == SPELL_AURA_MECHANIC_IMMUNITY) + mechanic_immune |= 1 << uint32(effect->MiscValue); + else if (effect->ApplyAuraName == SPELL_AURA_DISPEL_IMMUNITY) + dispel_immune |= SpellInfo::GetDispelMask(DispelType(effect->MiscValue)); } // immune movement impairment and loss of control if (m_spellInfo->Id == 42292 || m_spellInfo->Id == 59752 || m_spellInfo->Id == 19574) @@ -5684,9 +5898,12 @@ SpellCastResult Spell::CheckCasterAuras() const //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. - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - if (AuraEffect* part = aura->GetEffect(i)) + if (!effect) + continue; + + if (AuraEffect* part = aura->GetEffect(effect->EffectIndex)) { switch (part->GetAuraType()) { @@ -5758,25 +5975,28 @@ bool Spell::CanAutoCast(Unit* target) { ObjectGuid targetguid = target->GetGUID(); - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { - if (m_spellInfo->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA) + if (!effect) + continue; + + if (effect->Effect == SPELL_EFFECT_APPLY_AURA) { if (m_spellInfo->StackAmount <= 1) { - if (target->HasAuraEffect(m_spellInfo->Id, j)) + if (target->HasAuraEffect(m_spellInfo->Id, effect->EffectIndex)) return false; } else { - if (AuraEffect* aureff = target->GetAuraEffect(m_spellInfo->Id, j)) + if (AuraEffect* aureff = target->GetAuraEffect(m_spellInfo->Id, effect->EffectIndex)) if (aureff->GetBase()->GetStackAmount() >= m_spellInfo->StackAmount) return false; } } - else if (m_spellInfo->Effects[j].IsAreaAuraEffect()) + else if (effect->IsAreaAuraEffect()) { - if (target->HasAuraEffect(m_spellInfo->Id, j)) + if (target->HasAuraEffect(m_spellInfo->Id, effect->EffectIndex)) return false; } } @@ -5921,13 +6141,13 @@ SpellCastResult Spell::CheckItems() { // such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example SpellCastResult failReason = SPELL_CAST_OK; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { // skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.GetUnitTarget() is not the real target but the caster - if (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET) + if (!effect || effect->TargetA.GetTarget() == TARGET_UNIT_PET) continue; - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_HEAL) + if (effect->Effect == SPELL_EFFECT_HEAL) { if (m_targets.GetUnitTarget()->IsFullHealth()) { @@ -5942,15 +6162,15 @@ SpellCastResult Spell::CheckItems() } // Mana Potion, Rage Potion, Thistle Tea(Rogue), ... - if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_ENERGIZE) + if (effect->Effect == SPELL_EFFECT_ENERGIZE) { - if (m_spellInfo->Effects[i].MiscValue < 0 || m_spellInfo->Effects[i].MiscValue >= int8(MAX_POWERS)) + if (effect->MiscValue < 0 || effect->MiscValue >= int8(MAX_POWERS)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; continue; } - Powers power = Powers(m_spellInfo->Effects[i].MiscValue); + Powers power = Powers(effect->MiscValue); if (m_targets.GetUnitTarget()->GetPower(power) == m_targets.GetUnitTarget()->GetMaxPower(power)) { failReason = SPELL_FAILED_ALREADY_AT_FULL_POWER; @@ -6048,34 +6268,37 @@ SpellCastResult Spell::CheckItems() } // special checks for spell effects - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - switch (m_spellInfo->Effects[i].Effect) + if (!effect) + continue; + + switch (effect->Effect) { case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_ITEM_2: { - if (!IsTriggered() && m_spellInfo->Effects[i].ItemType) + if (!IsTriggered() && effect->ItemType) { ItemPosCountVec dest; - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1); + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1); if (msg != EQUIP_ERR_OK) { - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(m_spellInfo->Effects[i].ItemType); + ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(effect->ItemType); /// @todo Needs review if (pProto && !(pProto->ItemLimitCategory)) { - player->SendEquipError(msg, NULL, NULL, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, NULL, NULL, effect->ItemType); return SPELL_FAILED_DONT_REPORT; } else { if (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (m_spellInfo->SpellFamilyFlags[0] & 0x40000000))) return SPELL_FAILED_TOO_MANY_OF_ITEM; - else if (!(player->HasItemCount(m_spellInfo->Effects[i].ItemType))) + else if (!(player->HasItemCount(effect->ItemType))) return SPELL_FAILED_TOO_MANY_OF_ITEM; - else - player->CastSpell(m_caster, m_spellInfo->Effects[EFFECT_1].CalcValue(), false); // move this to anywhere + else if (SpellEffectInfo const* efi = GetEffect(EFFECT_1)) + player->CastSpell(m_caster, efi->CalcValue(), false); // move this to anywhere return SPELL_FAILED_DONT_REPORT; } } @@ -6083,7 +6306,7 @@ SpellCastResult Spell::CheckItems() break; } case SPELL_EFFECT_ENCHANT_ITEM: - if (m_spellInfo->Effects[i].ItemType && m_targets.GetItemTarget() + if (effect->ItemType && m_targets.GetItemTarget() && (m_targets.GetItemTarget()->IsVellum())) { // cannot enchant vellum for other player @@ -6093,10 +6316,10 @@ SpellCastResult Spell::CheckItems() if (m_CastItem && m_CastItem->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_TRIGGERED_CAST) return SPELL_FAILED_TOTEM_CATEGORY; ItemPosCountVec dest; - InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1); + InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, effect->ItemType, 1); if (msg != EQUIP_ERR_OK) { - player->SendEquipError(msg, NULL, NULL, m_spellInfo->Effects[i].ItemType); + player->SendEquipError(msg, NULL, NULL, effect->ItemType); return SPELL_FAILED_DONT_REPORT; } } @@ -6123,7 +6346,7 @@ SpellCastResult Spell::CheckItems() } } - SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(m_spellInfo->Effects[i].MiscValue); + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(effect->MiscValue); // do not allow adding usable enchantments to items that have use effect already if (enchantEntry) { @@ -6168,7 +6391,7 @@ SpellCastResult Spell::CheckItems() // Not allow enchant in trade slot for some enchant type if (item->GetOwner() != m_caster) { - uint32 enchant_id = m_spellInfo->Effects[i].MiscValue; + uint32 enchant_id = effect->MiscValue; SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); if (!pEnchant) return SPELL_FAILED_ERROR; @@ -6285,16 +6508,16 @@ SpellCastResult Spell::CheckItems() } case SPELL_EFFECT_CREATE_MANA_GEM: { - uint32 item_id = m_spellInfo->Effects[i].ItemType; - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item_id); + uint32 item_id = effect->ItemType; + ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id); - if (!proto) + if (!pProto) return SPELL_FAILED_ITEM_AT_MAX_CHARGES; - if (Item* item = player->GetItemByEntry(item_id)) + if (Item* pitem = player->GetItemByEntry(item_id)) { - for (uint32 x = 0; x < proto->Effects.size(); ++x) - if (proto->Effects[x].Charges != 0 && item->GetSpellCharges(x) == proto->Effects[x].Charges) + for (int x = 0; x < pProto->Effects.size(); ++x) + if (pProto->Effects[x].Charges != 0 && pitem->GetSpellCharges(x) == pProto->Effects[x].Charges) return SPELL_FAILED_ITEM_AT_MAX_CHARGES; } break; @@ -6457,9 +6680,12 @@ bool Spell::UpdatePointers() WorldObject* transport = NULL; // update effect destinations (in case of moved transport dest target) - for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetEffects()) { - SpellDestination& dest = m_destTargets[effIndex]; + if (!effect) + continue; + + SpellDestination& dest = m_destTargets[effect->EffectIndex]; if (!dest._transportGUID) continue; @@ -6490,7 +6716,11 @@ CurrentSpellTypes Spell::GetCurrentContainer() const bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* losPosition) const { - switch (m_spellInfo->Effects[eff].ApplyAuraName) + SpellEffectInfo const* effect = GetEffect(eff); + if (!effect) + return false; + + switch (effect->ApplyAuraName) { case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_MOD_CHARM: @@ -6520,7 +6750,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo /// @todo shit below shouldn't be here, but it's temporary //Check targets for LOS visibility (except spells without range limitations) - switch (m_spellInfo->Effects[eff].Effect) + switch (effect->Effect) { case SPELL_EFFECT_RESURRECT_NEW: // player far away, maybe his corpse near? @@ -6731,21 +6961,19 @@ bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const void Spell::HandleLaunchPhase() { // handle effects with SPELL_EFFECT_HANDLE_LAUNCH mode - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { // don't do anything for empty effect - if (!m_spellInfo->Effects[i].IsEffect()) + if (!effect || !effect->IsEffect()) continue; - HandleEffects(NULL, NULL, NULL, i, SPELL_EFFECT_HANDLE_LAUNCH); + HandleEffects(NULL, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_LAUNCH); } float multiplier[MAX_SPELL_EFFECTS]; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_applyMultiplierMask & (1 << i)) - multiplier[i] = m_spellInfo->Effects[i].CalcDamageMultiplier(m_originalCaster, this); - - bool usesAmmo = (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_DIRECT_DAMAGE) != 0; + for (SpellEffectInfo const* effect : GetEffects()) + if (effect && (m_applyMultiplierMask & (1 << effect->EffectIndex))) + multiplier[effect->EffectIndex] = effect->CalcDamageMultiplier(m_originalCaster, this); for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { @@ -6755,31 +6983,6 @@ void Spell::HandleLaunchPhase() if (!mask) continue; - // do not consume ammo anymore for Hunter's volley spell - if (IsTriggered() && m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->IsTargetingArea()) - usesAmmo = false; - - if (usesAmmo) - { - bool ammoTaken = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) - { - if (!(mask & 1<<i)) - continue; - switch (m_spellInfo->Effects[i].Effect) - { - case SPELL_EFFECT_SCHOOL_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE: - case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ammoTaken=true; - TakeAmmo(); - } - if (ammoTaken) - break; - } - } DoAllEffectOnLaunchTarget(target, multiplier); } } @@ -6796,18 +6999,18 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) if (!unit) return; - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - if (targetInfo.effectMask & (1<<i)) + if (effect && (targetInfo.effectMask & (1<<effect->EffectIndex))) { m_damage = 0; m_healing = 0; - HandleEffects(unit, NULL, NULL, i, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); + HandleEffects(unit, NULL, NULL, effect->EffectIndex, SPELL_EFFECT_HANDLE_LAUNCH_TARGET); if (m_damage > 0) { - if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) + if (effect->IsTargetingArea() || effect->IsAreaAuraEffect() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) { m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask)); if (m_caster->GetTypeId() != TYPEID_PLAYER) @@ -6822,10 +7025,10 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) } } - if (m_applyMultiplierMask & (1 << i)) + if (m_applyMultiplierMask & (1 << effect->EffectIndex)) { - m_damage = int32(m_damage * m_damageMultipliers[i]); - m_damageMultipliers[i] *= multiplier[i]; + m_damage = int32(m_damage * m_damageMultipliers[effect->EffectIndex]); + m_damageMultipliers[effect->EffectIndex] *= multiplier[effect->EffectIndex]; } targetInfo.damage += m_damage; } @@ -6845,6 +7048,10 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk if (!lockInfo) return SPELL_FAILED_BAD_TARGETS; + SpellEffectInfo const* effect = GetEffect(effIndex); + if (!effect) + return SPELL_FAILED_BAD_TARGETS; // no idea about correct error + bool reqKey = false; // some locks not have reqs for (int j = 0; j < MAX_LOCK_CASE; ++j) @@ -6863,7 +7070,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk reqKey = true; // wrong locktype, skip - if (uint32(m_spellInfo->Effects[effIndex].MiscValue) != lockInfo->Index[j]) + if (uint32(effect->MiscValue) != lockInfo->Index[j]) continue; skillId = SkillByLockType(LockType(lockInfo->Index[j])); @@ -6878,8 +7085,8 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk // skill bonus provided by casting spell (mostly item spells) // add the effect base points modifier from the spell cast (cheat lock / skeleton key etc.) - if (m_spellInfo->Effects[effIndex].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET || m_spellInfo->Effects[effIndex].TargetB.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET) - skillValue += m_spellInfo->Effects[effIndex].CalcValue(); + if (effect->TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET || effect->TargetB.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET) + skillValue += effect->CalcValue(); if (skillValue < reqSkillValue) return SPELL_FAILED_LOW_CASTLEVEL; @@ -6898,17 +7105,15 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk void Spell::SetSpellValue(SpellValueMod mod, int32 value) { + if (mod < SPELLVALUE_BASE_POINT_END) + { + if (SpellEffectInfo const* effect = GetEffect(mod)) + m_spellValue->EffectBasePoints[mod] = effect->CalcBaseValue(value); + return; + } + switch (mod) { - case SPELLVALUE_BASE_POINT0: - m_spellValue->EffectBasePoints[0] = m_spellInfo->Effects[EFFECT_0].CalcBaseValue(value); - break; - case SPELLVALUE_BASE_POINT1: - m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(value); - break; - case SPELLVALUE_BASE_POINT2: - m_spellValue->EffectBasePoints[2] = m_spellInfo->Effects[EFFECT_2].CalcBaseValue(value); - break; case SPELLVALUE_RADIUS_MOD: m_spellValue->RadiusMod = (float)value / 10000; break; @@ -6931,7 +7136,7 @@ void Spell::FinishTargetProcessing() SendLogExecute(); } -void Spell::InitEffectExecuteData(uint8 effIndex) +void Spell::InitEffectExecuteData(uint32 effIndex) { ASSERT(effIndex < MAX_SPELL_EFFECTS); if (!m_effectExecuteData[effIndex]) @@ -7193,9 +7398,9 @@ bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByA { bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER)); // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a cast spell with TARGET_UNIT_CASTER - for (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffects()) { - if ((effMask & (1 << i)) && (!only_on_caster || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER))) + if (effect && ((effMask & (1 << effect->EffectIndex)) && (!only_on_caster || (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER)))) return true; } return false; @@ -7236,19 +7441,23 @@ void Spell::PrepareTriggersExecutedOnHit() continue; SpellInfo const* auraSpellInfo = (*i)->GetSpellInfo(); uint32 auraSpellIdx = (*i)->GetEffIndex(); - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(auraSpellInfo->Effects[auraSpellIdx].TriggerSpell)) + // todo 6.x + if (SpellEffectInfo const* auraEffect = auraSpellInfo->GetEffect(m_caster->GetMap()->GetDifficulty(), auraSpellIdx)) { - // calculate the chance using spell base amount, because aura amount is not updated on combo-points change - // this possibly needs fixing - int32 auraBaseAmount = (*i)->GetBaseAmount(); - // proc chance is stored in effect amount - int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount); - // build trigger and add to the list - HitTriggerSpell spellTriggerInfo; - spellTriggerInfo.triggeredSpell = spellInfo; - spellTriggerInfo.triggeredByAura = auraSpellInfo; - spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount(); - m_hitTriggerSpells.push_back(spellTriggerInfo); + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(auraEffect->TriggerSpell)) + { + // calculate the chance using spell base amount, because aura amount is not updated on combo-points change + // this possibly needs fixing + int32 auraBaseAmount = (*i)->GetBaseAmount(); + // proc chance is stored in effect amount + int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount); + // build trigger and add to the list + HitTriggerSpell spellTriggerInfo; + spellTriggerInfo.triggeredSpell = spellInfo; + spellTriggerInfo.triggeredByAura = auraSpellInfo; + spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount(); + m_hitTriggerSpells.push_back(spellTriggerInfo); + } } } } @@ -7321,6 +7530,16 @@ void Spell::CancelGlobalCooldown() m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo); } +bool Spell::HasEffect(SpellEffectName effect) const +{ + for (SpellEffectInfo const* eff : GetEffects()) + { + if (eff && eff->IsEffect(effect)) + return true; + } + return false; +} + namespace Trinity { diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index dc07449c41f..33e4923d2f1 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -25,6 +25,14 @@ #include "SpellInfo.h" #include "PathGenerator.h" +namespace WorldPackets +{ + namespace Spells + { + struct SpellTargetData; + } +} + class Unit; class Player; class GameObject; @@ -99,10 +107,11 @@ class SpellCastTargets { public: SpellCastTargets(); + SpellCastTargets(Unit* caster, uint32 targetMask, ObjectGuid targetGuid, ObjectGuid itemTargetGuid, ObjectGuid srcTransportGuid, ObjectGuid destTransportGuid, Position srcPos, Position destPos, float elevation, float missileSpeed, std::string targetString); ~SpellCastTargets(); void Read(ByteBuffer& data, Unit* caster); - void Write(ByteBuffer& data); + void Write(WorldPackets::Spells::SpellTargetData& data); uint32 GetTargetMask() const { return m_targetMask; } void SetTargetMask(uint32 newMask) { m_targetMask = newMask; } @@ -168,6 +177,7 @@ class SpellCastTargets void Update(Unit* caster); void OutDebug() const; + std::string GetTargetString() const { return m_strTarget; } private: uint32 m_targetMask; @@ -377,7 +387,7 @@ class Spell void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask); void SelectImplicitTrajTargets(SpellEffIndex effIndex); - void SelectEffectTypeImplicitTargets(uint8 effIndex); + void SelectEffectTypeImplicitTargets(uint32 effIndex); uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList); template<class SEARCHER> void SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius); @@ -394,7 +404,6 @@ class Spell void cast(bool skipCheck = false); void finish(bool ok = true); void TakePower(); - void TakeAmmo(); void TakeRunePower(bool didHit); void TakeReagents(); @@ -503,6 +512,24 @@ class Spell void CleanupTargetList(); void SetSpellValue(SpellValueMod mod, int32 value); + + SpellEffectInfoVector GetEffects() const { return _effects; } + SpellEffectInfo const* GetEffect(uint32 index) const + { + if (index >= _effects.size()) + return nullptr; + + return _effects[index]; + } + + bool HasEffect(SpellEffectName effect) const; + + Spell** m_selfContainer; // pointer to our spell container (if applicable) + + SpellInfo const* GetTriggeredByAuraSpell() const { return m_triggeredByAuraSpell; } + + int32 GetTimer() const { return m_timer; } + protected: bool HasGlobalCooldown() const; void TriggerGlobalCooldown(); @@ -518,8 +545,6 @@ class Spell // e.g. damage around area spell trigered by victim aura and damage enemies of aura caster Unit* m_originalCaster; // cached pointer for m_originalCaster, updated at Spell::UpdatePointers() - Spell** m_selfContainer; // pointer to our spell container (if applicable) - //Spell data SpellSchoolMask m_spellSchoolMask; // Spell school (can be overwrite for some spells (wand shoot for example) WeaponAttackType m_attackType; // For weapon based attack @@ -591,7 +616,7 @@ class Spell uint64 timeDelay; SpellMissInfo missCondition:8; SpellMissInfo reflectResult:8; - uint8 effectMask:8; + uint32 effectMask:32; bool processed:1; bool alive:1; bool crit:1; @@ -599,13 +624,13 @@ class Spell int32 damage; }; std::list<TargetInfo> m_UniqueTargetInfo; - uint8 m_channelTargetEffectMask; // Mask req. alive targets + uint32 m_channelTargetEffectMask; // Mask req. alive targets struct GOTargetInfo { ObjectGuid targetGUID; uint64 timeDelay; - uint8 effectMask:8; + uint32 effectMask:32; bool processed:1; }; std::list<GOTargetInfo> m_UniqueGOTargetInfo; @@ -613,7 +638,7 @@ class Spell struct ItemTargetInfo { Item *item; - uint8 effectMask; + uint32 effectMask; }; std::list<ItemTargetInfo> m_UniqueItemInfo; @@ -638,7 +663,7 @@ class Spell void FinishTargetProcessing(); // spell execution log - void InitEffectExecuteData(uint8 effIndex); + void InitEffectExecuteData(uint32 effIndex); void CheckEffectExecuteData(); // Scripting system @@ -689,7 +714,7 @@ class Spell SpellInfo const* m_triggeredByAuraSpell; bool m_skipCheck; - uint8 m_auraScaleMask; + uint32 m_auraScaleMask; PathGenerator m_preGeneratedPath; ByteBuffer * m_effectExecuteData[MAX_SPELL_EFFECTS]; @@ -704,6 +729,8 @@ class Spell Spell(Spell const& right) = delete; Spell& operator=(Spell const& right) = delete; + + SpellEffectInfoVector _effects; }; namespace Trinity diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index eb4d0ad49de..9f53a2da031 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -252,6 +252,68 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectUnused, //180 SPELL_EFFECT_180 unused &Spell::EffectUnused, //181 SPELL_EFFECT_181 unused &Spell::EffectNULL, //182 SPELL_EFFECT_182 + &Spell::EffectNULL, //183 SPELL_EFFECT_183 + &Spell::EffectNULL, //184 SPELL_EFFECT_184 + &Spell::EffectNULL, //185 SPELL_EFFECT_185 + &Spell::EffectNULL, //186 SPELL_EFFECT_186 + &Spell::EffectNULL, //187 SPELL_EFFECT_187 + &Spell::EffectNULL, //188 SPELL_EFFECT_188 + &Spell::EffectNULL, //189 SPELL_EFFECT_189 + &Spell::EffectNULL, //190 SPELL_EFFECT_190 + &Spell::EffectNULL, //191 SPELL_EFFECT_191 + &Spell::EffectNULL, //192 SPELL_EFFECT_192 + &Spell::EffectNULL, //193 SPELL_EFFECT_193 + &Spell::EffectNULL, //194 SPELL_EFFECT_194 + &Spell::EffectNULL, //195 SPELL_EFFECT_195 + &Spell::EffectNULL, //196 SPELL_EFFECT_196 + &Spell::EffectNULL, //197 SPELL_EFFECT_197 + &Spell::EffectNULL, //198 SPELL_EFFECT_198 + &Spell::EffectNULL, //199 SPELL_EFFECT_199 + &Spell::EffectNULL, //200 SPELL_EFFECT_200 + &Spell::EffectNULL, //201 SPELL_EFFECT_201 + &Spell::EffectNULL, //202 SPELL_EFFECT_202 + &Spell::EffectNULL, //203 SPELL_EFFECT_203 + &Spell::EffectNULL, //204 SPELL_EFFECT_204 + &Spell::EffectNULL, //205 SPELL_EFFECT_205 + &Spell::EffectNULL, //206 SPELL_EFFECT_206 + &Spell::EffectNULL, //207 SPELL_EFFECT_207 + &Spell::EffectNULL, //208 SPELL_EFFECT_208 + &Spell::EffectNULL, //209 SPELL_EFFECT_209 + &Spell::EffectNULL, //210 SPELL_EFFECT_210 + &Spell::EffectNULL, //211 SPELL_EFFECT_211 + &Spell::EffectNULL, //212 SPELL_EFFECT_212 + &Spell::EffectNULL, //213 SPELL_EFFECT_213 + &Spell::EffectNULL, //214 SPELL_EFFECT_214 + &Spell::EffectNULL, //215 SPELL_EFFECT_215 + &Spell::EffectNULL, //216 SPELL_EFFECT_216 + &Spell::EffectNULL, //217 SPELL_EFFECT_217 + &Spell::EffectNULL, //218 SPELL_EFFECT_218 + &Spell::EffectNULL, //219 SPELL_EFFECT_219 + &Spell::EffectNULL, //220 SPELL_EFFECT_220 + &Spell::EffectNULL, //221 SPELL_EFFECT_221 + &Spell::EffectNULL, //222 SPELL_EFFECT_222 + &Spell::EffectNULL, //223 SPELL_EFFECT_223 + &Spell::EffectNULL, //224 SPELL_EFFECT_224 + &Spell::EffectNULL, //225 SPELL_EFFECT_225 + &Spell::EffectNULL, //226 SPELL_EFFECT_226 + &Spell::EffectNULL, //227 SPELL_EFFECT_227 + &Spell::EffectNULL, //228 SPELL_EFFECT_228 + &Spell::EffectNULL, //229 SPELL_EFFECT_229 + &Spell::EffectNULL, //230 SPELL_EFFECT_230 + &Spell::EffectNULL, //231 SPELL_EFFECT_231 + &Spell::EffectNULL, //232 SPELL_EFFECT_232 + &Spell::EffectNULL, //233 SPELL_EFFECT_233 + &Spell::EffectNULL, //234 SPELL_EFFECT_234 + &Spell::EffectNULL, //235 SPELL_EFFECT_235 + &Spell::EffectNULL, //236 SPELL_EFFECT_236 + &Spell::EffectNULL, //237 SPELL_EFFECT_237 + &Spell::EffectNULL, //238 SPELL_EFFECT_238 + &Spell::EffectNULL, //239 SPELL_EFFECT_239 + &Spell::EffectNULL, //240 SPELL_EFFECT_240 + &Spell::EffectNULL, //241 SPELL_EFFECT_241 + &Spell::EffectNULL, //242 SPELL_EFFECT_242 + &Spell::EffectNULL, //243 SPELL_EFFECT_243 + &Spell::EffectNULL, //244 SPELL_EFFECT_244 }; void Spell::EffectNULL(SpellEffIndex /*effIndex*/) @@ -284,7 +346,7 @@ void Spell::EffectResurrectNew(SpellEffIndex effIndex) return; uint32 health = damage; - uint32 mana = m_spellInfo->Effects[effIndex].MiscValue; + uint32 mana = GetEffect(effIndex)->MiscValue; ExecuteLogEffectResurrect(effIndex, target); target->SetResurrectRequestData(m_caster, health, mana, 0); SendResurrectRequest(target); @@ -359,7 +421,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) { // Consumption case 28865: - damage = (((InstanceMap*)m_caster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 2750 : 4250); + damage = (((InstanceMap*)m_caster->GetMap())->GetDifficulty() == DIFFICULTY_NONE ? 2750 : 4250); break; // percent from health with min case 25599: // Thundercrash @@ -419,23 +481,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) } case SPELLFAMILY_PRIEST: { - // Improved Mind Blast (Mind Blast in shadow form bonus) - if (m_caster->GetShapeshiftForm() == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags[0] & 0x00002000)) - { - Unit::AuraEffectList const& ImprMindBlast = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_FLAT_MODIFIER); - for (Unit::AuraEffectList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i) - { - if ((*i)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_PRIEST && - ((*i)->GetSpellInfo()->SpellIconID == 95)) - { - int chance = (*i)->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster); - if (roll_chance_i(chance)) - // Mind Trauma - m_caster->CastSpell(unitTarget, 48301, true, nullptr); - break; - } - } - } break; } case SPELLFAMILY_DRUID: @@ -464,31 +509,14 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x00010000, 0, 0, m_caster->GetGUID())) { // count consumed deadly poison doses at target - bool needConsume = true; uint32 spellId = aurEff->GetId(); uint32 doses = aurEff->GetBase()->GetStackAmount(); if (doses > combo) doses = combo; - // Master Poisoner - Unit::AuraEffectList const& auraList = player->GetAuraEffectsByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK); - for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter) - { - if ((*iter)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellInfo()->SpellIconID == 1960) - { - uint32 chance = (*iter)->GetSpellInfo()->Effects[EFFECT_2].CalcValue(m_caster); - - if (chance && roll_chance_i(chance)) - needConsume = false; - - break; - } - } - - if (needConsume) - for (uint32 i = 0; i < doses; ++i) - unitTarget->RemoveAuraFromStack(spellId, m_caster->GetGUID()); + for (uint32 i = 0; i < doses; ++i) + unitTarget->RemoveAuraFromStack(spellId, m_caster->GetGUID()); damage *= doses; damage += int32(player->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * combo); @@ -618,10 +646,10 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) && effectHandleMode != SPELL_EFFECT_HANDLE_LAUNCH) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; /// @todo move those to spell scripts - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_TRIGGER_SPELL && effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { // special cases @@ -718,13 +746,13 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo)) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty())) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH) { - if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty()) && (GetEffect(effIndex)->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -738,7 +766,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) CustomSpellValues values; // set basepoints for trigger with value effect - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE) { values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); values.AddSpellMod(SPELLVALUE_BASE_POINT1, damage); @@ -760,7 +788,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) && effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; // normal case SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -773,13 +801,13 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo)) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty())) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT) { - if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty()) && (GetEffect(effIndex)->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -790,7 +818,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) CustomSpellValues values; // set basepoints for trigger with value effect - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE) { // maybe need to set value only when basepoints == 0? values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); @@ -815,7 +843,7 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) if (!unitTarget) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; // normal case SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -826,7 +854,7 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) return; } - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST && damage) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_FORCE_CAST && damage) { switch (m_spellInfo->Id) { @@ -850,7 +878,7 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) CustomSpellValues values; // set basepoints for trigger with value effect - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE) { // maybe need to set value only when basepoints == 0? values.AddSpellMod(SPELLVALUE_BASE_POINT0, damage); @@ -869,7 +897,7 @@ void Spell::EffectTriggerRitualOfSummoning(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 triggered_spell_id = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetEffect(effIndex)->TriggerSpell; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id); if (!spellInfo) @@ -924,12 +952,16 @@ void Spell::EffectJumpDest(SpellEffIndex effIndex) void Spell::CalculateJumpSpeeds(uint8 i, float dist, float & speedXY, float & speedZ) { - if (m_spellInfo->Effects[i].MiscValue) - speedZ = float(m_spellInfo->Effects[i].MiscValue)/10; - else if (m_spellInfo->Effects[i].MiscValueB) - speedZ = float(m_spellInfo->Effects[i].MiscValueB)/10; - else - speedZ = 10.0f; + SpellEffectInfo const* effect = GetEffect(i); + if (effect) + { + if (effect->MiscValue) + speedZ = float(effect->MiscValue) / 10; + else if (effect->MiscValueB) + speedZ = float(effect->MiscValueB) / 10; + else + speedZ = 10.0f; + } speedXY = dist * 10.0f / speedZ; } @@ -1096,7 +1128,7 @@ void Spell::EffectUnlearnSpecialization(SpellEffIndex effIndex) return; Player* player = unitTarget->ToPlayer(); - uint32 spellToUnlearn = m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 spellToUnlearn = GetEffect(effIndex)->TriggerSpell; player->RemoveSpell(spellToUnlearn); @@ -1108,10 +1140,10 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers powerType = Powers(GetEffect(effIndex)->MiscValue); if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != powerType || damage < 0) return; @@ -1127,7 +1159,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex) // Don't restore from self drain if (m_caster != unitTarget) { - gainMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this); + gainMultiplier = GetEffect(effIndex)->CalcValueMultiplier(m_originalCaster, this); int32 gain = int32(newDamage* gainMultiplier); @@ -1159,7 +1191,7 @@ void Spell::EffectSendEvent(SpellEffIndex effIndex) // this check was requested by scripters, but it has some downsides: // now it's impossible to script (using sEventScripts) a cast which misses all targets // or to have an ability to script the moment spell hits dest (in a case when there are object targets present) - if (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK)) + if (GetEffect(effIndex)->GetProvidedTargetMask() & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK)) return; // some spells have no target entries in dbc and they use focus target if (focusObject) @@ -1167,14 +1199,14 @@ void Spell::EffectSendEvent(SpellEffIndex effIndex) /// @todo there should be a possibility to pass dest target to event script } - TC_LOG_DEBUG("spells", "Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id); + TC_LOG_DEBUG("spells", "Spell ScriptStart %u for spellid %u in EffectSendEvent ", GetEffect(effIndex)->MiscValue, m_spellInfo->Id); if (ZoneScript* zoneScript = m_caster->GetZoneScript()) - zoneScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue); + zoneScript->ProcessEvent(target, GetEffect(effIndex)->MiscValue); else if (InstanceScript* instanceScript = m_caster->GetInstanceScript()) // needed in case Player is the caster - instanceScript->ProcessEvent(target, m_spellInfo->Effects[effIndex].MiscValue); + instanceScript->ProcessEvent(target, GetEffect(effIndex)->MiscValue); - m_caster->GetMap()->ScriptsStart(sEventScripts, m_spellInfo->Effects[effIndex].MiscValue, m_caster, target); + m_caster->GetMap()->ScriptsStart(sEventScripts, GetEffect(effIndex)->MiscValue, m_caster, target); } void Spell::EffectPowerBurn(SpellEffIndex effIndex) @@ -1182,10 +1214,10 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers powerType = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers powerType = Powers(GetEffect(effIndex)->MiscValue); if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != powerType || damage < 0) return; @@ -1201,7 +1233,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex) int32 newDamage = -(unitTarget->ModifyPower(powerType, -damage)); // NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier - float dmgMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this); + float dmgMultiplier = GetEffect(effIndex)->CalcValueMultiplier(m_originalCaster, this); // add log data before multiplication (need power amount, not damage) ExecuteLogEffectTakeTargetPower(effIndex, unitTarget, powerType, newDamage, 0.0f); @@ -1356,7 +1388,7 @@ void Spell::EffectHealthLeech(SpellEffIndex effIndex) TC_LOG_DEBUG("spells", "HealthLeech :%i", damage); - float healMultiplier = m_spellInfo->Effects[effIndex].CalcValueMultiplier(m_originalCaster, this); + float healMultiplier = GetEffect(effIndex)->CalcValueMultiplier(m_originalCaster, this); m_damage += damage; // get max possible damage, don't count overkill for heal @@ -1491,8 +1523,8 @@ void Spell::EffectCreateItem(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType); - ExecuteLogEffectCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType); + DoCreateItem(effIndex, GetEffect(effIndex)->ItemType); + ExecuteLogEffectCreateItem(effIndex, GetEffect(effIndex)->ItemType); } void Spell::EffectCreateItem2(SpellEffIndex effIndex) @@ -1505,7 +1537,7 @@ void Spell::EffectCreateItem2(SpellEffIndex effIndex) Player* player = unitTarget->ToPlayer(); - uint32 item_id = m_spellInfo->Effects[effIndex].ItemType; + uint32 item_id = GetEffect(effIndex)->ItemType; if (item_id) DoCreateItem(effIndex, item_id); @@ -1553,7 +1585,7 @@ void Spell::EffectPersistentAA(SpellEffIndex effIndex) if (!m_spellAura) { Unit* caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(caster); + float radius = GetEffect(effIndex)->CalcRadius(caster); // Caster not in world, might be spell triggered from aura removal if (!caster->IsInWorld()) @@ -1588,10 +1620,10 @@ void Spell::EffectEnergize(SpellEffIndex effIndex) if (!unitTarget->IsAlive()) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers power = Powers(GetEffect(effIndex)->MiscValue); if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !(m_spellInfo->AttributesEx7 & SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER)) return; @@ -1697,10 +1729,10 @@ void Spell::EffectEnergizePct(SpellEffIndex effIndex) if (!unitTarget->IsAlive()) return; - if (m_spellInfo->Effects[effIndex].MiscValue < 0 || m_spellInfo->Effects[effIndex].MiscValue >= int8(MAX_POWERS)) + if (GetEffect(effIndex)->MiscValue < 0 || GetEffect(effIndex)->MiscValue >= int8(MAX_POWERS)) return; - Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue); + Powers power = Powers(GetEffect(effIndex)->MiscValue); if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !(m_spellInfo->AttributesEx7 & SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER)) return; @@ -1905,7 +1937,7 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) if (m_CastItem->GetOwnerGUID() != player->GetGUID()) return; - uint32 newitemid = m_spellInfo->Effects[effIndex].ItemType; + uint32 newitemid = GetEffect(effIndex)->ItemType; if (!newitemid) return; @@ -2022,14 +2054,14 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 entry = m_spellInfo->Effects[effIndex].MiscValue; + uint32 entry = GetEffect(effIndex)->MiscValue; if (!entry) return; - SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(m_spellInfo->Effects[effIndex].MiscValueB); + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(GetEffect(effIndex)->MiscValueB); if (!properties) { - TC_LOG_ERROR("spells", "EffectSummonType: Unhandled summon type %u", m_spellInfo->Effects[effIndex].MiscValueB); + TC_LOG_ERROR("spells", "EffectSummonType: Unhandled summon type %u", GetEffect(effIndex)->MiscValueB); return; } @@ -2130,7 +2162,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) } default: { - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; @@ -2175,8 +2207,8 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) // The spell that this effect will trigger. It has SPELL_AURA_CONTROL_VEHICLE uint32 spellId = VEHICLE_SPELL_RIDE_HARDCODED; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].CalcValue()); - if (spellInfo && spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(GetEffect(effIndex)->CalcValue()); + if (spellInfo && spellInfo->HasAura(m_originalCaster->GetMap()->GetDifficulty(), SPELL_AURA_CONTROL_VEHICLE)) spellId = spellInfo->Id; // Hard coded enter vehicle spell @@ -2214,7 +2246,7 @@ void Spell::EffectLearnSpell(SpellEffIndex effIndex) Player* player = unitTarget->ToPlayer(); - uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : m_spellInfo->Effects[effIndex].TriggerSpell; + uint32 spellToLearn = (m_spellInfo->Id == 483 || m_spellInfo->Id == 55884) ? damage : GetEffect(effIndex)->TriggerSpell; player->LearnSpell(spellToLearn, false); TC_LOG_DEBUG("spells", "Spell: %s has learned spell %u from %s", player->GetGUID().ToString().c_str(), spellToLearn, m_caster->GetGUID().ToString().c_str()); @@ -2229,7 +2261,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex) return; // Create dispel mask by dispel type - uint32 dispel_type = m_spellInfo->Effects[effIndex].MiscValue; + uint32 dispel_type = GetEffect(effIndex)->MiscValue; uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(dispel_type)); DispelChargesList dispel_list; @@ -2316,12 +2348,15 @@ void Spell::EffectDispel(SpellEffIndex effIndex) // Devour Magic if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->GetCategory() == SPELLCATEGORY_DEVOUR_MAGIC) { - int32 heal_amount = m_spellInfo->Effects[EFFECT_1].CalcValue(m_caster); - m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true); - // Glyph of Felhunter - if (Unit* owner = m_caster->GetOwner()) + if (SpellEffectInfo const* effect = GetEffect(EFFECT_1)) + { + int32 heal_amount = effect->CalcValue(m_caster); + m_caster->CastCustomSpell(m_caster, 19658, &heal_amount, NULL, NULL, true); + // Glyph of Felhunter + if (Unit* owner = m_caster->GetOwner()) if (owner->GetAura(56249)) owner->CastCustomSpell(owner, 19658, &heal_amount, NULL, NULL, true); + } } } @@ -2384,7 +2419,7 @@ void Spell::EffectAddFarsight(SpellEffIndex effIndex) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); int32 duration = m_spellInfo->GetDuration(); // Caster not in world, might be spell triggered from aura removal if (!m_caster->IsInWorld()) @@ -2423,7 +2458,7 @@ void Spell::EffectTeleUnitsFaceCaster(SpellEffIndex effIndex) if (unitTarget->IsInFlight()) return; - float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); + float dis = GetEffect(effIndex)->CalcRadius(m_caster); float fx, fy, fz; m_caster->GetClosePoint(fx, fy, fz, unitTarget->GetObjectSize(), dis); @@ -2442,7 +2477,7 @@ void Spell::EffectLearnSkill(SpellEffIndex effIndex) if (damage < 0) return; - uint32 skillid = m_spellInfo->Effects[effIndex].MiscValue; + uint32 skillid = GetEffect(effIndex)->MiscValue; SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skillid, unitTarget->getRace(), unitTarget->getClass()); if (!rcEntry) return; @@ -2452,7 +2487,7 @@ void Spell::EffectLearnSkill(SpellEffIndex effIndex) return; uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid); - unitTarget->ToPlayer()->SetSkill(skillid, m_spellInfo->Effects[effIndex].CalcValue(), std::max<uint16>(skillval, 1), tier->Value[damage - 1]); + unitTarget->ToPlayer()->SetSkill(skillid, GetEffect(effIndex)->CalcValue(), std::max<uint16>(skillval, 1), tier->Value[damage - 1]); } void Spell::EffectPlayMovie(SpellEffIndex effIndex) @@ -2462,12 +2497,14 @@ void Spell::EffectPlayMovie(SpellEffIndex effIndex) if (unitTarget->GetTypeId() != TYPEID_PLAYER) return; + if (SpellEffectInfo const* effect = GetEffect(effIndex)) + { + uint32 movieId = effect->MiscValue; + if (!sMovieStore.LookupEntry(movieId)) + return; - uint32 movieId = GetSpellInfo()->Effects[effIndex].MiscValue; - if (!sMovieStore.LookupEntry(movieId)) - return; - - unitTarget->ToPlayer()->SendMovieStart(movieId); + unitTarget->ToPlayer()->SendMovieStart(movieId); + } } void Spell::EffectTradeSkill(SpellEffIndex /*effIndex*/) @@ -2502,7 +2539,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) player->DestroyItemCount(itemTarget, count, true); unitTarget = player; // and add a scroll - DoCreateItem(effIndex, m_spellInfo->Effects[effIndex].ItemType); + DoCreateItem(effIndex, GetEffect(effIndex)->ItemType); itemTarget = NULL; m_targets.SetItemTarget(NULL); } @@ -2512,7 +2549,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) if (!(m_CastItem && m_CastItem->GetTemplate()->Flags[0] & ITEM_PROTO_FLAG_TRIGGERED_CAST)) player->UpdateCraftSkill(m_spellInfo->Id); - uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchant_id = GetEffect(effIndex)->MiscValue; if (!enchant_id) return; @@ -2558,7 +2595,7 @@ void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex) if (!player) return; - uint32 enchantId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchantId = GetEffect(effIndex)->MiscValue; if (!enchantId) return; @@ -2622,7 +2659,7 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) if (!itemTarget) return; - uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchant_id = GetEffect(effIndex)->MiscValue; if (!enchant_id) { @@ -2757,7 +2794,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) owner = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself(); } - uint32 petentry = m_spellInfo->Effects[effIndex].MiscValue; + uint32 petentry = GetEffect(effIndex)->MiscValue; if (!owner) { @@ -2843,7 +2880,7 @@ void Spell::EffectLearnPetSpell(SpellEffIndex effIndex) if (!pet) return; - SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].TriggerSpell); + SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(GetEffect(effIndex)->TriggerSpell); if (!learn_spellproto) return; @@ -2898,9 +2935,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // multiple weapon dmg effect workaround // execute only the last weapon damage // and handle all effects at once - for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { - switch (m_spellInfo->Effects[j].Effect) + if (!effect) + continue; + switch (effect->Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -2988,48 +3027,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // Blood Strike if (m_spellInfo->SpellFamilyFlags[0] & 0x400000) { - float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f; - // Death Knight T8 Melee 4P Bonus - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) - AddPct(bonusPct, aurEff->GetAmount()); - AddPct(totalDamagePercentMod, bonusPct); - break; - } - // Death Strike - if (m_spellInfo->SpellFamilyFlags[0] & 0x10) - { - // Glyph of Death Strike - // 2% more damage per 5 runic power, up to a maximum of 40% - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(59336, EFFECT_0)) - if (uint32 runic = std::min<uint32>(uint32(m_caster->GetPower(POWER_RUNIC_POWER) / 2.5f), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(m_caster))) - AddPct(totalDamagePercentMod, runic); - break; - } - // Obliterate (12.5% more damage per disease) - if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) - { - float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), false) / 2.0f; - // Death Knight T8 Melee 4P Bonus - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) - AddPct(bonusPct, aurEff->GetAmount()); - AddPct(totalDamagePercentMod, bonusPct); - break; - } - // Blood-Caked Strike - Blood-Caked Blade - if (m_spellInfo->SpellIconID == 1736) - { - AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) * 50.0f); - break; - } - // Heart Strike - if (m_spellInfo->SpellFamilyFlags[0] & 0x1000000) - { - float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()); - // Death Knight T8 Melee 4P Bonus - if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) - AddPct(bonusPct, aurEff->GetAmount()); - - AddPct(totalDamagePercentMod, bonusPct); + if (SpellEffectInfo const* effect = GetEffect(EFFECT_2)) + { + float bonusPct = effect->CalcValue(m_caster) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f; + // Death Knight T8 Melee 4P Bonus + if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) + AddPct(bonusPct, aurEff->GetAmount()); + AddPct(totalDamagePercentMod, bonusPct); + } break; } break; @@ -3038,20 +3043,22 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) bool normalized = false; float weaponDamagePercentMod = 1.0f; - for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { - switch (m_spellInfo->Effects[j].Effect) + if (!effect) + continue; + switch (effect->Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += CalculateDamage(j, unitTarget); + fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += CalculateDamage(j, unitTarget); + fixed_bonus += CalculateDamage(effect->EffectIndex, unitTarget); normalized = true; break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ApplyPct(weaponDamagePercentMod, CalculateDamage(j, unitTarget)); + ApplyPct(weaponDamagePercentMod, CalculateDamage(effect->EffectIndex, unitTarget)); break; default: break; // not weapon damage effect, just skip @@ -3083,11 +3090,13 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) int32 weaponDamage = m_caster->CalculateDamage(m_attackType, normalized, true); // Sequence is important - for (int j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : GetEffects()) { + if (!effect) + continue; // We assume that a spell have at most one fixed_bonus // and at most one weaponDamagePercentMod - switch (m_spellInfo->Effects[j].Effect) + switch (effect->Effect) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: @@ -3189,7 +3198,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 gameobject_id = GetEffect(effIndex)->MiscValue; GameObject* pGameObj = new GameObject; @@ -3321,7 +3330,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) case 55693: // Remove Collapsing Cave Aura if (!unitTarget) return; - unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].CalcValue()); + unitTarget->RemoveAurasDueToSpell(GetEffect(effIndex)->CalcValue()); break; // Bending Shinbone case 8856: @@ -3455,7 +3464,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) case 45151: { //Workaround for Range ... should be global for every ScriptEffect - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->GetDistance(m_caster) >= radius && !unitTarget->HasAura(46394) && unitTarget != m_caster) unitTarget->CastSpell(unitTarget, 46394, true); @@ -3567,7 +3576,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) return; float x, y, z; - float radius = m_spellInfo->Effects[effIndex].CalcRadius(); + float radius = GetEffect(effIndex)->CalcRadius(); for (uint8 i = 0; i < 15; ++i) { m_caster->GetRandomPoint(*destTarget, radius, x, y, z); @@ -3613,8 +3622,9 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex != 0) return; - uint32 spellID = m_spellInfo->Effects[EFFECT_0].CalcValue(); - uint32 questID = m_spellInfo->Effects[EFFECT_1].CalcValue(); + // Effects for 58418 and 58420 are all DIFFICULTY_NONE so always valid + uint32 spellID = GetEffect(EFFECT_0)->CalcValue(); + uint32 questID = GetEffect(EFFECT_1)->CalcValue(); if (unitTarget->ToPlayer()->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE) unitTarget->CastSpell(unitTarget, spellID, true); @@ -3664,7 +3674,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) { /// @todo a hack, range = 11, should after some time cast, otherwise too far m_caster->CastSpell(parent, 62496, true); - unitTarget->CastSpell(parent, m_spellInfo->Effects[EFFECT_0].CalcValue()); + unitTarget->CastSpell(parent, GetEffect(EFFECT_0)->CalcValue()); // DIFFICULTY_NONE, so effect always valid } } } @@ -3856,7 +3866,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex) //CREATE DUEL FLAG OBJECT GameObject* pGameObj = new GameObject; - uint32 gameobject_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 gameobject_id = GetEffect(effIndex)->MiscValue; Map* map = m_caster->GetMap(); if (!pGameObj->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), gameobject_id, @@ -3981,7 +3991,7 @@ void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/) ScriptInfo activateCommand; activateCommand.command = SCRIPT_COMMAND_ACTIVATE_OBJECT; - // int32 unk = m_spellInfo->Effects[effIndex].MiscValue; // This is set for EffectActivateObject spells; needs research + // int32 unk = GetEffect(effIndex)->MiscValue; // This is set for EffectActivateObject spells; needs research gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, 0, m_caster, gameObjTarget); } @@ -4020,7 +4030,7 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex) } // apply new one - if (uint32 newGlyph = m_spellInfo->Effects[effIndex].MiscValue) + if (uint32 newGlyph = GetEffect(effIndex)->MiscValue) { if (GlyphPropertiesEntry const* newGlyphProperties = sGlyphPropertiesStore.LookupEntry(newGlyph)) { @@ -4078,9 +4088,9 @@ void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex) if (!item->IsEquipped()) return; - if (m_spellInfo->Effects[effIndex].MiscValue) + if (GetEffect(effIndex)->MiscValue) { - uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 enchant_id = GetEffect(effIndex)->MiscValue; int32 duration = m_spellInfo->GetDuration(); //Try duration index first .. if (!duration) duration = damage;//+1; //Base points after .. @@ -4174,7 +4184,7 @@ void Spell::EffectFeedPet(SpellEffIndex effIndex) player->DestroyItemCount(foodItem, count, true); /// @todo fix crash when a spell has two effects, both pointed at the same item target - m_caster->CastCustomSpell(pet, m_spellInfo->Effects[effIndex].TriggerSpell, &benefit, NULL, NULL, true); + m_caster->CastCustomSpell(pet, GetEffect(effIndex)->TriggerSpell, &benefit, NULL, NULL, true); } void Spell::EffectDismissPet(SpellEffIndex effIndex) @@ -4196,8 +4206,8 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 go_id = m_spellInfo->Effects[effIndex].MiscValue; - uint8 slot = m_spellInfo->Effects[effIndex].Effect - SPELL_EFFECT_SUMMON_OBJECT_SLOT1; + uint32 go_id = GetEffect(effIndex)->MiscValue; + uint8 slot = GetEffect(effIndex)->Effect - SPELL_EFFECT_SUMMON_OBJECT_SLOT1; ObjectGuid guid = m_caster->m_ObjectSlot[slot]; if (!guid.IsEmpty()) { @@ -4332,7 +4342,7 @@ void Spell::EffectReputation(SpellEffIndex effIndex) int32 repChange = damage; - uint32 factionId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 factionId = GetEffect(effIndex)->MiscValue; FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId); if (!factionEntry) @@ -4352,7 +4362,7 @@ void Spell::EffectQuestComplete(SpellEffIndex effIndex) return; Player* player = unitTarget->ToPlayer(); - uint32 questId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 questId = GetEffect(effIndex)->MiscValue; if (questId) { Quest const* quest = sObjectMgr->GetQuestTemplate(questId); @@ -4396,7 +4406,7 @@ void Spell::EffectSelfResurrect(SpellEffIndex effIndex) if (damage < 0) { health = uint32(-damage); - mana = m_spellInfo->Effects[effIndex].MiscValue; + mana = GetEffect(effIndex)->MiscValue; } // percent case else @@ -4509,13 +4519,13 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex) unitTarget->InterruptNonMeleeSpells(true); float ratio = 0.1f; - float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue) * ratio; + float speedxy = float(GetEffect(effIndex)->MiscValue) * ratio; float speedz = float(damage) * ratio; if (speedxy < 0.1f && speedz < 0.1f) return; float x, y; - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_KNOCK_BACK_DEST) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_KNOCK_BACK_DEST) { if (m_targets.HasDst()) destTarget->GetPosition(x, y); @@ -4538,7 +4548,7 @@ void Spell::EffectLeapBack(SpellEffIndex effIndex) if (!unitTarget) return; - float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue)/10; + float speedxy = float(GetEffect(effIndex)->MiscValue)/10; float speedz = float(damage/10); //1891: Disengage m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellIconID != 1891); @@ -4553,7 +4563,7 @@ void Spell::EffectQuestClear(SpellEffIndex effIndex) return; Player* player = unitTarget->ToPlayer(); - uint32 quest_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 quest_id = GetEffect(effIndex)->MiscValue; Quest const* quest = sObjectMgr->GetQuestTemplate(quest_id); @@ -4595,7 +4605,7 @@ void Spell::EffectSendTaxi(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->ActivateTaxiPathTo(m_spellInfo->Effects[effIndex].MiscValue, m_spellInfo->Id); + unitTarget->ToPlayer()->ActivateTaxiPathTo(GetEffect(effIndex)->MiscValue, m_spellInfo->Id); } void Spell::EffectPullTowards(SpellEffIndex effIndex) @@ -4607,7 +4617,7 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) return; Position pos; - if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_PULL_TOWARDS_DEST) + if (GetEffect(effIndex)->Effect == SPELL_EFFECT_PULL_TOWARDS_DEST) { if (m_targets.HasDst()) pos.Relocate(*destTarget); @@ -4619,7 +4629,7 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) pos.Relocate(m_caster); } - float speedXY = float(m_spellInfo->Effects[effIndex].MiscValue) * 0.1f; + float speedXY = float(GetEffect(effIndex)->MiscValue) * 0.1f; float speedZ = unitTarget->GetDistance(pos) / speedXY * 0.5f * Movement::gravity; unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ); @@ -4633,7 +4643,7 @@ void Spell::EffectDispelMechanic(SpellEffIndex effIndex) if (!unitTarget) return; - uint32 mechanic = m_spellInfo->Effects[effIndex].MiscValue; + uint32 mechanic = GetEffect(effIndex)->MiscValue; DispelList dispel_list; Unit::AuraMap const& auras = unitTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) @@ -4752,7 +4762,7 @@ void Spell::EffectDurabilityDamage(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - int32 slot = m_spellInfo->Effects[effIndex].MiscValue; + int32 slot = GetEffect(effIndex)->MiscValue; // -1 means all player equipped items and -2 all items if (slot < 0) @@ -4781,7 +4791,7 @@ void Spell::EffectDurabilityDamagePCT(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - int32 slot = m_spellInfo->Effects[effIndex].MiscValue; + int32 slot = GetEffect(effIndex)->MiscValue; // FIXME: some spells effects have value -1/-2 // Possibly its mean -1 all player equipped items and -2 all items @@ -4818,7 +4828,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT) return; - uint32 name_id = m_spellInfo->Effects[effIndex].MiscValue; + uint32 name_id = GetEffect(effIndex)->MiscValue; GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id); @@ -4833,9 +4843,9 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (m_targets.HasDst()) destTarget->GetPosition(fx, fy, fz); //FIXME: this can be better check for most objects but still hack - else if (m_spellInfo->Effects[effIndex].HasRadius() && m_spellInfo->Speed == 0) + else if (GetEffect(effIndex)->HasRadius() && m_spellInfo->Speed == 0) { - float dis = m_spellInfo->Effects[effIndex].CalcRadius(m_originalCaster); + float dis = GetEffect(effIndex)->CalcRadius(m_originalCaster); m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis); } else @@ -5057,7 +5067,7 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex) DispelChargesList steal_list; // Create dispel mask by dispel type - uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[effIndex].MiscValue)); + uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(GetEffect(effIndex)->MiscValue)); Unit::AuraMap const& auras = unitTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { @@ -5157,7 +5167,7 @@ void Spell::EffectKillCreditPersonal(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->KilledMonsterCredit(m_spellInfo->Effects[effIndex].MiscValue); + unitTarget->ToPlayer()->KilledMonsterCredit(GetEffect(effIndex)->MiscValue); } void Spell::EffectKillCredit(SpellEffIndex effIndex) @@ -5168,7 +5178,7 @@ void Spell::EffectKillCredit(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - int32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue; + int32 creatureEntry = GetEffect(effIndex)->MiscValue; if (!creatureEntry) { if (m_spellInfo->Id == 42793) // Burn Body @@ -5187,7 +5197,7 @@ void Spell::EffectQuestFail(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->FailQuest(m_spellInfo->Effects[effIndex].MiscValue); + unitTarget->ToPlayer()->FailQuest(GetEffect(effIndex)->MiscValue); } void Spell::EffectQuestStart(SpellEffIndex effIndex) @@ -5202,7 +5212,7 @@ void Spell::EffectQuestStart(SpellEffIndex effIndex) if (!player) return; - if (Quest const* quest = sObjectMgr->GetQuestTemplate(m_spellInfo->Effects[effIndex].MiscValue)) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(GetEffect(effIndex)->MiscValue)) { if (!player->CanTakeQuest(quest, false)) return; @@ -5234,10 +5244,10 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex) if (count == 0) count = 1; for (uint32 j = 0; j < MAX_RUNES && count > 0; ++j) { - if (player->GetRuneCooldown(j) && player->GetCurrentRune(j) == RuneType(m_spellInfo->Effects[effIndex].MiscValue)) + if (player->GetRuneCooldown(j) && player->GetCurrentRune(j) == RuneType(GetEffect(effIndex)->MiscValue)) { if (m_spellInfo->Id == 45529) - if (player->GetBaseRune(j) != RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) + if (player->GetBaseRune(j) != RuneType(GetEffect(effIndex)->MiscValueB)) continue; player->SetRuneCooldown(j, 0); --count; @@ -5250,7 +5260,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex) for (uint32 l = 0; l + 1 < MAX_RUNES && count > 0; ++l) { // Check if both runes are on cd as that is the only time when this needs to come into effect - if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB))) + if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(GetEffect(effIndex)->MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(GetEffect(effIndex)->MiscValueB))) { // Should always update the rune with the lowest cd if (l + 1 < MAX_RUNES && player->GetRuneCooldown(l) >= player->GetRuneCooldown(l+1)) @@ -5288,7 +5298,7 @@ void Spell::EffectCreateTamedPet(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || !unitTarget->GetPetGUID().IsEmpty() || unitTarget->getClass() != CLASS_HUNTER) return; - uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue; + uint32 creatureEntry = GetEffect(effIndex)->MiscValue; Pet* pet = unitTarget->CreateTamedPetFrom(creatureEntry, m_spellInfo->Id); if (!pet) return; @@ -5320,7 +5330,7 @@ void Spell::EffectDiscoverTaxi(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - uint32 nodeid = m_spellInfo->Effects[effIndex].MiscValue; + uint32 nodeid = GetEffect(effIndex)->MiscValue; if (sTaxiNodesStore.LookupEntry(nodeid)) unitTarget->ToPlayer()->GetSession()->SendDiscoverNewTaxiNode(nodeid); } @@ -5382,7 +5392,7 @@ void Spell::EffectGameObjectSetDestructionState(SpellEffIndex effIndex) return; Player* player = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself(); - gameObjTarget->SetDestructibleState(GameObjectDestructibleState(m_spellInfo->Effects[effIndex].MiscValue), player, true); + gameObjTarget->SetDestructibleState(GameObjectDestructibleState(GetEffect(effIndex)->MiscValue), player, true); } void Spell::SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numGuardians) @@ -5472,7 +5482,7 @@ void Spell::EffectPlayMusic(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - uint32 soundid = m_spellInfo->Effects[effIndex].MiscValue; + uint32 soundid = GetEffect(effIndex)->MiscValue; if (!sSoundEntriesStore.LookupEntry(soundid)) { @@ -5529,7 +5539,7 @@ void Spell::EffectPlaySound(SpellEffIndex effIndex) break; } - uint32 soundId = m_spellInfo->Effects[effIndex].MiscValue; + uint32 soundId = GetEffect(effIndex)->MiscValue; if (!sSoundEntriesStore.LookupEntry(soundId)) { @@ -5548,7 +5558,7 @@ void Spell::EffectRemoveAura(SpellEffIndex effIndex) if (!unitTarget) return; // there may be need of specifying casterguid of removed auras - unitTarget->RemoveAurasDueToSpell(m_spellInfo->Effects[effIndex].TriggerSpell); + unitTarget->RemoveAurasDueToSpell(GetEffect(effIndex)->TriggerSpell); } void Spell::EffectDamageFromMaxHealthPCT(SpellEffIndex /*effIndex*/) @@ -5570,7 +5580,7 @@ void Spell::EffectGiveCurrency(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->ToPlayer()->ModifyCurrency(m_spellInfo->Effects[effIndex].MiscValue, damage); + unitTarget->ToPlayer()->ModifyCurrency(GetEffect(effIndex)->MiscValue, damage); } void Spell::EffectCastButtons(SpellEffIndex effIndex) @@ -5582,8 +5592,8 @@ void Spell::EffectCastButtons(SpellEffIndex effIndex) return; Player* p_caster = m_caster->ToPlayer(); - uint32 button_id = m_spellInfo->Effects[effIndex].MiscValue + 132; - uint32 n_buttons = m_spellInfo->Effects[effIndex].MiscValueB; + uint32 button_id = GetEffect(effIndex)->MiscValue + 132; + uint32 n_buttons = GetEffect(effIndex)->MiscValueB; for (; n_buttons; --n_buttons, ++button_id) { @@ -5628,21 +5638,23 @@ void Spell::EffectRechargeManaGem(SpellEffIndex /*effIndex*/) if (!player) return; - - uint32 item_id = m_spellInfo->Effects[EFFECT_0].ItemType; - - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id); - if (!pProto) + if (SpellEffectInfo const* effect = GetEffect(EFFECT_0)) { - player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); - return; - } + uint32 item_id = effect->ItemType; - if (Item* pItem = player->GetItemByEntry(item_id)) - { - for (uint32 x = 0; x < pProto->Effects.size(); ++x) - pItem->SetSpellCharges(x, pProto->Effects[x].Charges); - pItem->SetState(ITEM_CHANGED, player); + ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id); + if (!pProto) + { + player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL); + return; + } + + if (Item* pItem = player->GetItemByEntry(item_id)) + { + for (int x = 0; x < pProto->Effects.size(); ++x) + pItem->SetSpellCharges(x, pProto->Effects[x].Charges); + pItem->SetState(ITEM_CHANGED, player); + } } } @@ -5659,8 +5671,8 @@ void Spell::EffectBind(SpellEffIndex effIndex) WorldLocation homeLoc; uint32 areaId = player->GetAreaId(); - if (m_spellInfo->Effects[effIndex].MiscValue) - areaId = m_spellInfo->Effects[effIndex].MiscValue; + if (GetEffect(effIndex)->MiscValue) + areaId = GetEffect(effIndex)->MiscValue; if (m_targets.HasDst()) homeLoc.WorldRelocate(*destTarget); @@ -5688,7 +5700,7 @@ void Spell::EffectSummonRaFFriend(SpellEffIndex effIndex) if (m_caster->GetTypeId() != TYPEID_PLAYER || !unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - m_caster->CastSpell(unitTarget, m_spellInfo->Effects[effIndex].TriggerSpell, true); + m_caster->CastSpell(unitTarget, GetEffect(effIndex)->TriggerSpell, true); } void Spell::EffectUnlockGuildVaultTab(SpellEffIndex effIndex) @@ -5699,7 +5711,7 @@ void Spell::EffectUnlockGuildVaultTab(SpellEffIndex effIndex) // Safety checks done in Spell::CheckCast Player* caster = m_caster->ToPlayer(); if (Guild* guild = caster->GetGuild()) - guild->HandleBuyBankTab(caster->GetSession(), m_spellInfo->Effects[effIndex].BasePoints - 1); // Bank tabs start at zero internally + guild->HandleBuyBankTab(caster->GetSession(), GetEffect(effIndex)->BasePoints - 1); // Bank tabs start at zero internally } void Spell::EffectResurrectWithAura(SpellEffIndex effIndex) @@ -5723,8 +5735,8 @@ void Spell::EffectResurrectWithAura(SpellEffIndex effIndex) uint32 health = target->CountPctFromMaxHealth(damage); uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), damage); uint32 resurrectAura = 0; - if (sSpellMgr->GetSpellInfo(GetSpellInfo()->Effects[effIndex].TriggerSpell)) - resurrectAura = GetSpellInfo()->Effects[effIndex].TriggerSpell; + if (sSpellMgr->GetSpellInfo(GetEffect(effIndex)->TriggerSpell)) + resurrectAura = GetEffect(effIndex)->TriggerSpell; if (resurrectAura && target->HasAura(resurrectAura)) return; @@ -5746,7 +5758,7 @@ void Spell::EffectCreateAreaTrigger(SpellEffIndex effIndex) pos = destTarget->GetPosition(); // trigger entry/miscvalue relation is currently unknown, for now use MiscValue as trigger entry - uint32 triggerEntry = GetSpellInfo()->Effects[effIndex].MiscValue; + uint32 triggerEntry = GetEffect(effIndex)->MiscValue; AreaTrigger * areaTrigger = new AreaTrigger; if (!areaTrigger->CreateAreaTrigger(sObjectMgr->GetGenerator<HighGuid::AreaTrigger>()->Generate(), triggerEntry, GetCaster(), GetSpellInfo(), pos)) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index ba74ac6841c..b97c169ec7b 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -344,7 +344,7 @@ SpellEffectInfo::SpellEffectInfo(SpellEntry const* /*spellEntry*/, SpellInfo con SpellScalingEntry const* scaling = spellInfo->GetSpellScaling(); _spellInfo = spellInfo; - _effIndex = _effect ? _effect->EffectIndex : effIndex; + EffectIndex = _effect ? _effect->EffectIndex : effIndex; Effect = _effect ? _effect->Effect : 0; ApplyAuraName = _effect ? _effect->EffectAura : 0; ApplyAuraPeriod = _effect ? _effect->EffectAuraPeriod : 0; @@ -369,9 +369,9 @@ SpellEffectInfo::SpellEffectInfo(SpellEntry const* /*spellEntry*/, SpellInfo con SpellClassMask = _effect ? _effect->EffectSpellClassMask : flag128(); ImplicitTargetConditions = NULL; // TODO: 6.x these values are no longer in dbc - ScalingMultiplier = /*scaling ? scaling->Multiplier[_effIndex] :*/ 0.0f; - DeltaScalingMultiplier = /*scaling ? scaling->RandomMultiplier[_effIndex] :*/ 0.0f; - ComboScalingMultiplier = /*scaling ? scaling->OtherMultiplier[_effIndex] :*/ 0.0f; + ScalingMultiplier = /*scaling ? scaling->Multiplier[EffectIndex] :*/ 0.0f; + DeltaScalingMultiplier = /*scaling ? scaling->RandomMultiplier[EffectIndex] :*/ 0.0f; + ComboScalingMultiplier = /*scaling ? scaling->OtherMultiplier[EffectIndex] :*/ 0.0f; } bool SpellEffectInfo::IsEffect() const @@ -379,7 +379,7 @@ bool SpellEffectInfo::IsEffect() const return Effect != 0; } -bool SpellEffectInfo::IsEffect(SpellEffects effectName) const +bool SpellEffectInfo::IsEffect(SpellEffectName effectName) const { return Effect == uint32(effectName); } @@ -442,7 +442,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const if (caster) { int32 level = caster->getLevel(); - if (target && _spellInfo->IsPositiveEffect(_effIndex) && (Effect == SPELL_EFFECT_APPLY_AURA)) + if (target && _spellInfo->IsPositiveEffect(EffectIndex) && (Effect == SPELL_EFFECT_APPLY_AURA)) level = target->getLevel(); if (GtSpellScalingEntry const* gtScaling = sGtSpellScalingStore.LookupEntry((_spellInfo->ScalingClass != -1 ? _spellInfo->ScalingClass - 1 : MAX_CLASSES - 1) * 100 + level - 1)) @@ -509,7 +509,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const if (uint8 comboPoints = caster->m_movedPlayer->GetComboPoints()) value += comboDamage * comboPoints; - value = caster->ApplyEffectModifiers(_spellInfo, _effIndex, value); + value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value); // amount multiplication based on caster's level if (!caster->IsControlledByPlayer() && @@ -849,10 +849,23 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = {EFFECT_IMPLICIT_TARGET_NONE, TARGET_OBJECT_TYPE_UNIT}, // 182 SPELL_EFFECT_182 }; -SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effects) +SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntryMap effects) { Id = spellEntry->ID; + // SpellDifficultyEntry + for (SpellEffectEntryMap::const_iterator itr = effects.begin(); itr != effects.end(); ++itr) + { + _effects[itr->first].resize(MAX_SPELL_EFFECTS); + for (SpellEffectEntryVector::const_iterator i = itr->second.begin(); i != itr->second.end(); ++i) + { + if (!(*i)) + continue; + + _effects[itr->first][(*i)->EffectIndex] = new SpellEffectInfo(spellEntry, this, (*i)->EffectIndex, (*i)); + } + } + SpellName = spellEntry->Name_lang; //Rank = spellEntry->Rank; RuneCostID = spellEntry->RuneCostID; @@ -867,7 +880,6 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effe SpellEquippedItemsId = spellEntry->EquippedItemsID; SpellInterruptsId = spellEntry->InterruptsID; SpellLevelsId = spellEntry->LevelsID; - //SpellPowerId = spellEntry->PowerID; SpellReagentsId = spellEntry->ReagentsID; SpellShapeshiftId = spellEntry->ShapeshiftID; SpellTargetRestrictionsId = spellEntry->TargetRestrictionsID; @@ -903,10 +915,6 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effe SpellIconID = _misc ? _misc->SpellIconID : 0; ActiveIconID = _misc ? _misc->ActiveIconID : 0; - // SpellDifficultyEntry - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - Effects[i] = SpellEffectInfo(spellEntry, this, i, effects[i]); - // SpellScalingEntry SpellScalingEntry const* _scaling = GetSpellScaling(); CastTimeMin = _scaling ? _scaling->CastTimeMin : 0; @@ -1027,58 +1035,99 @@ uint32 SpellInfo::GetCategory() const return CategoryEntry ? CategoryEntry->ID : 0; } -bool SpellInfo::HasEffect(SpellEffects effect) const +bool SpellInfo::HasEffect(uint32 difficulty, SpellEffectName effect) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsEffect(effect)) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* eff : effects) + { + if (eff && eff->IsEffect(effect)) return true; + } return false; } -bool SpellInfo::HasAura(AuraType aura) const +bool SpellInfo::HasEffect(SpellEffectName effect) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsAura(aura)) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* eff : itr->second) + { + if (eff && eff->IsEffect(effect)) + return true; + } + } + return false; +} + +bool SpellInfo::HasAura(uint32 difficulty, AuraType aura) const +{ + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) + { + if (effect && effect->IsAura(aura)) return true; + } return false; } -bool SpellInfo::HasAreaAuraEffect() const +bool SpellInfo::HasAreaAuraEffect(uint32 difficulty) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsAreaAuraEffect()) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) + { + if (effect && effect->IsAreaAuraEffect()) return true; + } + return false; +} + +bool SpellInfo::HasAreaAuraEffect() const +{ + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && effect->IsAreaAuraEffect()) + return true; + } + } return false; } bool SpellInfo::IsExplicitDiscovery() const { - return ((Effects[0].Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM - || Effects[0].Effect == SPELL_EFFECT_CREATE_ITEM_2) - && Effects[1].Effect == SPELL_EFFECT_SCRIPT_EFFECT) + SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0); + SpellEffectInfo const* effect1 = GetEffect(DIFFICULTY_NONE, EFFECT_1); + + return ((effect0 && (effect0->Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || effect0->Effect == SPELL_EFFECT_CREATE_ITEM_2)) + && effect1 && effect1->Effect == SPELL_EFFECT_SCRIPT_EFFECT) || Id == 64323; } bool SpellInfo::IsLootCrafting() const { - return (Effects[0].Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || + SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0); + return effect0 && (effect0->Effect == SPELL_EFFECT_CREATE_RANDOM_ITEM || // different random cards from Inscription (121==Virtuoso Inking Set category) r without explicit item - (Effects[0].Effect == SPELL_EFFECT_CREATE_ITEM_2 && - ((TotemCategory[0] != 0 || (Totem[0] != 0 && SpellIconID == 1)) || Effects[0].ItemType == 0))); + (effect0->Effect == SPELL_EFFECT_CREATE_ITEM_2 && + ((TotemCategory[0] != 0 || (Totem[0] != 0 && SpellIconID == 1)) || effect0->ItemType == 0))); } bool SpellInfo::IsQuestTame() const { - return Effects[0].Effect == SPELL_EFFECT_THREAT && Effects[1].Effect == SPELL_EFFECT_APPLY_AURA && Effects[1].ApplyAuraName == SPELL_AURA_DUMMY; + SpellEffectInfo const* effect0 = GetEffect(DIFFICULTY_NONE, EFFECT_0); + SpellEffectInfo const* effect1 = GetEffect(DIFFICULTY_NONE, EFFECT_1); + return effect0 && effect1 && effect0->Effect == SPELL_EFFECT_THREAT && effect1->Effect == SPELL_EFFECT_APPLY_AURA && effect1->ApplyAuraName == SPELL_AURA_DUMMY; } -bool SpellInfo::IsProfessionOrRiding() const +bool SpellInfo::IsProfessionOrRiding(uint32 difficulty) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) { - if (Effects[i].Effect == SPELL_EFFECT_SKILL) + if ((effect && effect->Effect == SPELL_EFFECT_SKILL)) { - uint32 skill = Effects[i].MiscValue; + uint32 skill = effect->MiscValue; if (IsProfessionOrRidingSkill(skill)) return true; @@ -1087,13 +1136,14 @@ bool SpellInfo::IsProfessionOrRiding() const return false; } -bool SpellInfo::IsProfession() const +bool SpellInfo::IsProfession(uint32 difficulty) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) { - if (Effects[i].Effect == SPELL_EFFECT_SKILL) + if (effect && effect->Effect == SPELL_EFFECT_SKILL) { - uint32 skill = Effects[i].MiscValue; + uint32 skill = effect->MiscValue; if (IsProfessionSkill(skill)) return true; @@ -1102,13 +1152,14 @@ bool SpellInfo::IsProfession() const return false; } -bool SpellInfo::IsPrimaryProfession() const +bool SpellInfo::IsPrimaryProfession(uint32 difficulty) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for(SpellEffectInfo const* effect : effects) { - if (Effects[i].Effect == SPELL_EFFECT_SKILL) + if (effect && effect->Effect == SPELL_EFFECT_SKILL) { - uint32 skill = Effects[i].MiscValue; + uint32 skill = effect->MiscValue; if (IsPrimaryProfessionSkill(skill)) return true; @@ -1117,9 +1168,9 @@ bool SpellInfo::IsPrimaryProfession() const return false; } -bool SpellInfo::IsPrimaryProfessionFirstRank() const +bool SpellInfo::IsPrimaryProfessionFirstRank(uint32 difficulty) const { - return IsPrimaryProfession() && GetRank() == 1; + return IsPrimaryProfession(difficulty) && GetRank() == 1; } bool SpellInfo::IsAbilityLearnedWithProfession() const @@ -1150,20 +1201,26 @@ bool SpellInfo::IsAbilityOfSkillType(uint32 skillType) const return false; } -bool SpellInfo::IsAffectingArea() const +bool SpellInfo::IsAffectingArea(uint32 difficulty) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsEffect() && (Effects[i].IsTargetingArea() || Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || Effects[i].IsAreaAuraEffect())) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) + { + if (effect && effect->IsEffect() && (effect->IsTargetingArea() || effect->IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) || effect->IsAreaAuraEffect())) return true; + } return false; } // checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example) -bool SpellInfo::IsTargetingArea() const +bool SpellInfo::IsTargetingArea(uint32 difficulty) const { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsEffect() && Effects[i].IsTargetingArea()) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) + { + if (effect && effect->IsEffect() && effect->IsTargetingArea()) return true; + } return false; } @@ -1172,7 +1229,7 @@ bool SpellInfo::NeedsExplicitUnitTarget() const return (GetExplicitTargetMask() & TARGET_FLAG_UNIT_MASK) != 0; } -bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const +bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const { if (NeedsExplicitUnitTarget()) return true; @@ -1192,12 +1249,16 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) con if (triggeringSpell->IsChanneled()) { uint32 mask = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + for (SpellEffectInfo const* effect : effects) { - if (Effects[i].TargetA.GetTarget() != TARGET_UNIT_CASTER && Effects[i].TargetA.GetTarget() != TARGET_DEST_CASTER - && Effects[i].TargetB.GetTarget() != TARGET_UNIT_CASTER && Effects[i].TargetB.GetTarget() != TARGET_DEST_CASTER) + if (!effect) + continue; + + if (effect->TargetA.GetTarget() != TARGET_UNIT_CASTER && effect->TargetA.GetTarget() != TARGET_DEST_CASTER + && effect->TargetB.GetTarget() != TARGET_UNIT_CASTER && effect->TargetB.GetTarget() != TARGET_DEST_CASTER) { - mask |= Effects[i].GetProvidedTargetMask(); + mask |= effect->GetProvidedTargetMask(); } } @@ -1235,19 +1296,23 @@ bool SpellInfo::IsStackableWithRanks() const return false; // All stance spells. if any better way, change it. - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + SpellEffectInfoVector effects = GetEffectsForDifficulty(DIFFICULTY_NONE); + for (SpellEffectInfo const* effect : effects) { + if (!effect) + continue; + switch (SpellFamilyName) { case SPELLFAMILY_PALADIN: // Paladin aura Spell - if (Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) + if (effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) return false; break; case SPELLFAMILY_DRUID: // Druid form Spell - if (Effects[i].Effect == SPELL_EFFECT_APPLY_AURA && - Effects[i].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect->Effect == SPELL_EFFECT_APPLY_AURA && + effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) return false; break; } @@ -1255,9 +1320,9 @@ bool SpellInfo::IsStackableWithRanks() const return true; } -bool SpellInfo::IsPassiveStackableWithRanks() const +bool SpellInfo::IsPassiveStackableWithRanks(uint32 difficulty) const { - return IsPassive() && !HasEffect(SPELL_EFFECT_APPLY_AURA); + return IsPassive() && !HasEffect(difficulty, SPELL_EFFECT_APPLY_AURA); } bool SpellInfo::IsMultiSlotAura() const @@ -1637,12 +1702,12 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a // aura limitations if (player) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(player->GetMap()->GetDifficulty())) { - if (!Effects[i].IsAura()) + if (!effect || !effect->IsAura()) continue; - switch (Effects[i].ApplyAuraName) + switch (effect->ApplyAuraName) { case SPELL_AURA_FLY: { @@ -1652,7 +1717,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a } case SPELL_AURA_MOUNTED: { - if (Effects[i].MiscValueB && !player->GetMountCapability(Effects[i].MiscValueB)) + if (effect->MiscValueB && !player->GetMountCapability(effect->MiscValueB)) return SPELL_FAILED_NOT_HERE; break; } @@ -1801,14 +1866,14 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta return SPELL_FAILED_TARGET_AURASTATE; } - if (TargetAuraSpell && !unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(TargetAuraSpell, caster))) + if (TargetAuraSpell && !unitTarget->HasAura(TargetAuraSpell)) return SPELL_FAILED_TARGET_AURASTATE; - if (ExcludeTargetAuraSpell && unitTarget->HasAura(sSpellMgr->GetSpellIdForDifficulty(ExcludeTargetAuraSpell, caster))) + if (ExcludeTargetAuraSpell && unitTarget->HasAura(ExcludeTargetAuraSpell)) return SPELL_FAILED_TARGET_AURASTATE; if (unitTarget->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) - if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW)) + if (HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_SELF_RESURRECT) || HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_RESURRECT) || HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_RESURRECT_NEW)) return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; return SPELL_CAST_OK; @@ -1859,18 +1924,18 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const if (vehicle) { uint16 checkMask = 0; - for (uint8 effIndex = EFFECT_0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) { - if (Effects[effIndex].ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) + if (effect && effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) { - SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(Effects[effIndex].MiscValue); + SpellShapeshiftFormEntry const* shapeShiftFromEntry = sSpellShapeshiftFormStore.LookupEntry(effect->MiscValue); if (shapeShiftFromEntry && (shapeShiftFromEntry->Flags & 1) == 0) // unk flag checkMask |= VEHICLE_SEAT_FLAG_UNCONTROLLED; break; } } - if (HasAura(SPELL_AURA_MOUNTED)) + if (HasAura(caster->GetMap()->GetDifficulty(), SPELL_AURA_MOUNTED)) checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL; if (!checkMask) @@ -1884,12 +1949,12 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const // Can only summon uncontrolled minions/guardians when on controlled vehicle if (vehicleSeat->Flags & (VEHICLE_SEAT_FLAG_CAN_CONTROL | VEHICLE_SEAT_FLAG_UNK2)) { - for (uint32 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) { - if (Effects[i].Effect != SPELL_EFFECT_SUMMON) + if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) continue; - SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(Effects[i].MiscValueB); + SummonPropertiesEntry const* props = sSummonPropertiesStore.LookupEntry(effect->MiscValueB); if (props && props->Category != SUMMON_CATEGORY_WILD) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; } @@ -1929,19 +1994,30 @@ uint32 SpellInfo::GetAllEffectsMechanicMask() const uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsEffect() && Effects[i].Mechanic) - mask |= 1 << Effects[i].Mechanic; + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && effect->IsEffect() && effect->Mechanic) + mask |= 1 << effect->Mechanic; + } + } return mask; } -uint32 SpellInfo::GetEffectMechanicMask(uint8 effIndex) const +uint32 SpellInfo::GetEffectMechanicMask(uint32 effIndex) const { uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - if (Effects[effIndex].IsEffect() && Effects[effIndex].Mechanic) - mask |= 1 << Effects[effIndex].Mechanic; + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && effect->EffectIndex == effIndex && effect->IsEffect() && effect->Mechanic) + mask |= 1 << effect->Mechanic; + } + } return mask; } @@ -1950,28 +2026,34 @@ uint32 SpellInfo::GetSpellMechanicMaskByEffectMask(uint32 effectMask) const uint32 mask = 0; if (Mechanic) mask |= 1 << Mechanic; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if ((effectMask & (1 << i)) && Effects[i].Mechanic) - mask |= 1 << Effects[i].Mechanic; + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) + { + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && (effectMask & (1 << effect->EffectIndex)) && effect->Mechanic) + mask |= 1 << effect->Mechanic; + } + } return mask; } -Mechanics SpellInfo::GetEffectMechanic(uint8 effIndex) const +Mechanics SpellInfo::GetEffectMechanic(uint32 effIndex, uint32 difficulty) const { - if (Effects[effIndex].IsEffect() && Effects[effIndex].Mechanic) - return Mechanics(Effects[effIndex].Mechanic); + SpellEffectInfo const* effect = GetEffect(difficulty, effIndex); + if (effect && effect->IsEffect() && effect->Mechanic) + return Mechanics(effect->Mechanic); if (Mechanic) return Mechanics(Mechanic); return MECHANIC_NONE; } -bool SpellInfo::HasAnyEffectMechanic() const +/*bool SpellInfo::HasAnyEffectMechanic() const { for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (Effects[i].Mechanic) return true; return false; -} +}*/ uint32 SpellInfo::GetDispelMask() const { @@ -1992,7 +2074,7 @@ uint32 SpellInfo::GetExplicitTargetMask() const return ExplicitTargetMask; } -AuraStateType SpellInfo::GetAuraState() const +AuraStateType SpellInfo::GetAuraState(uint32 difficulty) const { // Seals if (GetSpellSpecific() == SPELL_SPECIFIC_SEAL) @@ -2035,10 +2117,10 @@ AuraStateType SpellInfo::GetAuraState() const return AURA_STATE_BLEEDING; if (GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (Effects[i].IsAura() && (Effects[i].ApplyAuraName == SPELL_AURA_MOD_STUN - || Effects[i].ApplyAuraName == SPELL_AURA_MOD_ROOT)) - return AURA_STATE_FROZEN; + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(difficulty)) + if (effect && effect->IsAura() && (effect->ApplyAuraName == SPELL_AURA_MOD_STUN + || effect->ApplyAuraName == SPELL_AURA_MOD_ROOT)) + return AURA_STATE_FROZEN; switch (Id) { @@ -2063,24 +2145,27 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const { bool food = false; bool drink = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (!Effects[i].IsAura()) - continue; - switch (Effects[i].ApplyAuraName) + for (SpellEffectInfo const* effect : itr->second) { - // Food + if (!effect || !effect->IsAura()) + continue; + switch (effect->ApplyAuraName) + { + // Food case SPELL_AURA_MOD_REGEN: case SPELL_AURA_OBS_MOD_HEALTH: food = true; break; - // Drink + // Drink case SPELL_AURA_MOD_POWER_REGEN: case SPELL_AURA_OBS_MOD_POWER: drink = true; break; default: break; + } } } @@ -2120,8 +2205,8 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const // Arcane brillance and Arcane intelect (normal check fails because of flags difference) if (SpellFamilyFlags[0] & 0x400) return SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE; - - if ((SpellFamilyFlags[0] & 0x1000000) && Effects[0].ApplyAuraName == SPELL_AURA_MOD_CONFUSE) + SpellEffectInfo const* effect = GetEffect(DIFFICULTY_NONE, EFFECT_0); + if (effect && (SpellFamilyFlags[0] & 0x1000000) && effect->ApplyAuraName == SPELL_AURA_MOD_CONFUSE) return SPELL_SPECIFIC_MAGE_POLYMORPH; break; @@ -2207,12 +2292,14 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const break; } - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) + for (SpellEffectInfo const* effect : itr->second) { - switch (Effects[i].ApplyAuraName) + if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) { + switch (effect->ApplyAuraName) + { case SPELL_AURA_MOD_CHARM: case SPELL_AURA_MOD_POSSESS_PET: case SPELL_AURA_MOD_POSSESS: @@ -2225,10 +2312,10 @@ SpellSpecificType SpellInfo::GetSpellSpecific() const case SPELL_AURA_TRACK_RESOURCES: case SPELL_AURA_TRACK_STEALTHED: return SPELL_SPECIFIC_TRACKER; + } } } } - return SPELL_SPECIFIC_NORMAL; } @@ -2298,7 +2385,7 @@ uint32 SpellInfo::CalcCastTime(uint8 level, Spell* spell /*= NULL*/) const return (castTime > 0) ? uint32(castTime) : 0; } -uint32 SpellInfo::GetMaxTicks() const +uint32 SpellInfo::GetMaxTicks(uint32 difficulty) const { int32 DotDuration = GetDuration(); if (DotDuration == 0) @@ -2308,16 +2395,16 @@ uint32 SpellInfo::GetMaxTicks() const if (DotDuration > 30000) DotDuration = 30000; - for (uint8 x = 0; x < MAX_SPELL_EFFECTS; x++) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(difficulty)) { - if (Effects[x].Effect == SPELL_EFFECT_APPLY_AURA) - switch (Effects[x].ApplyAuraName) + if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) + switch (effect->ApplyAuraName) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_HEAL: case SPELL_AURA_PERIODIC_LEECH: - if (Effects[x].ApplyAuraPeriod != 0) - return DotDuration / Effects[x].ApplyAuraPeriod; + if (effect->ApplyAuraPeriod != 0) + return DotDuration / effect->ApplyAuraPeriod; break; } } @@ -2479,13 +2566,13 @@ SpellInfo const* SpellInfo::GetAuraRankForLevel(uint8 level) const return this; bool needRankSelection = false; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (IsPositiveEffect(i) && - (Effects[i].Effect == SPELL_EFFECT_APPLY_AURA || - Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || - Effects[i].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && - !Effects[i].ScalingMultiplier) + if (effect && IsPositiveEffect(effect->Effect) && + (effect->Effect == SPELL_EFFECT_APPLY_AURA || + effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect->Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID) && + !effect->ScalingMultiplier) { needRankSelection = true; break; @@ -2537,32 +2624,35 @@ void SpellInfo::_InitializeExplicitTargetMask() bool dstSet = false; uint32 targetMask = Targets; // prepare target mask using effect target entries - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (!Effects[i].IsEffect()) - continue; + for (SpellEffectInfo const* effect : itr->second) + { + if (!effect || !effect->IsEffect()) + continue; - targetMask |= Effects[i].TargetA.GetExplicitTargetMask(srcSet, dstSet); - targetMask |= Effects[i].TargetB.GetExplicitTargetMask(srcSet, dstSet); + targetMask |= effect->TargetA.GetExplicitTargetMask(srcSet, dstSet); + targetMask |= effect->TargetB.GetExplicitTargetMask(srcSet, dstSet); - // add explicit target flags based on spell effects which have EFFECT_IMPLICIT_TARGET_EXPLICIT and no valid target provided - if (Effects[i].GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) - continue; + // add explicit target flags based on spell effects which have EFFECT_IMPLICIT_TARGET_EXPLICIT and no valid target provided + if (effect->GetImplicitTargetType() != EFFECT_IMPLICIT_TARGET_EXPLICIT) + continue; - // extend explicit target mask only if valid targets for effect could not be provided by target types - uint32 effectTargetMask = Effects[i].GetMissingTargetMask(srcSet, dstSet, targetMask); + // extend explicit target mask only if valid targets for effect could not be provided by target types + uint32 effectTargetMask = effect->GetMissingTargetMask(srcSet, dstSet, targetMask); - // don't add explicit object/dest flags when spell has no max range - if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f) - effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION); + // don't add explicit object/dest flags when spell has no max range + if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f) + effectTargetMask &= ~(TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_DEST_LOCATION); - targetMask |= effectTargetMask; + targetMask |= effectTargetMask; + } } ExplicitTargetMask = targetMask; } -bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const +bool SpellInfo::_IsPositiveEffect(uint32 effIndex, bool deep) const { // not found a single positive spell with this attribute if (Attributes & SPELL_ATTR0_NEGATIVE_1) @@ -2627,40 +2717,50 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const } // Special case: effects which determine positivity of whole spell - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - if (Effects[i].IsAura() && Effects[i].ApplyAuraName == SPELL_AURA_MOD_STEALTH) - return true; + for (SpellEffectInfo const* effect : itr->second) + { + if (effect && effect->IsAura() && effect->ApplyAuraName == SPELL_AURA_MOD_STEALTH) + return true; + } } - switch (Effects[effIndex].Effect) + for (SpellEffectInfoMap::const_iterator itr = _effects.begin(); itr != _effects.end(); ++itr) { - case SPELL_EFFECT_DUMMY: - // some explicitly required dummy effect sets - switch (Id) + for (SpellEffectInfo const* effect : itr->second) + { + if (!effect || effect->EffectIndex != effIndex) + continue; + + switch (effect->Effect) { + case SPELL_EFFECT_DUMMY: + // some explicitly required dummy effect sets + switch (Id) + { case 28441: return false; // AB Effect 000 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: - case SPELL_EFFECT_HEAL_PCT: - case SPELL_EFFECT_ENERGIZE_PCT: - return true; - case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: - return false; + } + 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: + case SPELL_EFFECT_HEAL_PCT: + case SPELL_EFFECT_ENERGIZE_PCT: + return true; + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: + return false; - // non-positive aura use - case SPELL_EFFECT_APPLY_AURA: - case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: - { - switch (Effects[effIndex].ApplyAuraName) + // non-positive aura use + case SPELL_EFFECT_APPLY_AURA: + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: { + switch (effect->ApplyAuraName) + { case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from bas point sign (negative -> negative) case SPELL_AURA_MOD_STAT: case SPELL_AURA_MOD_SKILL: @@ -2668,16 +2768,16 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_MOD_HEALING_PCT: case SPELL_AURA_MOD_HEALING_DONE: case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: - if (Effects[effIndex].CalcValue() < 0) + if (effect->CalcValue() < 0) return false; break; case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from bas point sign (positive -> negative) - if (Effects[effIndex].CalcValue() > 0) + if (effect->CalcValue() > 0) return false; break; case SPELL_AURA_MOD_CRIT_PCT: case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: - if (Effects[effIndex].CalcValue() > 0) + if (effect->CalcValue() > 0) return true; // some expected positive spells have SPELL_ATTR1_NEGATIVE break; case SPELL_AURA_ADD_TARGET_TRIGGER: @@ -2686,17 +2786,20 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_PERIODIC_TRIGGER_SPELL: if (!deep) { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(Effects[effIndex].TriggerSpell)) + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell)) { // negative targets of main spell return early - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfoMap::const_iterator it = spellTriggeredProto->_effects.begin(); it != spellTriggeredProto->_effects.end(); ++it) { - if (!spellTriggeredProto->Effects[i].Effect) - continue; - // if non-positive trigger cast targeted to positive target this main cast is non-positive - // this will place this spell auras as debuffs - if (_IsPositiveTarget(spellTriggeredProto->Effects[i].TargetA.GetTarget(), spellTriggeredProto->Effects[i].TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(i, true)) - return false; + for (SpellEffectInfo const* eff : itr->second) + { + if (!eff || !eff->Effect) + continue; + // if non-positive trigger cast targeted to positive target this main cast is non-positive + // this will place this spell auras as debuffs + if (_IsPositiveTarget(eff->TargetA.GetTarget(), eff->TargetB.GetTarget()) && !spellTriggeredProto->_IsPositiveEffect(eff->EffectIndex, true)) + return false; + } } } } @@ -2704,9 +2807,23 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const // 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 == 0 && Effects[1].Effect == 0 && Effects[2].Effect == 0) + { + bool more = false; + for (SpellEffectInfoMap::const_iterator i = _effects.begin(); i != _effects.end(); ++i) + { + for (SpellEffectInfo const* eff : i->second) + { + if (eff && eff->EffectIndex != 0) + { + more = true; + break; + } + } + } + if (effIndex == 0 && !more) return false; // but all single stun aura spells is negative break; + } case SPELL_AURA_MOD_PACIFY_SILENCE: if (Id == 24740) // Wisp Costume return true; @@ -2721,12 +2838,12 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const return false; case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. // part of negative spell if cast at self (prevent cancel) - if (Effects[effIndex].TargetA.GetTarget() == TARGET_UNIT_CASTER) + if (effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) return false; break; case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also // part of positive spell if cast at self - if (Effects[effIndex].TargetA.GetTarget() != TARGET_UNIT_CASTER) + if (effect->TargetA.GetTarget() != TARGET_UNIT_CASTER) return false; // but not this if this first effect (didn't find better check) if (Attributes & SPELL_ATTR0_NEGATIVE_1 && effIndex == 0) @@ -2735,7 +2852,7 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_MECHANIC_IMMUNITY: { // non-positive immunities - switch (Effects[effIndex].MiscValue) + switch (effect->MiscValue) { case MECHANIC_BANDAGE: case MECHANIC_SHIELD: @@ -2751,10 +2868,10 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_ADD_PCT_MODIFIER: { // non-positive mods - switch (Effects[effIndex].MiscValue) + switch (effect->MiscValue) { case SPELLMOD_COST: // dependent from bas point sign (negative -> positive) - if (Effects[effIndex].CalcValue() > 0) + if (effect->CalcValue() > 0) { if (!deep) { @@ -2780,25 +2897,26 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const } default: break; + } + break; + } + default: + break; } - break; - } - default: - break; - } - - // non-positive targets - if (!_IsPositiveTarget(Effects[effIndex].TargetA.GetTarget(), Effects[effIndex].TargetB.GetTarget())) - return false; - // negative spell if triggered spell is negative - if (!deep && !Effects[effIndex].ApplyAuraName && Effects[effIndex].TriggerSpell) - { - if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(Effects[effIndex].TriggerSpell)) - if (!spellTriggeredProto->_IsPositiveSpell()) + // non-positive targets + if (!_IsPositiveTarget(effect->TargetA.GetTarget(), effect->TargetB.GetTarget())) return false; - } + // negative spell if triggered spell is negative + if (!deep && !effect->ApplyAuraName && effect->TriggerSpell) + { + if (SpellInfo const* spellTriggeredProto = sSpellMgr->GetSpellInfo(effect->TriggerSpell)) + if (!spellTriggeredProto->_IsPositiveSpell()) + return false; + } + } + } // ok, positive return true; } @@ -2857,7 +2975,10 @@ SpellLevelsEntry const* SpellInfo::GetSpellLevels() const SpellPowerEntry const* SpellInfo::GetSpellPower() const { - return SpellPowerId ? sSpellPowerStore.LookupEntry(SpellPowerId) : NULL; + auto itr = sSpellPowerBySpellIDStore.find(Id); + if (itr != sSpellPowerBySpellIDStore.end()) + return itr->second; + return NULL; } SpellReagentsEntry const* SpellInfo::GetSpellReagents() const @@ -2918,16 +3039,64 @@ SpellCooldownsEntry const* SpellInfo::GetSpellCooldowns() const void SpellInfo::_UnloadImplicitTargetConditionLists() { // find the same instances of ConditionList and delete them. - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint32 d = 0; d < DIFFICULTY_MAX; ++d) { - ConditionList* cur = Effects[i].ImplicitTargetConditions; - if (!cur) - continue; - for (uint8 j = i; j < MAX_SPELL_EFFECTS; ++j) + for (uint32 i = 0; i < _effects.size(); ++i) + { + if (SpellEffectInfo const* effect = GetEffect(d, i)) + { + ConditionList* cur = effect->ImplicitTargetConditions; + if (!cur) + continue; + for (uint8 j = i; j < _effects.size(); ++j) + { + if (SpellEffectInfo const* eff = GetEffect(d, j)) + { + if (eff->ImplicitTargetConditions == cur) + const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = NULL; + } + } + delete cur; + } + } + } +} + +SpellEffectInfoVector SpellInfo::GetEffectsForDifficulty(uint32 difficulty) const +{ + SpellEffectInfoVector effList; + + // DIFFICULTY_NONE effects are the default effects, always active if current difficulty's effects don't overwrite + SpellEffectInfoMap::const_iterator itr = _effects.find(DIFFICULTY_NONE); + if (itr != _effects.end()) + effList = itr->second; + + // downscale difficulty if original was not found + // DIFFICULTY_NONE is already in our list + for (; difficulty > DIFFICULTY_NONE; --difficulty) + { + SpellEffectInfoMap::const_iterator itr = _effects.find(difficulty); + if (itr != _effects.end()) { - if (Effects[j].ImplicitTargetConditions == cur) - Effects[j].ImplicitTargetConditions = NULL; + for (SpellEffectInfo const* effect : itr->second) + { + // overwrite any existing effect from DIFFICULTY_NONE + effList[effect->EffectIndex] = effect; + } + // if we found any effect in our difficulty then stop searching + break; } - delete cur; } + if (effList.empty()) + TC_LOG_ERROR("spells", "GetEffectsForDifficulty did not find any effects for spell %u in difficulty %u", Id, difficulty); + return effList; +} + +SpellEffectInfo const* SpellInfo::GetEffect(uint32 difficulty, uint32 index) const +{ + SpellEffectInfoVector effects = GetEffectsForDifficulty(difficulty); + if (index >= effects.size()) + return nullptr; + + return effects[index]; } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 753a6c8d63c..d787fc8b44e 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -65,6 +65,11 @@ enum SpellCastTargetFlags TARGET_FLAG_DEST_TARGET = 0x00040000, // sometimes appears with DEST_TARGET spells (may appear or not for a given spell) TARGET_FLAG_EXTRA_TARGETS = 0x00080000, // uint32 counter, loop { vec3 - screen position (?), guid }, not used so far TARGET_FLAG_UNIT_PASSENGER = 0x00100000, // guessed, used to validate target (if vehicle passenger) + TARGET_FLAG_UNK400000 = 0X00400000, + TARGET_FLAG_UNK1000000 = 0X01000000, + TARGET_FLAG_UNK4000000 = 0X04000000, + TARGET_FLAG_UNK10000000 = 0X10000000, + TARGET_FLAG_UNK40000000 = 0X40000000, TARGET_FLAG_UNIT_MASK = TARGET_FLAG_UNIT | TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ENEMY | TARGET_FLAG_UNIT_ALLY | TARGET_FLAG_UNIT_DEAD | TARGET_FLAG_UNIT_MINIPET | TARGET_FLAG_UNIT_PASSENGER, @@ -230,8 +235,8 @@ private: class SpellEffectInfo { SpellInfo const* _spellInfo; - uint8 _effIndex; public: + uint32 EffectIndex; uint32 Effect; uint32 ApplyAuraName; uint32 ApplyAuraPeriod; @@ -260,14 +265,14 @@ public: float DeltaScalingMultiplier; float ComboScalingMultiplier; - SpellEffectInfo() : _spellInfo(NULL), _effIndex(0), Effect(0), ApplyAuraName(0), ApplyAuraPeriod(0), DieSides(0), + SpellEffectInfo() : _spellInfo(NULL), EffectIndex(0), Effect(0), ApplyAuraName(0), ApplyAuraPeriod(0), DieSides(0), RealPointsPerLevel(0), BasePoints(0), PointsPerResource(0), Amplitude(0), ChainAmplitude(0), BonusCoefficient(0), MiscValue(0), MiscValueB(0), Mechanic(MECHANIC_NONE), PositionFacing(0), RadiusEntry(NULL), ChainTargets(0), ItemType(0), TriggerSpell(0), ImplicitTargetConditions(NULL) { } SpellEffectInfo(SpellEntry const* spellEntry, SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* effect); bool IsEffect() const; - bool IsEffect(SpellEffects effectName) const; + bool IsEffect(SpellEffectName effectName) const; bool IsAura() const; bool IsAura(AuraType aura) const; bool IsTargetingArea() const; @@ -300,6 +305,14 @@ private: static StaticData _data[TOTAL_SPELL_EFFECTS]; }; +typedef std::vector<SpellEffectInfo const*> SpellEffectInfoVector; +typedef std::unordered_map<uint32, SpellEffectInfoVector> SpellEffectInfoMap; + +typedef std::vector<SpellEffectEntry const*> SpellEffectEntryVector; +typedef std::unordered_map<uint32, SpellEffectEntryVector> SpellEffectEntryMap; + +typedef std::vector<AuraEffect*> AuraEffectVector; + class SpellInfo { public: @@ -391,7 +404,6 @@ public: uint32 SpellEquippedItemsId; uint32 SpellInterruptsId; uint32 SpellLevelsId; - uint32 SpellPowerId; uint32 SpellReagentsId; uint32 SpellShapeshiftId; uint32 SpellTargetRestrictionsId; @@ -404,7 +416,6 @@ public: int32 ScalingClass; float CoefBase; int32 CoefLevelBase; - SpellEffectInfo Effects[MAX_SPELL_EFFECTS]; uint32 ExplicitTargetMask; SpellChainNode const* ChainEntry; @@ -426,33 +437,35 @@ public: SpellTotemsEntry const* GetSpellTotems() const; SpellMiscEntry const* GetSpellMisc() const; - SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effects); + SpellInfo(SpellEntry const* spellEntry, SpellEffectEntryMap effects); ~SpellInfo(); uint32 GetCategory() const; - bool HasEffect(SpellEffects effect) const; - bool HasAura(AuraType aura) const; + bool HasEffect(uint32 difficulty, SpellEffectName effect) const; + bool HasEffect(SpellEffectName effect) const; + bool HasAura(uint32 difficulty, AuraType aura) const; + bool HasAreaAuraEffect(uint32 difficulty) const; bool HasAreaAuraEffect() const; bool IsExplicitDiscovery() const; bool IsLootCrafting() const; bool IsQuestTame() const; - bool IsProfessionOrRiding() const; - bool IsProfession() const; - bool IsPrimaryProfession() const; - bool IsPrimaryProfessionFirstRank() const; + bool IsProfessionOrRiding(uint32 difficulty = DIFFICULTY_NONE) const; + bool IsProfession(uint32 difficulty = DIFFICULTY_NONE) const; + bool IsPrimaryProfession(uint32 difficulty = DIFFICULTY_NONE) const; + bool IsPrimaryProfessionFirstRank(uint32 difficulty = DIFFICULTY_NONE) const; bool IsAbilityLearnedWithProfession() const; bool IsAbilityOfSkillType(uint32 skillType) const; - bool IsAffectingArea() const; - bool IsTargetingArea() const; + bool IsAffectingArea(uint32 difficulty) const; + bool IsTargetingArea(uint32 difficulty) const; bool NeedsExplicitUnitTarget() const; - bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const; + bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const; bool IsPassive() const; bool IsAutocastable() const; bool IsStackableWithRanks() const; - bool IsPassiveStackableWithRanks() const; + bool IsPassiveStackableWithRanks(uint32 difficulty) const; bool IsMultiSlotAura() const; bool IsStackableOnOneSlotWithDifferentCasters() const; bool IsCooldownStartedOnEvent() const; @@ -487,15 +500,15 @@ public: SpellSchoolMask GetSchoolMask() const; uint32 GetAllEffectsMechanicMask() const; - uint32 GetEffectMechanicMask(uint8 effIndex) const; + uint32 GetEffectMechanicMask(uint32 effIndex) const; uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; - Mechanics GetEffectMechanic(uint8 effIndex) const; - bool HasAnyEffectMechanic() const; + Mechanics GetEffectMechanic(uint32 effIndex, uint32 difficulty) const; + //bool HasAnyEffectMechanic() const; uint32 GetDispelMask() const; static uint32 GetDispelMask(DispelType type); uint32 GetExplicitTargetMask() const; - AuraStateType GetAuraState() const; + AuraStateType GetAuraState(uint32 difficulty) const; SpellSpecificType GetSpellSpecific() const; float GetMinRange(bool positive = false) const; @@ -504,7 +517,7 @@ public: int32 GetDuration() const; int32 GetMaxDuration() const; - uint32 GetMaxTicks() const; + uint32 GetMaxTicks(uint32 difficulty) const; uint32 CalcCastTime(uint8 level = 0, Spell* spell = NULL) const; uint32 GetRecoveryTime() const; @@ -524,12 +537,19 @@ public: // loading helpers void _InitializeExplicitTargetMask(); - bool _IsPositiveEffect(uint8 effIndex, bool deep) const; + bool _IsPositiveEffect(uint32 effIndex, bool deep) const; bool _IsPositiveSpell() const; static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); // unloading helpers void _UnloadImplicitTargetConditionLists(); + + SpellEffectInfoVector GetEffectsForDifficulty(uint32 difficulty) const; + SpellEffectInfo const* GetEffect(uint32 difficulty, uint32 index) const; + SpellEffectInfo const* GetEffect(uint32 index) const { return GetEffect(DIFFICULTY_NONE, index); } + SpellEffectInfo const* GetEffect(WorldObject* obj, uint32 index) const { return GetEffect(obj->GetMap()->GetDifficulty(), index); } + + SpellEffectInfoMap _effects; }; #endif // _SPELLINFO_H diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 43307ab1a9b..4ba129b4946 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -59,9 +59,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, if (spellproto->IsPositive()) return DIMINISHING_NONE; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect: spellproto->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellproto->Effects[i].ApplyAuraName == SPELL_AURA_MOD_TAUNT) + if (effect && effect->ApplyAuraName == SPELL_AURA_MOD_TAUNT) return DIMINISHING_TAUNT; } @@ -370,9 +370,12 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg bool needCheckReagents = false; // check effects - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - switch (spellInfo->Effects[i].Effect) + if (!effect) + continue; + + switch (effect->Effect) { case 0: continue; @@ -381,7 +384,7 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_CREATE_ITEM_2: { - if (spellInfo->Effects[i].ItemType == 0) + if (effect->ItemType == 0) { // skip auto-loot crafting spells, its not need explicit item info (but have special fake items sometime) if (!spellInfo->IsLootCrafting()) @@ -398,14 +401,14 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg } // also possible IsLootCrafting case but fake item must exist anyway - else if (!sObjectMgr->GetItemTemplate(spellInfo->Effects[i].ItemType)) + else if (!sObjectMgr->GetItemTemplate(effect->ItemType)) { if (msg) { if (player) - ChatHandler(player->GetSession()).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...", spellInfo->Id, spellInfo->Effects[i].ItemType); + ChatHandler(player->GetSession()).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...", spellInfo->Id, effect->ItemType); else - TC_LOG_ERROR("sql.sql", "Craft spell %u create not-exist in DB item (Entry: %u) and then...", spellInfo->Id, spellInfo->Effects[i].ItemType); + TC_LOG_ERROR("sql.sql", "Craft spell %u create not-exist in DB item (Entry: %u) and then...", spellInfo->Id, effect->ItemType); } return false; } @@ -415,15 +418,15 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg } case SPELL_EFFECT_LEARN_SPELL: { - SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(spellInfo->Effects[i].TriggerSpell); + SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(effect->TriggerSpell); if (!IsSpellValid(spellInfo2, player, msg)) { if (msg) { if (player) - ChatHandler(player->GetSession()).PSendSysMessage("Spell %u learn to broken spell %u, and then...", spellInfo->Id, spellInfo->Effects[i].TriggerSpell); + ChatHandler(player->GetSession()).PSendSysMessage("Spell %u learn to broken spell %u, and then...", spellInfo->Id, effect->TriggerSpell); else - TC_LOG_ERROR("sql.sql", "Spell %u learn to invalid spell %u, and then...", spellInfo->Id, spellInfo->Effects[i].TriggerSpell); + TC_LOG_ERROR("sql.sql", "Spell %u learn to invalid spell %u, and then...", spellInfo->Id, effect->TriggerSpell); } return false; } @@ -453,81 +456,6 @@ bool SpellMgr::IsSpellValid(SpellInfo const* spellInfo, Player* player, bool msg return true; } -uint32 SpellMgr::GetSpellDifficultyId(uint32 spellId) const -{ - SpellDifficultySearcherMap::const_iterator i = mSpellDifficultySearcherMap.find(spellId); - return i == mSpellDifficultySearcherMap.end() ? 0 : i->second; -} - -void SpellMgr::SetSpellDifficultyId(uint32 spellId, uint32 id) -{ - if (uint32 i = GetSpellDifficultyId(spellId)) - TC_LOG_ERROR("spells", "SpellMgr::SetSpellDifficultyId: Spell %u has already spellDifficultyId %u. Will override with spellDifficultyId %u.", spellId, i, id); - mSpellDifficultySearcherMap[spellId] = id; -} - -// TODO: 6.x adapt to new spell diff system -uint32 SpellMgr::GetSpellIdForDifficulty(uint32 spellId, Unit const* caster) const -{ - /*if (!GetSpellInfo(spellId)) - return spellId; - - if (!caster || !caster->GetMap() || !caster->GetMap()->IsDungeon()) - return spellId; - - uint32 mode = uint32(caster->GetMap()->GetSpawnMode()); - if (mode >= MAX_DIFFICULTY) - { - TC_LOG_ERROR("spells", "SpellMgr::GetSpellIdForDifficulty: Incorrect Difficulty for spell %u.", spellId); - return spellId; //return source spell - } - - uint32 difficultyId = GetSpellDifficultyId(spellId); - if (!difficultyId) - return spellId; //return source spell, it has only REGULAR_DIFFICULTY - - SpellDifficultyEntry const* difficultyEntry = sSpellDifficultyStore.LookupEntry(difficultyId); - if (!difficultyEntry) - { - TC_LOG_ERROR("spells", "SpellMgr::GetSpellIdForDifficulty: SpellDifficultyEntry not found for spell %u. This should never happen.", spellId); - return spellId; //return source spell - } - - if (difficultyEntry->SpellID[mode] <= 0 && mode > DUNGEON_DIFFICULTY_HEROIC) - { - TC_LOG_DEBUG("spells", "SpellMgr::GetSpellIdForDifficulty: spell %u mode %u spell is NULL, using mode %u", spellId, mode, mode - 2); - mode -= 2; - } - - if (difficultyEntry->SpellID[mode] <= 0) - { - TC_LOG_ERROR("sql.sql", "SpellMgr::GetSpellIdForDifficulty: spell %u mode %u spell is 0. Check spelldifficulty_dbc!", spellId, mode); - return spellId; - } - - TC_LOG_DEBUG("spells", "SpellMgr::GetSpellIdForDifficulty: spellid for spell %u in mode %u is %d", spellId, mode, difficultyEntry->SpellID[mode]); - return uint32(difficultyEntry->SpellID[mode]); - */ - return 0; -} - -SpellInfo const* SpellMgr::GetSpellForDifficultyFromSpell(SpellInfo const* spell, Unit const* caster) const -{ - if (!spell) - return NULL; - - uint32 newSpellId = GetSpellIdForDifficulty(spell->Id, caster); - SpellInfo const* newSpell = GetSpellInfo(newSpellId); - if (!newSpell) - { - TC_LOG_DEBUG("spells", "SpellMgr::GetSpellForDifficultyFromSpell: spell %u not found. Check spelldifficulty_dbc!", newSpellId); - return spell; - } - - TC_LOG_DEBUG("spells", "SpellMgr::GetSpellForDifficultyFromSpell: Spell id for instance mode is %u (original %u)", newSpell->Id, spell->Id); - return newSpell; -} - SpellChainNode const* SpellMgr::GetSpellChainNode(uint32 spell_id) const { SpellChainMap::const_iterator itr = mSpellChains.find(spell_id); @@ -1479,13 +1407,13 @@ void SpellMgr::LoadSpellLearnSkills() if (!entry) continue; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : entry->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (entry->Effects[i].Effect == SPELL_EFFECT_SKILL) + if (effect && effect->Effect == SPELL_EFFECT_SKILL) { SpellLearnSkillNode dbc_node; - dbc_node.skill = entry->Effects[i].MiscValue; - dbc_node.step = entry->Effects[i].CalcValue(); + dbc_node.skill = effect->MiscValue; + dbc_node.step = effect->CalcValue(); if (dbc_node.skill != SKILL_RIDING) dbc_node.value = 1; else @@ -1562,12 +1490,12 @@ void SpellMgr::LoadSpellLearnSpells() if (!entry) continue; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (SpellEffectInfo const* effect : entry->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (entry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL) + if (effect && effect->Effect == SPELL_EFFECT_LEARN_SPELL) { SpellLearnSpellNode dbc_node; - dbc_node.spell = entry->Effects[i].TriggerSpell; + dbc_node.spell = effect->TriggerSpell; dbc_node.active = true; // all dbc based learned spells is active (show in spell book or hide by client itself) // ignore learning not existed spells (broken/outdated/or generic learnig spell 483 @@ -1577,7 +1505,7 @@ void SpellMgr::LoadSpellLearnSpells() // talent or passive spells or skill-step spells auto-cast and not need dependent learning, // pet teaching spells must not be dependent learning (cast) // other required explicit dependent learning - dbc_node.autoLearned = entry->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentBySpellID(spell) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); + dbc_node.autoLearned = effect->TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentBySpellID(spell) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spell); @@ -1715,13 +1643,26 @@ void SpellMgr::LoadSpellTargetPositions() continue; } + SpellEffectInfo const* effect = spellInfo->GetEffect(effIndex); + if (!effect) + { + TC_LOG_ERROR("sql.sql", "Spell (Id: %u, effIndex: %u) listed in `spell_target_position` does not have an effect at index %u.", Spell_ID, effIndex, effIndex); + continue; + } + // target facing is in degrees for 6484 & 9268... (blizz sucks) - if (spellInfo->Effects[effIndex].PositionFacing > 2 * M_PI) - st.target_Orientation = spellInfo->Effects[effIndex].PositionFacing * M_PI / 180; + if (effect->PositionFacing > 2 * M_PI) + st.target_Orientation = effect->PositionFacing * M_PI / 180; else - st.target_Orientation = spellInfo->Effects[effIndex].PositionFacing; + st.target_Orientation = effect->PositionFacing; + + if (effect->TargetA.GetTarget() == TARGET_DEST_DB || effect->TargetB.GetTarget() == TARGET_DEST_DB) + { + TC_LOG_ERROR("sql.sql", "Spell (Id: %u, effIndex: %u) listed in `spell_target_position` does not have TARGET_DEST_DB as target at index %u.", Spell_ID, effIndex, effIndex); + continue; + } - if (spellInfo->Effects[effIndex].TargetA.GetTarget() == TARGET_DEST_DB || spellInfo->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DB) + if (effect->TargetA.GetTarget() == TARGET_DEST_DB || effect->TargetB.GetTarget() == TARGET_DEST_DB) { std::pair<uint32, SpellEffIndex> key = std::make_pair(Spell_ID, effIndex); mSpellTargetPositions[key] = st; @@ -2260,9 +2201,16 @@ void SpellMgr::LoadSpellPetAuras() TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_pet_auras` does not exist", spell); continue; } - if (spellInfo->Effects[eff].Effect != SPELL_EFFECT_DUMMY && - (spellInfo->Effects[eff].Effect != SPELL_EFFECT_APPLY_AURA || - spellInfo->Effects[eff].ApplyAuraName != SPELL_AURA_DUMMY)) + SpellEffectInfo const* effect = spellInfo->GetEffect(eff); + if (!effect) + { + TC_LOG_ERROR("spells", "Spell %u listed in `spell_pet_auras` does not have effect at index %u", spell, uint32(eff)); + continue; + } + + if (effect->Effect != SPELL_EFFECT_DUMMY && + (effect->Effect != SPELL_EFFECT_APPLY_AURA || + effect->ApplyAuraName != SPELL_AURA_DUMMY)) { TC_LOG_ERROR("spells", "Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect", spell); continue; @@ -2275,7 +2223,7 @@ void SpellMgr::LoadSpellPetAuras() continue; } - PetAura pa(pet, aura, spellInfo->Effects[eff].TargetA.GetTarget() == TARGET_UNIT_PET, spellInfo->Effects[eff].CalcValue()); + PetAura pa(pet, aura, effect->TargetA.GetTarget() == TARGET_UNIT_PET, effect->CalcValue()); mSpellPetAuraMap[(spell<<8) + eff] = pa; } @@ -2307,11 +2255,11 @@ void SpellMgr::LoadEnchantCustomAttr() if (!(spellInfo->AttributesEx2 & SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !(spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT)) continue; - for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellInfo->Effects[j].Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) + if (effect && effect->Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) { - uint32 enchId = spellInfo->Effects[j].MiscValue; + uint32 enchId = effect->MiscValue; SpellItemEnchantmentEntry const* ench = sSpellItemEnchantmentStore.LookupEntry(enchId); if (!ench) continue; @@ -2398,10 +2346,10 @@ void SpellMgr::LoadSpellLinked() } if (effect >= 0) - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* eff : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellInfo->Effects[j].CalcValue() == abs(effect)) - TC_LOG_ERROR("sql.sql", "Spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack)", abs(trigger), abs(effect), j); + if (eff && eff->CalcValue() == abs(effect)) + TC_LOG_ERROR("sql.sql", "Spell %u Effect: %u listed in `spell_linked_spell` has same bp%u like effect (possible hack)", abs(trigger), abs(effect), eff->EffectIndex); } spellInfo = GetSpellInfo(abs(effect)); @@ -2575,11 +2523,11 @@ void SpellMgr::LoadPetDefaultSpells() if (!spellEntry) continue; - for (uint8 k = 0; k < MAX_SPELL_EFFECTS; ++k) + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - if (spellEntry->Effects[k].Effect == SPELL_EFFECT_SUMMON || spellEntry->Effects[k].Effect == SPELL_EFFECT_SUMMON_PET) + if (effect && (effect->Effect == SPELL_EFFECT_SUMMON || effect->Effect == SPELL_EFFECT_SUMMON_PET)) { - uint32 creature_id = spellEntry->Effects[k].MiscValue; + uint32 creature_id = effect->MiscValue; CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); if (!cInfo) continue; @@ -2796,18 +2744,7 @@ void SpellMgr::LoadSpellAreas() TC_LOG_INFO("server.loading", ">> Loaded %u spell area requirements in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -// Temporary structure to hold spell effect entries for faster loading -struct SpellEffectArray -{ - SpellEffectArray() - { - effects[0] = NULL; - effects[1] = NULL; - effects[2] = NULL; - } - - SpellEffectEntry const* effects[MAX_SPELL_EFFECTS]; -}; +typedef std::vector<SpellEffectEntry const*> SpellEffectVector; void SpellMgr::LoadSpellInfoStore() { @@ -2816,7 +2753,7 @@ void SpellMgr::LoadSpellInfoStore() UnloadSpellInfoStore(); mSpellInfoMap.resize(sSpellStore.GetNumRows(), NULL); - std::map<uint32, SpellEffectArray> effectsBySpell; + std::unordered_map<uint32, SpellEffectEntryMap> effectsBySpell; for (uint32 i = 0; i < sSpellEffectStore.GetNumRows(); ++i) { @@ -2824,17 +2761,19 @@ void SpellMgr::LoadSpellInfoStore() if (!effect) continue; - // TODO: 6.x implement dynamic spell effect storage and remove MAX_SPELL_EFFECTS - // This is a temporary fix to avoid crash when loading spells if (effect->EffectIndex >= MAX_SPELL_EFFECTS) + { + TC_LOG_ERROR("server.loading", "Spell %u has invalid EffectIndex %u, max is %u, skipped", i, effect->EffectIndex, uint32(MAX_SPELL_EFFECTS)); continue; + } - effectsBySpell[effect->SpellID].effects[effect->EffectIndex] = effect; + effectsBySpell[effect->SpellID][effect->DifficultyID].resize(MAX_SPELL_EFFECTS); + effectsBySpell[effect->SpellID][effect->DifficultyID][effect->EffectIndex] = effect; } for (uint32 i = 0; i < sSpellStore.GetNumRows(); ++i) if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(i)) - mSpellInfoMap[i] = new SpellInfo(spellEntry, effectsBySpell[i].effects); + mSpellInfoMap[i] = new SpellInfo(spellEntry, effectsBySpell[i]); TC_LOG_INFO("server.loading", ">> Loaded SpellInfo store in %u ms", GetMSTimeDiffToNow(oldMSTime)); } @@ -2896,9 +2835,12 @@ void SpellMgr::LoadSpellInfoCustomAttributes() if (!spellInfo) continue; - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - switch (spellInfo->Effects[j].ApplyAuraName) + if (!effect) + continue; + + switch (effect->ApplyAuraName) { case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_MOD_CONFUSE: @@ -2922,7 +2864,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes() break; } - switch (spellInfo->Effects[j].Effect) + switch (effect->Effect) { case SPELL_EFFECT_SCHOOL_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE: @@ -2960,7 +2902,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes() // only enchanting profession enchantments procs can stack if (IsPartOfSkillLine(SKILL_ENCHANTING, i)) { - uint32 enchantId = spellInfo->Effects[j].MiscValue; + uint32 enchantId = effect->MiscValue; SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId); if (!enchant) break; @@ -2977,7 +2919,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes() // if proced directly from enchantment, not via proc aura // NOTE: Enchant Weapon - Blade Ward also has proc aura spell and is proced directly // however its not expected to stack so this check is good - if (procInfo->HasAura(SPELL_AURA_PROC_TRIGGER_SPELL)) + if (procInfo->HasAura(DIFFICULTY_NONE, SPELL_AURA_PROC_TRIGGER_SPELL)) continue; procInfo->AttributesCu |= SPELL_ATTR0_CU_ENCHANT_PROC; @@ -3033,9 +2975,11 @@ void SpellMgr::LoadSpellInfoCorrections() if (!spellInfo) continue; - for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - switch (spellInfo->Effects[j].Effect) + if (!effect) + continue; + switch (effect->Effect) { case SPELL_EFFECT_CHARGE: case SPELL_EFFECT_CHARGE_DEST: @@ -3054,43 +2998,43 @@ void SpellMgr::LoadSpellInfoCorrections() switch (spellInfo->Id) { case 42436: // Drink! (Brewfest) - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); break; case 52611: // Summon Skeletons case 52612: // Summon Skeletons - spellInfo->Effects[EFFECT_0].MiscValueB = 64; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->MiscValueB = 64; break; case 40244: // Simon Game Visual case 40245: // Simon Game Visual case 40246: // Simon Game Visual case 40247: // Simon Game Visual case 42835: // Spout, remove damage effect, only anim is needed - spellInfo->Effects[EFFECT_0].Effect = 0; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->Effect = 0; break; case 30657: // Quake - spellInfo->Effects[EFFECT_0].TriggerSpell = 30571; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TriggerSpell = 30571; break; case 30541: // Blaze (needs conditions entry) - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY); - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(); break; case 63665: // Charge (Argent Tournament emote on riders) case 31298: // Sleep (needs target selection script) case 51904: // Summon Ghouls On Scarlet Crusade (this should use conditions table, script for this spell needs to be fixed) case 68933: // Wrath of Air Totem rank 2 (Aura) case 29200: // Purify Helboar Meat - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(); break; case 31344: // Howl of Azgalor - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yards instead of 50000?! + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yards instead of 50000?! break; case 42818: // Headless Horseman - Wisp Flight Port case 42821: // Headless Horseman - Wisp Flight Missile spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100 yards break; case 36350: // They Must Burn Bomb Aura (self) - spellInfo->Effects[EFFECT_0].TriggerSpell = 36325; // They Must Burn Bomb Drop (DND) + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TriggerSpell = 36325; // They Must Burn Bomb Drop (DND) break; case 49838: // Stop Time spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; @@ -3099,11 +3043,11 @@ void SpellMgr::LoadSpellInfoCorrections() case 62136: // Energize Cores case 54069: // Energize Cores case 56251: // Energize Cores - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENTRY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENTRY); break; case 50785: // Energize Cores case 59372: // Energize Cores - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENEMY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENEMY); break; case 63320: // Glyph of Life Tap case 53228: // Rapid Killing (Rank 1) @@ -3116,8 +3060,8 @@ void SpellMgr::LoadSpellInfoCorrections() break; case 59725: // Improved Spell Reflection - aoe aura // Target entry seems to be wrong for this spell :/ - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER_AREA_PARTY); - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS_2); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER_AREA_PARTY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS_2); break; case 31347: // Doom case 36327: // Shoot Arcane Explosion Arrow @@ -3189,7 +3133,7 @@ void SpellMgr::LoadSpellInfoCorrections() case 33711: // Murmur's Touch case 38794: // Murmur's Touch spellInfo->MaxAffectedTargets = 1; - spellInfo->Effects[EFFECT_0].TriggerSpell = 33760; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TriggerSpell = 33760; break; case 17941: // Shadow Trance case 22008: // Netherwind Focus @@ -3204,7 +3148,7 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->ProcCharges = 1; break; case 44544: // Fingers of Frost - spellInfo->Effects[EFFECT_0].SpellClassMask = flag128(685904631, 1151048, 0, 0); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(685904631, 1151048, 0, 0); break; case 74396: // Fingers of Frost visual buff spellInfo->ProcCharges = 2; @@ -3219,16 +3163,16 @@ void SpellMgr::LoadSpellInfoCorrections() case 47204: // Everlasting Affliction (4) case 47205: // Everlasting Affliction (5) // add corruption to affected spells - spellInfo->Effects[EFFECT_1].SpellClassMask[0] |= 2; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->SpellClassMask[0] |= 2; break; case 37408: // Oscillation Field spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS; break; case 51852: // The Eye of Acherus (no spawn in phase 2 in db) - spellInfo->Effects[EFFECT_0].MiscValue |= 1; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->MiscValue |= 1; break; case 51912: // Crafty's Ultra-Advanced Proto-Typical Shortening Blaster - spellInfo->Effects[EFFECT_0].ApplyAuraPeriod = 3000; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraPeriod = 3000; break; // Master Shapeshifter: missing stance data for forms other than bear - bear version has correct data // To prevent aura staying on target after talent unlearned @@ -3244,23 +3188,23 @@ void SpellMgr::LoadSpellInfoCorrections() break; case 51466: // Elemental Oath (Rank 1) case 51470: // Elemental Oath (Rank 2) - spellInfo->Effects[EFFECT_1].Effect = SPELL_EFFECT_APPLY_AURA; - spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; - spellInfo->Effects[EFFECT_1].MiscValue = SPELLMOD_EFFECT2; - spellInfo->Effects[EFFECT_1].SpellClassMask = flag128(0x00000000, 0x00004000, 0x00000000, 0x00000000); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->Effect = SPELL_EFFECT_APPLY_AURA; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->MiscValue = SPELLMOD_EFFECT2; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->SpellClassMask = flag128(0x00000000, 0x00004000, 0x00000000, 0x00000000); break; case 47569: // Improved Shadowform (Rank 1) // with this spell atrribute aura can be stacked several times spellInfo->Attributes &= ~SPELL_ATTR0_NOT_SHAPESHIFT; break; case 64904: // Hymn of Hope - spellInfo->Effects[EFFECT_1].ApplyAuraName = SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->ApplyAuraName = SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT; break; case 30421: // Nether Portal - Perseverence - spellInfo->Effects[EFFECT_2].BasePoints += 30000; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->BasePoints += 30000; break; case 41913: // Parasitic Shadowfiend Passive - spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_DUMMY; // proc debuff, and summon infinite fiends + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraName = SPELL_AURA_DUMMY; // proc debuff, and summon infinite fiends break; case 27892: // To Anchor 1 case 27928: // To Anchor 1 @@ -3274,8 +3218,8 @@ void SpellMgr::LoadSpellInfoCorrections() // this is the only known exception, probably just wrong data case 29214: // Wrath of the Plaguebringer case 54836: // Wrath of the Plaguebringer - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY); - spellInfo->Effects[EFFECT_1].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ALLY); break; case 63675: // Improved Devouring Plague spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS; @@ -3289,47 +3233,47 @@ void SpellMgr::LoadSpellInfoCorrections() break; case 53241: // Marked for Death (Rank 1) case 53243: // Marked for Death (Rank 2) - spellInfo->Effects[EFFECT_0].SpellClassMask = flag128(0x00067801, 0x10820001, 0x00000801, 0x00000000); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x00067801, 0x10820001, 0x00000801, 0x00000000); break; case 5176: // Wrath case 2912: // Starfire - case 78674: // Starsurge - spellInfo->Effects[EFFECT_1].Effect = SPELL_EFFECT_DUMMY; - spellInfo->Effects[EFFECT_1].TargetA = TARGET_UNIT_CASTER; + //case 78674: // Starsurge 6.x effect 1 is no more + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->Effect = SPELL_EFFECT_DUMMY; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->TargetA = TARGET_UNIT_CASTER; break; case 70728: // Exploit Weakness (needs target selection script) case 70840: // Devious Minds (needs target selection script) - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_PET); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_PET); break; case 70893: // Culling The Herd (needs target selection script) - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_MASTER); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_MASTER); break; case 54800: // Sigil of the Frozen Conscience - change class mask to custom extended flags of Icy Touch // this is done because another spell also uses the same SpellFamilyFlags as Icy Touch // SpellFamilyFlags[0] & 0x00000040 in SPELLFAMILY_DEATHKNIGHT is currently unused (3.3.5a) // this needs research on modifier applying rules, does not seem to be in Attributes fields - spellInfo->Effects[EFFECT_0].SpellClassMask = flag128(0x00000040, 0x00000000, 0x00000000, 0x00000000); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x00000040, 0x00000000, 0x00000000, 0x00000000); break; case 64949: // Idol of the Flourishing Life - spellInfo->Effects[EFFECT_0].SpellClassMask = flag128(0x00000000, 0x02000000, 0x00000000, 0x00000000); - spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x00000000, 0x02000000, 0x00000000, 0x00000000); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; break; case 34231: // Libram of the Lightbringer case 60792: // Libram of Tolerance case 64956: // Libram of the Resolute - spellInfo->Effects[EFFECT_0].SpellClassMask = flag128(0x80000000, 0x00000000, 0x00000000, 0x00000000); - spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x80000000, 0x00000000, 0x00000000, 0x00000000); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; break; case 28851: // Libram of Light case 28853: // Libram of Divinity case 32403: // Blessed Book of Nagrand - spellInfo->Effects[EFFECT_0].SpellClassMask = flag128(0x40000000, 0x00000000, 0x00000000, 0x00000000); - spellInfo->Effects[EFFECT_0].ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask = flag128(0x40000000, 0x00000000, 0x00000000, 0x00000000); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER; break; case 45602: // Ride Carpet - spellInfo->Effects[EFFECT_0].BasePoints = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)" + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->BasePoints = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)" break; case 61719: // Easter Lay Noblegarden Egg Aura - Interrupt flags copied from aura which this aura is linked with spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE; @@ -3344,7 +3288,7 @@ void SpellMgr::LoadSpellInfoCorrections() case 56606: // Ride Jokkum case 61791: // Ride Vehicle (Yogg-Saron) /// @todo: remove this when basepoints of all Ride Vehicle auras are calculated correctly - spellInfo->Effects[EFFECT_0].BasePoints = 1; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->BasePoints = 1; break; case 59630: // Black Magic spellInfo->Attributes |= SPELL_ATTR0_PASSIVE; @@ -3355,12 +3299,12 @@ void SpellMgr::LoadSpellInfoCorrections() case 51798: // Brewfest - Relay Race - Intro - Quest Complete case 47134: // Quest Complete //! HACK: This spell break quest complete for alliance and on retail not used °_O - spellInfo->Effects[EFFECT_0].Effect = 0; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->Effect = 0; break; // ULDUAR SPELLS // case 62374: // Pursued (Flame Leviathan) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 63342: // Focused Eyebeam Summon Trigger (Kologarn) spellInfo->MaxAffectedTargets = 1; @@ -3382,7 +3326,7 @@ void SpellMgr::LoadSpellInfoCorrections() // then EFFECT_1, etc - instead of applying each effect on target1, then target2, etc. // The above situation causes the visual for this spell to be bugged, so we remove the instakill // effect and implement a script hack for that. - spellInfo->Effects[EFFECT_1].Effect = 0; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->Effect = 0; break; case 64386: // Terrifying Screech (Auriaya) case 64389: // Sentinel Blast (Auriaya) @@ -3396,7 +3340,7 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY; break; case 63414: // Spinning Up (Mimiron) - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_CASTER); spellInfo->ChannelInterruptFlags = 0; break; case 63036: // Rocket Strike (Mimiron) @@ -3416,7 +3360,7 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->MaxAffectedTargets = 3; break; case 62293: // Cosmic Smash (Algalon the Observer) - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_DEST_CASTER); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_DEST_CASTER); break; case 62311: // Cosmic Smash (Algalon the Observer) case 64596: // Cosmic Smash (Algalon the Observer) @@ -3431,7 +3375,7 @@ void SpellMgr::LoadSpellInfoCorrections() case 64031: // Scrapyard Teleport case 64032: // Formation Grounds Teleport case 65042: // Prison of Yogg-Saron Teleport - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB); break; // ENDOF ULDUAR SPELLS // @@ -3449,14 +3393,14 @@ void SpellMgr::LoadSpellInfoCorrections() // case 72435: // Defiling Horror case 72452: // Defiling Horror - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd break; case 72830: // Achievement Check - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 72900: // Start Halls of Reflection Quest AE - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; // ENDOF HALLS OF REFLECTION SPELLS // @@ -3472,7 +3416,7 @@ void SpellMgr::LoadSpellInfoCorrections() case 70859: // Upper Spire Teleport case 70860: // Frozen Throne Teleport case 70861: // Sindragosa's Lair Teleport - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB); break; case 69075: // Bone Storm (Lord Marrowgar) case 70834: // Bone Storm (Lord Marrowgar) @@ -3482,7 +3426,7 @@ void SpellMgr::LoadSpellInfoCorrections() case 71160: // Plague Stench (Stinky) case 71161: // Plague Stench (Stinky) case 71123: // Decimate (Stinky & Precious) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd break; case 71169: // Shadow's Fate spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS; @@ -3494,59 +3438,59 @@ void SpellMgr::LoadSpellInfoCorrections() case 73844: // Award Reputation - Boss Kill case 73845: // Award Reputation - Boss Kill case 73846: // Award Reputation - Boss Kill - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 72378: // Blood Nova (Deathbringer Saurfang) case 73058: // Blood Nova (Deathbringer Saurfang) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); break; case 72769: // Scent of Blood (Deathbringer Saurfang) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // no break case 72771: // Scent of Blood (Deathbringer Saurfang) - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); break; case 72723: // Resistant Skin (Deathbringer Saurfang adds) // this spell initially granted Shadow damage immunity, however it was removed but the data was left in client - spellInfo->Effects[EFFECT_2].Effect = 0; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->Effect = 0; break; case 70460: // Coldflame Jets (Traps after Saurfang) spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(1); // 10 seconds break; case 71412: // Green Ooze Summon (Professor Putricide) case 71415: // Orange Ooze Summon (Professor Putricide) - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); break; case 71159: // Awaken Plagued Zombies spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(21); break; case 70530: // Volatile Ooze Beam Protection (Professor Putricide) - spellInfo->Effects[EFFECT_0].Effect = SPELL_EFFECT_APPLY_AURA; // for an unknown reason this was SPELL_EFFECT_APPLY_AREA_AURA_RAID + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->Effect = SPELL_EFFECT_APPLY_AURA; // for an unknown reason this was SPELL_EFFECT_APPLY_AREA_AURA_RAID break; // THIS IS HERE BECAUSE COOLDOWN ON CREATURE PROCS IS NOT IMPLEMENTED case 71604: // Mutated Strength (Professor Putricide) case 72673: // Mutated Strength (Professor Putricide) case 72674: // Mutated Strength (Professor Putricide) case 72675: // Mutated Strength (Professor Putricide) - spellInfo->Effects[EFFECT_1].Effect = 0; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->Effect = 0; break; case 72454: // Mutated Plague (Professor Putricide) case 72464: // Mutated Plague (Professor Putricide) case 72506: // Mutated Plague (Professor Putricide) case 72507: // Mutated Plague (Professor Putricide) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 70911: // Unbound Plague (Professor Putricide) (needs target selection script) case 72854: // Unbound Plague (Professor Putricide) (needs target selection script) case 72855: // Unbound Plague (Professor Putricide) (needs target selection script) case 72856: // Unbound Plague (Professor Putricide) (needs target selection script) - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY); break; case 71518: // Unholy Infusion Quest Credit (Professor Putricide) case 72934: // Blood Infusion Quest Credit (Blood-Queen Lana'thel) case 72289: // Frost Infusion Quest Credit (Sindragosa) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // another missing radius + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // another missing radius break; case 71708: // Empowered Flare (Blood Prince Council) case 72785: // Empowered Flare (Blood Prince Council) @@ -3570,18 +3514,18 @@ void SpellMgr::LoadSpellInfoCorrections() break; case 72015: // Frostbolt Volley (only heroic) case 72016: // Frostbolt Volley (only heroic) - spellInfo->Effects[EFFECT_2].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_40_YARDS); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_40_YARDS); break; case 70936: // Summon Suppressor (needs target selection script) - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); - spellInfo->Effects[EFFECT_0].TargetB = SpellImplicitTargetInfo(); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetB = SpellImplicitTargetInfo(); break; case 72706: // Achievement Check (Valithria Dreamwalker) case 71357: // Order Whelp - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; case 70598: // Sindragosa's Fury - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DEST); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_DEST_DEST); break; case 69846: // Frost Bomb spellInfo->Speed = 0.0f; // This spell's summon happens instantly @@ -3599,12 +3543,12 @@ void SpellMgr::LoadSpellInfoCorrections() case 73708: // Defile case 73709: // Defile case 73710: // Defile - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; case 69030: // Val'kyr Target Search - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; case 69198: // Raging Spirit Visual spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13); // 50000yd @@ -3613,9 +3557,9 @@ void SpellMgr::LoadSpellInfoCorrections() case 74295: // Harvest Souls case 74296: // Harvest Souls case 74297: // Harvest Souls - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - spellInfo->Effects[EFFECT_2].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_2))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 73655: // Harvest Soul spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS; @@ -3627,34 +3571,34 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->DurationEntry = sSpellDurationStore.LookupEntry(28); // 5 seconds break; case 73529: // Shadow Trap - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS); // 10yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_10_YARDS); // 10yd break; case 74282: // Shadow Trap (searcher) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); // 3yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_3_YARDS); // 3yd break; case 72595: // Restore Soul case 73650: // Restore Soul - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; case 74086: // Destroy Soul - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; case 74302: // Summon Spirit Bomb case 74342: // Summon Spirit Bomb - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd spellInfo->MaxAffectedTargets = 1; break; case 74341: // Summon Spirit Bomb case 74343: // Summon Spirit Bomb - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd spellInfo->MaxAffectedTargets = 3; break; case 73579: // Summon Spirit Bomb - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd break; case 72350: // Fury of Frostmourne - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 75127: // Kill Frostmourne Players case 72351: // Fury of Frostmourne @@ -3662,31 +3606,31 @@ void SpellMgr::LoadSpellInfoCorrections() case 72429: // Mass Resurrection case 73159: // Play Movie case 73582: // Trigger Vile Spirit (Inside, Heroic) - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 72376: // Raise Dead spellInfo->MaxAffectedTargets = 3; - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd break; case 71809: // Jump spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(3); // 20yd - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); // 25yd break; case 72405: // Broken Frostmourne - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd break; // ENDOF ICECROWN CITADEL SPELLS // // RUBY SANCTUM SPELLS // case 74799: // Soul Consumption - spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_12_YARDS); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_1))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_12_YARDS); break; case 74769: // Twilight Cutter case 77844: // Twilight Cutter case 77845: // Twilight Cutter case 77846: // Twilight Cutter - spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_100_YARDS); // 100yd break; case 75509: // Twilight Mending spellInfo->AttributesEx6 |= SPELL_ATTR6_CAN_TARGET_INVISIBLE; @@ -3731,7 +3675,7 @@ void SpellMgr::LoadSpellInfoCorrections() case 76606: // Disable Beacon Beams L case 76608: // Disable Beacon Beams R // Little hack, Increase the radius so it can hit the Cave In Stalkers in the platform. - spellInfo->Effects[EFFECT_0].MaxRadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_45_YARDS); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->MaxRadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_45_YARDS); break; case 75323: // Reverberating Hymn // Aura is refreshed at 3 seconds, and the tick should happen at the fourth. @@ -3760,7 +3704,7 @@ void SpellMgr::LoadSpellInfoCorrections() spellInfo->MaxAffectedTargets = 1; break; case 75697: // Evolution - spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENTRY); + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->TargetA = SpellImplicitTargetInfo(TARGET_UNIT_SRC_AREA_ENTRY); break; // ISLE OF CONQUEST SPELLS // @@ -3778,7 +3722,7 @@ void SpellMgr::LoadSpellInfoCorrections() case SPELLFAMILY_PALADIN: // Seals of the Pure should affect Seal of Righteousness if (spellInfo->SpellIconID == 25 && spellInfo->Attributes & SPELL_ATTR0_PASSIVE) - spellInfo->Effects[EFFECT_0].SpellClassMask[1] |= 0x20000000; + const_cast<SpellEffectInfo*>(spellInfo->GetEffect(EFFECT_0))->SpellClassMask[1] |= 0x20000000; break; case SPELLFAMILY_DEATHKNIGHT: // Icy Touch - extend FamilyFlags (unused value) for Sigil of the Frozen Conscience to use @@ -3795,3 +3739,42 @@ void SpellMgr::LoadSpellInfoCorrections() TC_LOG_INFO("server.loading", ">> Loaded SpellInfo corrections in %u ms", GetMSTimeDiffToNow(oldMSTime)); } + +void SpellMgr::LoadPetFamilySpellsStore() +{ + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) + { + SkillLineAbilityEntry const* skillLine = sSkillLineAbilityStore.LookupEntry(j); + if (!skillLine) + continue; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->SpellID); + if (!spellInfo) + continue; + + SpellLevelsEntry const* levels = sSpellLevelsStore.LookupEntry(spellInfo->LevelsID); + if (spellInfo->LevelsID && (!levels || levels->SpellLevel)) + continue; + + if (SpellMiscEntry const* spellMisc = sSpellMiscStore.LookupEntry(spellInfo->MiscID)) + { + if (spellMisc->Attributes & SPELL_ATTR0_PASSIVE) + { + for (uint32 i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i) + { + CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i); + if (!cFamily) + continue; + + if (skillLine->SkillLine != cFamily->SkillLine[0] && skillLine->SkillLine != cFamily->SkillLine[1]) + continue; + + if (skillLine->AquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) + continue; + + sPetFamilySpellsStore[i].insert(spellInfo->ID); + } + } + } + } +} diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 053935a53cb..0e591a27e81 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -617,12 +617,6 @@ class SpellMgr // Spell correctness for client using static bool IsSpellValid(SpellInfo const* spellInfo, Player* player = NULL, bool msg = true); - // Spell difficulty - uint32 GetSpellDifficultyId(uint32 spellId) const; - void SetSpellDifficultyId(uint32 spellId, uint32 id); - uint32 GetSpellIdForDifficulty(uint32 spellId, Unit const* caster) const; - SpellInfo const* GetSpellForDifficultyFromSpell(SpellInfo const* spell, Unit const* caster) const; - // Spell Ranks table SpellChainNode const* GetSpellChainNode(uint32 spell_id) const; uint32 GetFirstSpellInChain(uint32 spell_id) const; @@ -705,6 +699,8 @@ class SpellMgr } uint32 GetSpellInfoStoreSize() const { return mSpellInfoMap.size(); } + void LoadPetFamilySpellsStore(); + private: SpellInfo* _GetSpellInfo(uint32 spellId) { return spellId < GetSpellInfoStoreSize() ? mSpellInfoMap[spellId] : NULL; } diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 8ab3a72b47e..00a9fa5eb45 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -110,11 +110,14 @@ std::string _SpellScript::EffectHook::EffIndexToString() bool _SpellScript::EffectNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) { - if (!spellEntry->Effects[effIndex].Effect && !effName) + SpellEffectInfo const* effect = spellEntry->GetEffect(effIndex); + if (!effect) + return false; + if (!effect->Effect && !effName) return true; - if (!spellEntry->Effects[effIndex].Effect) + if (!effect->Effect) return false; - return (effName == SPELL_EFFECT_ANY) || (spellEntry->Effects[effIndex].Effect == effName); + return (effName == SPELL_EFFECT_ANY) || (effect->Effect == effName); } std::string _SpellScript::EffectNameCheck::ToString() @@ -132,11 +135,14 @@ std::string _SpellScript::EffectNameCheck::ToString() bool _SpellScript::EffectAuraNameCheck::Check(SpellInfo const* spellEntry, uint8 effIndex) { - if (!spellEntry->Effects[effIndex].ApplyAuraName && !effAurName) + SpellEffectInfo const* effect = spellEntry->GetEffect(effIndex); + if (!effect) + return false; + if (!effect->ApplyAuraName && !effAurName) return true; - if (!spellEntry->Effects[effIndex].ApplyAuraName) + if (!effect->ApplyAuraName) return false; - return (effAurName == SPELL_AURA_ANY) || (spellEntry->Effects[effIndex].ApplyAuraName == effAurName); + return (effAurName == SPELL_AURA_ANY) || (effect->ApplyAuraName == effAurName); } std::string _SpellScript::EffectAuraNameCheck::ToString() @@ -218,8 +224,12 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 eff if (!targetType) return false; - if (spellEntry->Effects[effIndex].TargetA.GetTarget() != targetType && - spellEntry->Effects[effIndex].TargetB.GetTarget() != targetType) + SpellEffectInfo const* effect = spellEntry->GetEffect(effIndex); + if (!effect) + return false; + + if (effect->TargetA.GetTarget() != targetType && + effect->TargetB.GetTarget() != targetType) return false; SpellImplicitTargetInfo targetInfo(targetType); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a9d12fd11f8..c24bd53bd57 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1413,6 +1413,8 @@ void World::SetInitialWorldSettings() LoadDBCStores(m_dataPath); LoadDB2Stores(m_dataPath); + sSpellMgr->LoadPetFamilySpellsStore(); + TC_LOG_INFO("server.loading", "Loading SpellInfo store..."); sSpellMgr->LoadSpellInfoStore(); diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index 2cf97403595..e571f30b74e 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -204,7 +204,7 @@ public: // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) player->LearnSpellHighestRank(talentInfo->SpellID); - player->AddTalent(talentInfo->SpellID, player->GetActiveTalentGroup()); + player->AddTalent(talentInfo->SpellID, player->GetActiveTalentGroup(), true); } handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 39644e5c08f..c806b99f2db 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -808,9 +808,11 @@ public: } bool known = target && target->HasSpell(id); - bool learn = (spellInfo->Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL); - SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[0].TriggerSpell); + SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0); + bool learn = effect ? (effect->Effect == SPELL_EFFECT_LEARN_SPELL) : false; + + SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell) : NULL; bool talent = (GetTalentBySpellID(id) != nullptr); bool passive = spellInfo->IsPassive(); @@ -878,9 +880,11 @@ public: } bool known = target && target->HasSpell(id); - bool learn = (spellInfo->Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL); - SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[0].TriggerSpell); + SpellEffectInfo const* effect = spellInfo->GetEffect(EFFECT_0); + bool learn = effect? (effect->Effect == SPELL_EFFECT_LEARN_SPELL) : false; + + SpellInfo const* learnSpellInfo = effect ? sSpellMgr->GetSpellInfo(effect->TriggerSpell) : NULL; bool talent = (GetTalentBySpellID(id) != nullptr); bool passive = spellInfo->IsPassive(); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index f1b6e7f7289..f8c3f43d144 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -2248,7 +2248,7 @@ public: SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); - if (Unit::IsDamageReducedByArmor(schoolmask)) + if (handler->GetSession()->GetPlayer()->IsDamageReducedByArmor(schoolmask)) damage = handler->GetSession()->GetPlayer()->CalcArmorReducedDamage(target, damage, NULL, BASE_ATTACK); char* spellStr = strtok((char*)NULL, " "); diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp index 9c203ac2395..5805509cc9b 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp +++ b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp @@ -267,7 +267,7 @@ class spell_occuthar_eyes_of_occuthar : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].CalcValue())) + if (!sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_0)->CalcValue())) return false; return true; } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp index 4cb0b61365d..9c4865a8d84 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp @@ -485,23 +485,23 @@ public: void SpellHit(Unit* /*pAttacker*/, const SpellInfo* Spell) override { //We only care about interrupt effects and only if they are durring a spell currently being cast - if ((Spell->Effects[0].Effect != SPELL_EFFECT_INTERRUPT_CAST && - Spell->Effects[1].Effect != SPELL_EFFECT_INTERRUPT_CAST && - Spell->Effects[2].Effect != SPELL_EFFECT_INTERRUPT_CAST) || !me->IsNonMeleeSpellCast(false)) - return; - - //Interrupt effect - me->InterruptNonMeleeSpells(false); + for (SpellEffectInfo const* effect : Spell->GetEffectsForDifficulty(me->GetMap()->GetDifficulty())) + if (effect && effect->Effect == SPELL_EFFECT_INTERRUPT_CAST && me->IsNonMeleeSpellCast(false)) + { + //Interrupt effect + me->InterruptNonMeleeSpells(false); - //Normally we would set the cooldown equal to the spell duration - //but we do not have access to the DurationStore + //Normally we would set the cooldown equal to the spell duration + //but we do not have access to the DurationStore - switch (CurrentNormalSpell) - { - case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; - case SPELL_FIREBALL: FireCooldown = 5000; break; - case SPELL_FROSTBOLT: FrostCooldown = 5000; break; - } + switch (CurrentNormalSpell) + { + case SPELL_ARCMISSLE: ArcaneCooldown = 5000; break; + case SPELL_FIREBALL: FireCooldown = 5000; break; + case SPELL_FROSTBOLT: FrostCooldown = 5000; break; + } + return; + } } }; }; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp index 6cd14598a58..6758808c5d9 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp @@ -164,8 +164,10 @@ public: { if (Player* player = i->GetSource()) { - if (spell && spell->Effects[0].MiscValue) - player->KilledMonsterCredit(spell->Effects[0].MiscValue); + if (spell) + if (SpellEffectInfo const* effect = spell->GetEffect(EFFECT_0)) + if (effect->MiscValue) + player->KilledMonsterCredit(effect->MiscValue); } } } diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp index 69c188a61dc..e5a42096a04 100644 --- a/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp @@ -314,7 +314,7 @@ class spell_shadow_portal_rooms : public SpellScriptLoader int8 phase_to_set = 0; int32 gate_to_close = 0; - switch (GetSpellInfo()->Effects[effIndex].MiscValue) + switch (GetSpellInfo()->GetEffect(effIndex)->MiscValue) { case SPELL_EVENT_HALLOFSECRETS: pos_to_summon = 0; // Not yet spawned diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index 99b710afb1e..cf0228f5192 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -412,9 +412,14 @@ public: void SpellHit(Unit* /*caster*/, const SpellInfo* Spell) override { - for (uint8 i = 0; i < 3; ++i) - if (Spell->Effects[i].Effect == 38) + for (SpellEffectInfo const* effect : Spell->GetEffectsForDifficulty(DIFFICULTY_NONE)) + { + if (effect && effect->Effect == 38) + { me->DisappearAndDie(); + return; + } + } } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp index 84a267543c5..15fbef8a08b 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp @@ -537,7 +537,7 @@ public: /// TODO: Remove this once we find a general rule for WorldObject::MovePosition (this spell shouldn't take the Z change into consideration) Unit* caster = GetCaster(); float angle = float(rand_norm()) * static_cast<float>(2 * M_PI); - uint32 dist = caster->GetObjectSize() + GetSpellInfo()->Effects[effIndex].CalcRadius(GetCaster()) * (float)rand_norm(); + uint32 dist = caster->GetObjectSize() + GetSpellInfo()->GetEffect(effIndex)->CalcRadius(GetCaster()) * (float)rand_norm(); float x = caster->GetPositionX() + dist * std::cos(angle); float y = caster->GetPositionY() + dist * std::sin(angle); diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp index 47a40dd56ef..e5f24d37a30 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp @@ -378,7 +378,7 @@ public: { CustomSpellValues values; values.AddSpellMod(SPELLVALUE_BASE_POINT0, aurEff->GetAmount()); - caster->CastCustomSpell(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, values, GetTarget()); + caster->CastCustomSpell(GetSpellInfo()->GetEffect(caster, EFFECT_0)->TriggerSpell, values, GetTarget()); } } diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp index 189cc842d9b..919f8b43ce3 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp @@ -106,7 +106,7 @@ public: //THIS GOB IS A TRAP - What shall i do? =( //Cast it spell? Copyed Heigan method floorEruption->SendCustomAnim(floorEruption->GetGoAnimProgress()); - floorEruption->CastSpell(NULL, Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL ? 17731 : 69294); //pFloorEruption->GetGOInfo()->trap.spellId + floorEruption->CastSpell(NULL, Difficulty(instance->GetSpawnMode()) == DIFFICULTY_10_N ? 17731 : 69294); //pFloorEruption->GetGOInfo()->trap.spellId //Get all immediatly nearby floors std::list<GameObject*> nearFloorList; diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index e0b03d54f69..533d78a68f5 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -518,7 +518,7 @@ class spell_ooze_zap : public SpellScriptLoader SpellCastResult CheckRequirement() { - if (!GetCaster()->HasAura(GetSpellInfo()->Effects[EFFECT_1].CalcValue())) + if (!GetCaster()->HasAura(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue())) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; // This is actually correct if (!GetExplTargetUnit()) @@ -603,7 +603,7 @@ class spell_energize_aoe : public SpellScriptLoader { for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { - if ((*itr)->GetTypeId() == TYPEID_PLAYER && (*itr)->ToPlayer()->GetQuestStatus(GetSpellInfo()->Effects[EFFECT_1].CalcValue()) == QUEST_STATUS_INCOMPLETE) + if ((*itr)->GetTypeId() == TYPEID_PLAYER && (*itr)->ToPlayer()->GetQuestStatus(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()) == QUEST_STATUS_INCOMPLETE) ++itr; else targets.erase(itr++); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp index 592d69c5c76..5b88cfb332b 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp @@ -142,7 +142,7 @@ public: // clone player->CastSpell(summon, SPELL_CLONE_PLAYER, true); // phase the summon - summon->SetInPhase(spellInfo->Effects[EFFECT_0].MiscValueB, true, true); + summon->SetInPhase(spellInfo->GetEffect(EFFECT_0)->MiscValueB, true, true); } } ++insanityHandled; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp index c826b8fc9ef..f1d029e53e2 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp @@ -151,7 +151,7 @@ class boss_baltharus_the_warborn : public CreatureScript void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_10_N) { if (me->HealthBelowPctDamaged(50, damage) && _cloneCount == 1) DoAction(ACTION_CLONE); diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index ee77671d83e..16cbcee562e 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -1499,8 +1499,8 @@ class spell_halion_damage_aoe_summon : public SpellScriptLoader { PreventHitDefaultEffect(effIndex); Unit* caster = GetCaster(); - uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue); - SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetSpellInfo()->Effects[effIndex].MiscValueB)); + uint32 entry = uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValue); + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValueB)); uint32 duration = uint32(GetSpellInfo()->GetDuration()); Position pos = caster->GetPosition(); @@ -1607,8 +1607,8 @@ class spell_halion_clear_debuffs : public SpellScriptLoader void HandleScript(SpellEffIndex effIndex) { - if (GetHitUnit()->HasAura(GetSpellInfo()->Effects[effIndex].CalcValue())) - GetHitUnit()->RemoveAurasDueToSpell(GetSpellInfo()->Effects[effIndex].CalcValue()); + if (GetHitUnit()->HasAura(GetSpellInfo()->GetEffect(effIndex)->CalcValue())) + GetHitUnit()->RemoveAurasDueToSpell(GetSpellInfo()->GetEffect(effIndex)->CalcValue()); } void Register() override diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index 69dc25892c1..aa80295d83c 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -837,10 +837,9 @@ class spell_impale : public SpellScriptLoader void HandleDamageCalc(SpellEffIndex /*effIndex*/) { Unit* target = GetHitUnit(); - uint32 permafrost = sSpellMgr->GetSpellIdForDifficulty(SPELL_PERMAFROST, target); // make sure Impale doesnt do damage if we are standing on permafrost - if (target && target->HasAura(permafrost)) + if (target && target->HasAura(SPELL_PERMAFROST)) SetHitDamage(0); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index 2b541e4b972..b79e093a3e0 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -384,7 +384,7 @@ class boss_toc_champion_controller : public CreatureScript vOtherEntries.push_back(playerTeam == ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR); uint8 healersSubtracted = 2; - if (_instance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL || _instance->instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC) + if (_instance->instance->GetSpawnMode() == DIFFICULTY_25_N || _instance->instance->GetSpawnMode() == DIFFICULTY_25_HC) healersSubtracted = 1; for (uint8 i = 0; i < healersSubtracted; ++i) { @@ -421,7 +421,7 @@ class boss_toc_champion_controller : public CreatureScript vHealersEntries.erase(vHealersEntries.begin() + pos); } - if (_instance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_NORMAL || _instance->instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC) + if (_instance->instance->GetSpawnMode() == DIFFICULTY_10_N || _instance->instance->GetSpawnMode() == DIFFICULTY_10_HC) for (uint8 i = 0; i < 4; ++i) vOtherEntries.erase(vOtherEntries.begin() + urand(0, vOtherEntries.size() - 1)); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 7e8653c4a55..25dc59acc34 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -494,7 +494,7 @@ class spell_mistress_kiss : public SpellScriptLoader bool Load() override { if (GetCaster()) - if (sSpellMgr->GetSpellIdForDifficulty(SPELL_MISTRESS_KISS_DAMAGE_SILENCE, GetCaster())) + if (sSpellMgr->GetSpellInfo(SPELL_MISTRESS_KISS_DAMAGE_SILENCE)) return true; return false; } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index dec2f44745d..07eec388ca2 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -706,11 +706,11 @@ class spell_powering_up : public SpellScriptLoader bool Load() override { - spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_SURGE_OF_SPEED, GetCaster()); + spellId = SPELL_SURGE_OF_SPEED; if (!sSpellMgr->GetSpellInfo(spellId)) return false; - poweringUp = sSpellMgr->GetSpellIdForDifficulty(SPELL_POWERING_UP, GetCaster()); + poweringUp = SPELL_POWERING_UP; if (!sSpellMgr->GetSpellInfo(poweringUp)) return false; @@ -769,7 +769,7 @@ class spell_valkyr_essences : public SpellScriptLoader bool Load() override { - spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_SURGE_OF_SPEED, GetCaster()); + spellId = SPELL_SURGE_OF_SPEED; if (!sSpellMgr->GetSpellInfo(spellId)) return false; return true; @@ -781,57 +781,54 @@ class spell_valkyr_essences : public SpellScriptLoader { if (dmgInfo.GetSpellInfo()) { - if (uint32 poweringUp = sSpellMgr->GetSpellIdForDifficulty(SPELL_POWERING_UP, owner)) - { - if (urand(0, 99) < 5) - GetTarget()->CastSpell(GetTarget(), spellId, true); + if (urand(0, 99) < 5) + GetTarget()->CastSpell(GetTarget(), spellId, true); - // Twin Vortex part - uint32 lightVortex = sSpellMgr->GetSpellIdForDifficulty(SPELL_LIGHT_VORTEX_DAMAGE, owner); - uint32 darkVortex = sSpellMgr->GetSpellIdForDifficulty(SPELL_DARK_VORTEX_DAMAGE, owner); - int32 stacksCount = dmgInfo.GetSpellInfo()->Effects[EFFECT_0].CalcValue() / 1000 - 1; + // Twin Vortex part + uint32 lightVortex = SPELL_LIGHT_VORTEX_DAMAGE; + uint32 darkVortex = SPELL_DARK_VORTEX_DAMAGE; + int32 stacksCount = dmgInfo.GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue() / 1000 - 1; - if (lightVortex && darkVortex && stacksCount) + if (lightVortex && darkVortex && stacksCount) + { + if (dmgInfo.GetSpellInfo()->Id == darkVortex || dmgInfo.GetSpellInfo()->Id == lightVortex) { - if (dmgInfo.GetSpellInfo()->Id == darkVortex || dmgInfo.GetSpellInfo()->Id == lightVortex) + Aura* pAura = owner->GetAura(SPELL_POWERING_UP); + if (pAura) + { + pAura->ModStackAmount(stacksCount); + owner->CastSpell(owner, SPELL_POWERING_UP, true); + } + else { - Aura* pAura = owner->GetAura(poweringUp); - if (pAura) - { - pAura->ModStackAmount(stacksCount); - owner->CastSpell(owner, poweringUp, true); - } - else - { - owner->CastSpell(owner, poweringUp, true); - if (Aura* pTemp = owner->GetAura(poweringUp)) - pTemp->ModStackAmount(stacksCount); - } + owner->CastSpell(owner, SPELL_POWERING_UP, true); + if (Aura* pTemp = owner->GetAura(SPELL_POWERING_UP)) + pTemp->ModStackAmount(stacksCount); } } + } - // Picking floating balls - uint32 unleashedDark = sSpellMgr->GetSpellIdForDifficulty(SPELL_UNLEASHED_DARK, owner); - uint32 unleashedLight = sSpellMgr->GetSpellIdForDifficulty(SPELL_UNLEASHED_LIGHT, owner); + // Picking floating balls + uint32 unleashedDark = SPELL_UNLEASHED_DARK; + uint32 unleashedLight = SPELL_UNLEASHED_LIGHT; - if (unleashedDark && unleashedLight) + if (unleashedDark && unleashedLight) + { + if (dmgInfo.GetSpellInfo()->Id == unleashedDark || dmgInfo.GetSpellInfo()->Id == unleashedLight) { - if (dmgInfo.GetSpellInfo()->Id == unleashedDark || dmgInfo.GetSpellInfo()->Id == unleashedLight) + // need to do the things in this order, else players might have 100 charges of Powering Up without anything happening + Aura* pAura = owner->GetAura(SPELL_POWERING_UP); + if (pAura) + { + // 2 lines together add the correct amount of buff stacks + pAura->ModStackAmount(stacksCount); + owner->CastSpell(owner, SPELL_POWERING_UP, true); + } + else { - // need to do the things in this order, else players might have 100 charges of Powering Up without anything happening - Aura* pAura = owner->GetAura(poweringUp); - if (pAura) - { - // 2 lines together add the correct amount of buff stacks - pAura->ModStackAmount(stacksCount); - owner->CastSpell(owner, poweringUp, true); - } - else - { - owner->CastSpell(owner, poweringUp, true); - if (Aura* pTemp = owner->GetAura(poweringUp)) - pTemp->ModStackAmount(stacksCount); - } + owner->CastSpell(owner, SPELL_POWERING_UP, true); + if (Aura* pTemp = owner->GetAura(SPELL_POWERING_UP)) + pTemp->ModStackAmount(stacksCount); } } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index cb7e58cfe16..91da9ebd9be 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -274,7 +274,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript { EventStage = 6000; uint32 tributeChest = 0; - if (instance->GetSpawnMode() == RAID_DIFFICULTY_10MAN_HEROIC) + if (instance->GetSpawnMode() == DIFFICULTY_10_HC) { if (TrialCounter >= 50) tributeChest = GO_TRIBUTE_CHEST_10H_99; @@ -291,7 +291,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript } } } - else if (instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC) + else if (instance->GetSpawnMode() == DIFFICULTY_25_HC) { if (TrialCounter >= 50) tributeChest = GO_TRIBUTE_CHEST_25H_99; diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp index b91ca893955..f24ca7dd583 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_trollgore.cpp @@ -309,7 +309,7 @@ class spell_trollgore_invader_taunt : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].CalcValue())) + if (!sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_0)->CalcValue())) return false; return true; } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp index a014be4369e..ebad98de91a 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp @@ -89,7 +89,7 @@ class boss_falric : public CreatureScript || (_hopelessnessCount < 3 && me->HealthBelowPctDamaged(10, damage))) { if (_hopelessnessCount) - me->RemoveOwnedAura(sSpellMgr->GetSpellIdForDifficulty(HopelessnessHelper[_hopelessnessCount - 1], me)); + me->RemoveOwnedAura(HopelessnessHelper[_hopelessnessCount - 1]); DoCast(me, HopelessnessHelper[_hopelessnessCount]); ++_hopelessnessCount; } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index eeb05f44a71..c99ebddae37 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -2390,7 +2390,7 @@ class spell_hor_evasion : public SpellScriptLoader return; float angle = pos.GetAngle(&home); - float dist = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + float dist = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); target->MovePosition(pos, dist, angle); dest.Relocate(pos); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 6053ff295a9..d289d494d62 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -553,8 +553,7 @@ class spell_blood_queen_vampiric_bite : public SpellScriptLoader if (GetCaster()->GetTypeId() != TYPEID_PLAYER) return; - uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(SPELL_FRENZIED_BLOODTHIRST, GetCaster()); - GetCaster()->RemoveAura(spellId, ObjectGuid::Empty, 0, AURA_REMOVE_BY_ENEMY_SPELL); + GetCaster()->RemoveAura(SPELL_FRENZIED_BLOODTHIRST, ObjectGuid::Empty, 0, AURA_REMOVE_BY_ENEMY_SPELL); GetCaster()->CastSpell(GetCaster(), SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR, TRIGGERED_FULL_MASK); // Shadowmourne questline @@ -807,7 +806,7 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg : public SpellScriptLoader void PeriodicTick(AuraEffect const* aurEff) { SpellInfo const* damageSpell = sSpellMgr->EnsureSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE); - int32 damage = damageSpell->Effects[EFFECT_0].CalcValue(); + int32 damage = damageSpell->GetEffect(EFFECT_0)->CalcValue(); float multiplier = 0.3375f + 0.1f * uint32(aurEff->GetTickNumber()/10); // do not convert to 0.01f - we need tick number/10 as INT (damage increases every 10 ticks) damage = int32(damage * multiplier); GetTarget()->CastCustomSpell(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetTarget(), true); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp index b1f6a4a5e83..008a89030a7 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp @@ -377,11 +377,7 @@ class spell_festergut_pungent_blight : public SpellScriptLoader void HandleScript(SpellEffIndex /*effIndex*/) { - // Get Inhaled Blight id for our difficulty - uint32 blightId = sSpellMgr->GetSpellIdForDifficulty(uint32(GetEffectValue()), GetCaster()); - - // ...and remove it - GetCaster()->RemoveAurasDueToSpell(blightId); + GetCaster()->RemoveAurasDueToSpell(uint32(GetEffectValue())); GetCaster()->ToCreature()->AI()->Talk(EMOTE_PUNGENT_BLIGHT); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 416c27b7353..080880608d6 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -1847,7 +1847,7 @@ class spell_igb_rocket_pack : public SpellScriptLoader void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { SpellInfo const* damageInfo = sSpellMgr->EnsureSpellInfo(SPELL_ROCKET_PACK_DAMAGE); - GetTarget()->CastCustomSpell(SPELL_ROCKET_PACK_DAMAGE, SPELLVALUE_BASE_POINT0, 2 * (damageInfo->Effects[EFFECT_0].CalcValue() + aurEff->GetTickNumber() * aurEff->GetPeriod()), NULL, TRIGGERED_FULL_MASK); + GetTarget()->CastCustomSpell(SPELL_ROCKET_PACK_DAMAGE, SPELLVALUE_BASE_POINT0, 2 * (damageInfo->GetEffect(EFFECT_0)->CalcValue() + aurEff->GetTickNumber() * aurEff->GetPeriod()), NULL, TRIGGERED_FULL_MASK); GetTarget()->CastSpell(NULL, SPELL_ROCKET_BURST, TRIGGERED_FULL_MASK); } @@ -1977,7 +1977,7 @@ class spell_igb_periodic_trigger_with_power_cost : public SpellScriptLoader void HandlePeriodicTick(AuraEffect const* /*aurEff*/) { PreventDefaultAction(); - GetTarget()->CastSpell(GetTarget(), GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); + GetTarget()->CastSpell(GetTarget(), GetSpellInfo()->GetEffect(EFFECT_0)->TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index 3e78865c924..834b0aeb5e1 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -288,7 +288,7 @@ class boss_lady_deathwhisper : public CreatureScript events.ScheduleEvent(EVENT_P1_SUMMON_WAVE, 5000, 0, PHASE_ONE); events.ScheduleEvent(EVENT_P1_SHADOW_BOLT, urand(5500, 6000), 0, PHASE_ONE); events.ScheduleEvent(EVENT_P1_EMPOWER_CULTIST, urand(20000, 30000), 0, PHASE_ONE); - if (GetDifficulty() != RAID_DIFFICULTY_10MAN_NORMAL) + if (GetDifficulty() != DIFFICULTY_10_N) events.ScheduleEvent(EVENT_DOMINATE_MIND_H, 27000); Talk(SAY_AGGRO); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 2e360e19b75..3a66d3e1363 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -576,7 +576,7 @@ class spell_marrowgar_coldflame_damage : public SpellScriptLoader if (target->HasAura(SPELL_IMPALED)) return false; - if (target->GetExactDist2d(GetOwner()) > GetSpellInfo()->Effects[EFFECT_0].CalcRadius()) + if (target->GetExactDist2d(GetOwner()) > GetSpellInfo()->GetEffect(target, EFFECT_0)->CalcRadius()) return false; if (Aura* aur = target->GetAura(GetId())) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 8f5ca0b4322..d0bf573ba19 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -395,14 +395,14 @@ class boss_professor_putricide : public CreatureScript { SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_CREATE_CONCOCTION); DoCast(me, SPELL_CREATE_CONCOCTION); - events.ScheduleEvent(EVENT_PHASE_TRANSITION, sSpellMgr->GetSpellForDifficultyFromSpell(spell, me)->CalcCastTime() + 100); + events.ScheduleEvent(EVENT_PHASE_TRANSITION, spell->CalcCastTime() + 100); break; } case PHASE_COMBAT_3: { SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_GUZZLE_POTIONS); DoCast(me, SPELL_GUZZLE_POTIONS); - events.ScheduleEvent(EVENT_PHASE_TRANSITION, sSpellMgr->GetSpellForDifficultyFromSpell(spell, me)->CalcCastTime() + 100); + events.ScheduleEvent(EVENT_PHASE_TRANSITION, spell->CalcCastTime() + 100); break; } default: @@ -725,7 +725,7 @@ class npc_putricide_oozeAI : public ScriptedAI void SpellHitTarget(Unit* /*target*/, SpellInfo const* spell) override { - if (!_newTargetSelectTimer && spell->Id == sSpellMgr->GetSpellIdForDifficulty(_hitTargetSpellId, me)) + if (!_newTargetSelectTimer && spell->Id == _hitTargetSpellId) _newTargetSelectTimer = 1000; } @@ -1031,7 +1031,7 @@ class spell_putricide_unstable_experiment : public SpellScriptLoader break; } - GetCaster()->CastSpell(target, uint32(GetSpellInfo()->Effects[stage].CalcValue()), true, NULL, NULL, GetCaster()->GetGUID()); + GetCaster()->CastSpell(target, uint32(GetSpellInfo()->GetEffect(stage)->CalcValue()), true, NULL, NULL, GetCaster()->GetGUID()); } void Register() override @@ -1057,11 +1057,10 @@ class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader void HandleDummy(SpellEffIndex /*effIndex*/) { - uint32 adhesiveId = sSpellMgr->GetSpellIdForDifficulty(SPELL_VOLATILE_OOZE_ADHESIVE, GetCaster()); - if (GetHitUnit()->HasAura(adhesiveId)) + if (GetHitUnit()->HasAura(SPELL_VOLATILE_OOZE_ADHESIVE)) { GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true); - GetHitUnit()->RemoveAurasDueToSpell(adhesiveId, GetCaster()->GetGUID(), 0, AURA_REMOVE_BY_ENEMY_SPELL); + GetHitUnit()->RemoveAurasDueToSpell(SPELL_VOLATILE_OOZE_ADHESIVE, GetCaster()->GetGUID(), 0, AURA_REMOVE_BY_ENEMY_SPELL); } } @@ -1089,12 +1088,12 @@ class spell_putricide_choking_gas_bomb : public SpellScriptLoader void HandleScript(SpellEffIndex /*effIndex*/) { uint32 skipIndex = urand(0, 2); - for (uint32 i = 0; i < 3; ++i) + for (SpellEffectInfo const* effect : GetSpellInfo()->GetEffectsForDifficulty(GetCaster()->GetMap()->GetDifficulty())) { - if (i == skipIndex) + if (!effect || effect->EffectIndex == skipIndex) continue; - uint32 spellId = uint32(GetSpellInfo()->Effects[i].CalcValue()); + uint32 spellId = uint32(effect->CalcValue()); GetCaster()->CastSpell(GetCaster(), spellId, true, NULL, NULL, GetCaster()->GetGUID()); } } @@ -1141,7 +1140,7 @@ class spell_putricide_unbound_plague : public SpellScriptLoader } - targets.remove_if(Trinity::UnitAuraCheck(true, sSpellMgr->GetSpellIdForDifficulty(SPELL_UNBOUND_PLAGUE, GetCaster()))); + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_UNBOUND_PLAGUE)); Trinity::Containers::RandomResizeList(targets, 1); } @@ -1154,15 +1153,13 @@ class spell_putricide_unbound_plague : public SpellScriptLoader if (!instance) return; - uint32 plagueId = sSpellMgr->GetSpellIdForDifficulty(SPELL_UNBOUND_PLAGUE, GetCaster()); - - if (!GetHitUnit()->HasAura(plagueId)) + if (!GetHitUnit()->HasAura(SPELL_UNBOUND_PLAGUE)) { if (Creature* professor = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_PROFESSOR_PUTRICIDE))) { - if (Aura* oldPlague = GetCaster()->GetAura(plagueId, professor->GetGUID())) + if (Aura* oldPlague = GetCaster()->GetAura(SPELL_UNBOUND_PLAGUE, professor->GetGUID())) { - if (Aura* newPlague = professor->AddAura(plagueId, GetHitUnit())) + if (Aura* newPlague = professor->AddAura(SPELL_UNBOUND_PLAGUE, GetHitUnit())) { newPlague->SetMaxDuration(oldPlague->GetMaxDuration()); newPlague->SetDuration(oldPlague->GetDuration()); @@ -1258,11 +1255,10 @@ class spell_putricide_mutated_plague : public SpellScriptLoader if (!caster) return; - uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + uint32 triggerSpell = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell; SpellInfo const* spell = sSpellMgr->GetSpellInfo(triggerSpell); - spell = sSpellMgr->GetSpellForDifficultyFromSpell(spell, caster); - int32 damage = spell->Effects[EFFECT_0].CalcValue(caster); + int32 damage = spell->GetEffect(EFFECT_0)->CalcValue(caster); float multiplier = 2.0f; if (GetTarget()->GetMap()->GetSpawnMode() & 1) multiplier = 3.0f; @@ -1275,13 +1271,13 @@ class spell_putricide_mutated_plague : public SpellScriptLoader void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - uint32 healSpell = uint32(GetSpellInfo()->Effects[EFFECT_0].CalcValue()); + uint32 healSpell = uint32(GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue()); SpellInfo const* healSpellInfo = sSpellMgr->GetSpellInfo(healSpell); if (!healSpellInfo) return; - int32 heal = healSpellInfo->Effects[0].CalcValue() * GetStackAmount(); + int32 heal = healSpellInfo->GetEffect(EFFECT_0)->CalcValue() * GetStackAmount(); GetTarget()->CastCustomSpell(healSpell, SPELLVALUE_BASE_POINT0, heal, GetTarget(), true, NULL, NULL, GetCasterGUID()); } @@ -1445,8 +1441,8 @@ class spell_putricide_mutated_transformation : public SpellScriptLoader return; } - uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue); - SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetSpellInfo()->Effects[effIndex].MiscValueB)); + uint32 entry = uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValue); + SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValueB)); uint32 duration = uint32(GetSpellInfo()->GetDuration()); Position pos = caster->GetPosition(); @@ -1543,8 +1539,7 @@ class spell_putricide_clear_aura_effect_value : public SpellScriptLoader void HandleScript(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - uint32 auraId = sSpellMgr->GetSpellIdForDifficulty(uint32(GetEffectValue()), GetCaster()); - GetHitUnit()->RemoveAurasDueToSpell(auraId); + GetHitUnit()->RemoveAurasDueToSpell(GetEffectValue()); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index d5c07fb6942..ee948789bc4 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -745,7 +745,7 @@ class spell_rotface_unstable_ooze_explosion : public SpellScriptLoader if (!GetExplTargetDest()) return; - uint32 triggered_spell_id = GetSpellInfo()->Effects[effIndex].TriggerSpell; + uint32 triggered_spell_id = GetSpellInfo()->GetEffect(effIndex)->TriggerSpell; float x, y, z; GetExplTargetDest()->GetPosition(x, y, z); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 8e659a746ed..ab19ffe7fed 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -409,10 +409,9 @@ class boss_sindragosa : public CreatureScript void SpellHitTarget(Unit* target, SpellInfo const* spell) override { - if (uint32 spellId = sSpellMgr->GetSpellIdForDifficulty(70127, me)) - if (spellId == spell->Id) - if (Aura const* mysticBuffet = target->GetAura(spell->Id)) - _mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount()); + if (spell->Id == 70127) + if (Aura const* mysticBuffet = target->GetAura(spell->Id)) + _mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount()); } @@ -1546,7 +1545,7 @@ class spell_frostwarden_handler_focus_fire : public SpellScriptLoader PreventDefaultAction(); if (Unit* caster = GetCaster()) { - caster->AddThreat(GetTarget(), -float(GetSpellInfo()->Effects[EFFECT_1].CalcValue())); + caster->AddThreat(GetTarget(), -float(GetSpellInfo()->GetEffect(caster, EFFECT_1)->CalcValue())); caster->GetAI()->SetData(DATA_WHELP_MARKER, 0); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 03c26ba2e09..caba9ff5262 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -2437,7 +2437,7 @@ class spell_the_lich_king_summon_into_air : public SpellScriptLoader dest->RelocateOffset(offset); GetHitDest()->RelocateOffset(offset); // spirit bombs get higher - if (GetSpellInfo()->Effects[effIndex].MiscValue == NPC_SPIRIT_BOMB) + if (GetSpellInfo()->GetEffect(effIndex)->MiscValue == NPC_SPIRIT_BOMB) { dest->RelocateOffset(offset); GetHitDest()->RelocateOffset(offset); @@ -2641,7 +2641,7 @@ class spell_the_lich_king_vile_spirits : public SpellScriptLoader void OnPeriodic(AuraEffect const* aurEff) { if (_is25Man || ((aurEff->GetTickNumber() - 1) % 5)) - GetTarget()->CastSpell((Unit*)NULL, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, NULL, aurEff, GetCasterGUID()); + GetTarget()->CastSpell((Unit*)NULL, aurEff->GetSpellEffectInfo()->TriggerSpell, true, NULL, aurEff, GetCasterGUID()); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 49e24f54b02..eebf5a2c2ea 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -1227,7 +1227,7 @@ class spell_dreamwalker_summoner : public SpellScriptLoader if (!GetHitUnit()) return; - GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->Effects[effIndex].TriggerSpell, true, NULL, NULL, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); + GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, true, NULL, NULL, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); } void Register() override @@ -1306,7 +1306,7 @@ class spell_dreamwalker_summon_suppresser_effect : public SpellScriptLoader if (!GetHitUnit()) return; - GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->Effects[effIndex].TriggerSpell, true, NULL, NULL, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); + GetHitUnit()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, true, NULL, NULL, GetCaster()->GetInstanceScript()->GetGuidData(DATA_VALITHRIA_LICH_KING)); } void Register() override @@ -1442,7 +1442,7 @@ class spell_dreamwalker_twisted_nightmares : public SpellScriptLoader // return; if (InstanceScript* instance = GetHitUnit()->GetInstanceScript()) - GetHitUnit()->CastSpell((Unit*)NULL, GetSpellInfo()->Effects[effIndex].TriggerSpell, true, NULL, NULL, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)); + GetHitUnit()->CastSpell((Unit*)NULL, GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, true, NULL, NULL, instance->GetGuidData(DATA_VALITHRIA_DREAMWALKER)); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index abe178a874d..ab7606f5e6f 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -1799,7 +1799,7 @@ class spell_icc_sprit_alarm : public SpellScriptLoader { PreventHitDefaultEffect(effIndex); uint32 trapId = 0; - switch (GetSpellInfo()->Effects[effIndex].MiscValue) + switch (GetSpellInfo()->GetEffect(effIndex)->MiscValue) { case EVENT_AWAKEN_WARD_1: trapId = GO_SPIRIT_ALARM_1; @@ -1838,7 +1838,7 @@ class spell_icc_sprit_alarm : public SpellScriptLoader void Register() override { - OnEffectHit += SpellEffectFn(spell_icc_sprit_alarm_SpellScript::HandleEvent, EFFECT_2, SPELL_EFFECT_SEND_EVENT); + OnEffectHit += SpellEffectFn(spell_icc_sprit_alarm_SpellScript::HandleEvent, EFFECT_1, SPELL_EFFECT_SEND_EVENT); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index 35402771494..90b252a47ce 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -80,7 +80,7 @@ public: Initialize(); - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_25_N) { Position pos; @@ -121,7 +121,7 @@ public: events.ScheduleEvent(EVENT_LOCUST, 90000); events.ScheduleEvent(EVENT_BERSERK, 600000); - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_10_N) events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000, 20000)); } @@ -160,7 +160,7 @@ public: case EVENT_IMPALE: //Cast Impale on a random target //Do NOT cast it when we are afflicted by locust swarm - if (!me->HasAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_LOCUST_SWARM, me))) + if (!me->HasAura(SPELL_LOCUST_SWARM)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) DoCast(target, SPELL_IMPALE); events.ScheduleEvent(EVENT_IMPALE, urand(10000, 20000)); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index dcb004cc3a0..568df379f15 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -192,7 +192,7 @@ class npc_faerlina_add : public CreatureScript void Reset() override { - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { + if (GetDifficulty() == DIFFICULTY_10_N) { me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_BIND, true); me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true); } @@ -200,7 +200,7 @@ class npc_faerlina_add : public CreatureScript void JustDied(Unit* /*killer*/) override { - if (_instance && GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (_instance && GetDifficulty() == DIFFICULTY_10_N) if (Creature* faerlina = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FAERLINA))) DoCast(faerlina, SPELL_WIDOWS_EMBRACE); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 39381f38d67..a70d354b966 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -259,7 +259,7 @@ class boss_gothik : public CreatureScript void DoGothikSummon(uint32 entry) { - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_25_N) { switch (entry) { @@ -421,9 +421,9 @@ class boss_gothik : public CreatureScript case EVENT_SUMMON: if (waves[waveCount].entry) { - if ((waves[waveCount].mode == 2) && (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) + if ((waves[waveCount].mode == 2) && (GetDifficulty() == DIFFICULTY_25_N)) DoGothikSummon(waves[waveCount].entry); - else if ((waves[waveCount].mode == 0) && (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) + else if ((waves[waveCount].mode == 0) && (GetDifficulty() == DIFFICULTY_10_N)) DoGothikSummon(waves[waveCount].entry); else if (waves[waveCount].mode == 1) DoGothikSummon(waves[waveCount].entry); @@ -443,9 +443,9 @@ class boss_gothik : public CreatureScript if (waves[waveCount].mode == 1) events.ScheduleEvent(EVENT_SUMMON, waves[waveCount].time); - else if ((waves[waveCount].mode == 2) && (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)) + else if ((waves[waveCount].mode == 2) && (GetDifficulty() == DIFFICULTY_25_N)) events.ScheduleEvent(EVENT_SUMMON, waves[waveCount].time); - else if ((waves[waveCount].mode == 0) && (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL)) + else if ((waves[waveCount].mode == 0) && (GetDifficulty() == DIFFICULTY_10_N)) events.ScheduleEvent(EVENT_SUMMON, waves[waveCount].time); else events.ScheduleEvent(EVENT_SUMMON, 0); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index 929c52a986c..ba54b5150e4 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -194,7 +194,7 @@ class spell_grobbulus_poison_cloud : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell)) + if (!sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_0)->TriggerSpell)) return false; return true; } @@ -203,7 +203,7 @@ class spell_grobbulus_poison_cloud : public SpellScriptLoader { PreventDefaultAction(); - uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + uint32 triggerSpell = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell; int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_RADIUS_MOD, mod, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 87466b6bf41..102d1f0fb5b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -415,7 +415,7 @@ public: events.ScheduleEvent(EVENT_DETONATE, urand(30000, 40000)); events.ScheduleEvent(EVENT_FISSURE, urand(10000, 30000)); events.ScheduleEvent(EVENT_BLAST, urand(60000, 120000)); - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_25_N) events.ScheduleEvent(EVENT_CHAIN, urand(30000, 60000)); Phase = 2; break; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index fc376a5439f..cc7e38173c8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -112,7 +112,7 @@ public: { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP)) { - target->RemoveAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_WEB_SPRAY, me)); + target->RemoveAura(SPELL_WEB_SPRAY); uint8 pos = rand32() % MAX_POS_WRAP; target->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20); if (Creature* wrap = DoSummon(NPC_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN)) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index 0e07ff027f6..be4c8583377 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -106,7 +106,7 @@ public: events.ScheduleEvent(EVENT_BALCONY, 110000); events.ScheduleEvent(EVENT_CURSE, 10000 + rand32() % 15000); events.ScheduleEvent(EVENT_WARRIOR, 30000); - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_25_N) events.ScheduleEvent(EVENT_BLINK, urand(20000, 40000)); } } diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index b66bc07f2c8..bada44b20a0 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -387,11 +387,11 @@ class instance_naxxramas : public InstanceMapScript switch (criteria_id) { case 7600: // Criteria for achievement 2176: And They Would All Go Down Together 15sec of each other 10-man - if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_10MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) + if (Difficulty(instance->GetSpawnMode()) == DIFFICULTY_10_N && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) return true; return false; case 7601: // Criteria for achievement 2177: And They Would All Go Down Together 15sec of each other 25-man - if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) + if (Difficulty(instance->GetSpawnMode()) == DIFFICULTY_25_N && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15) return true; return false; // Difficulty checks are done on DB. diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 813e51ad23c..b4f27710e03 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -406,7 +406,7 @@ public: { _summonDeaths = value; - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_10_N) { if (_summonDeaths == MAX_SUMMONS_PHASE_TWO_10MAN) { @@ -414,7 +414,7 @@ public: DoAction(ACTION_HANDLE_P_THREE_INTRO); } } - else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + else if (GetDifficulty() == DIFFICULTY_25_N) { if (_summonDeaths == MAX_SUMMONS_PHASE_TWO_25MAN) { @@ -862,7 +862,7 @@ public: if (_arcaneReinforcements) { - for (uint8 rangeDisks = 0; rangeDisks < (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 4 : 5); rangeDisks++) + for (uint8 rangeDisks = 0; rangeDisks < (GetDifficulty() == DIFFICULTY_10_N ? 4 : 5); rangeDisks++) { Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]); @@ -878,7 +878,7 @@ public: _arcaneReinforcements = false; - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_25_N) events.ScheduleEvent(EVENT_DELAYED_REINFORCEMENTS, 1*IN_MILLISECONDS, 0, PHASE_TWO); } break; @@ -958,7 +958,7 @@ public: SetPhase(PHASE_THREE, true); break; case EVENT_SURGE_OF_POWER_P_THREE: - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_10_N) { if (Unit* tempSurgeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY)) { @@ -975,7 +975,7 @@ public: } } } - else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + else if (GetDifficulty() == DIFFICULTY_25_N) { memset(_surgeTargetGUID, 0, sizeof(_surgeTargetGUID)); DoCastAOE(SPELL_SURGE_OF_POWER_WARNING_SELECTOR_25, true); @@ -1007,10 +1007,10 @@ public: Talk(SAY_DEATH); if (Creature* alexstraszaGiftBoxBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GIFT_BOX_BUNNY_GUID))) { - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (GetDifficulty() == DIFFICULTY_10_N) alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_10, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(), HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0); - else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + else if (GetDifficulty() == DIFFICULTY_25_N) alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_25, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(), HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0); } @@ -1786,10 +1786,10 @@ class spell_malygos_arcane_storm : public SpellScriptLoader { // Resize list only to objects that are vehicles. IsCreatureVehicleCheck check(true); - Trinity::Containers::RandomResizeList(targets, check, (malygos->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 4 : 10)); + Trinity::Containers::RandomResizeList(targets, check, (malygos->GetMap()->GetDifficulty() == DIFFICULTY_10_N ? 4 : 10)); } else - Trinity::Containers::RandomResizeList(targets, (malygos->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 4 : 10)); + Trinity::Containers::RandomResizeList(targets, (malygos->GetMap()->GetDifficulty() == DIFFICULTY_10_N ? 4 : 10)); } void HandleVisual(SpellEffIndex /*effIndex*/) @@ -1948,7 +1948,7 @@ class spell_arcane_overload : public SpellScriptLoader { Creature* arcaneOverload = GetCaster()->ToCreature(); targets.remove_if(ExactDistanceCheck(arcaneOverload, - GetSpellInfo()->Effects[EFFECT_0].CalcRadius(arcaneOverload) * arcaneOverload->GetObjectScale())); + GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(arcaneOverload) * arcaneOverload->GetObjectScale())); } void Register() override @@ -2475,9 +2475,9 @@ class spell_alexstrasza_gift_beam_visual : public SpellScriptLoader { if (Creature* target = GetTarget()->ToCreature()) { - if (target->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (target->GetMap()->GetDifficulty() == DIFFICULTY_10_N) _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_10, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0); - else if (target->GetMap()->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + else if (target->GetMap()->GetDifficulty() == DIFFICULTY_25_N) _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_25, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0); } } diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index 90decfbf46e..b689df3c977 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -92,14 +92,14 @@ public: platformGUID = go->GetGUID(); break; case GO_FOCUSING_IRIS_10: - if (instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (instance->GetDifficulty() == DIFFICULTY_10_N) { irisGUID = go->GetGUID(); focusingIrisPosition = go->GetPosition(); } break; case GO_FOCUSING_IRIS_25: - if (instance->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + if (instance->GetDifficulty() == DIFFICULTY_25_N) { irisGUID = go->GetGUID(); focusingIrisPosition = go->GetPosition(); @@ -110,11 +110,11 @@ public: exitPortalPosition = go->GetPosition(); break; case GO_HEART_OF_MAGIC_10: - if (instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (instance->GetDifficulty() == DIFFICULTY_10_N) heartOfMagicGUID = go->GetGUID(); break; case GO_HEART_OF_MAGIC_25: - if (instance->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + if (instance->GetDifficulty() == DIFFICULTY_25_N) heartOfMagicGUID = go->GetGUID(); break; } @@ -240,7 +240,7 @@ public: PowerSparksHandling(); break; case DATA_RESPAWN_IRIS: - SpawnGameObject(instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? GO_FOCUSING_IRIS_10 : GO_FOCUSING_IRIS_25, focusingIrisPosition); + SpawnGameObject(instance->GetDifficulty() == DIFFICULTY_10_N ? GO_FOCUSING_IRIS_10 : GO_FOCUSING_IRIS_25, focusingIrisPosition); break; } } diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index 3f882e0b99e..b0c4be44ee8 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -418,7 +418,7 @@ class spell_oculus_ride_ruby_emerald_amber_drake_que : public SpellScriptLoader // caster of the triggered spell is wrong for an unknown reason, handle it here correctly PreventDefaultAction(); if (Unit* caster = GetCaster()) - GetTarget()->CastSpell(caster, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true); + GetTarget()->CastSpell(caster, aurEff->GetSpellEffectInfo()->TriggerSpell, true); } void Register() override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index fc29369c28f..c0760afec23 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -161,7 +161,7 @@ public: Talk(EMOTE_NOVA); DoCast(me, SPELL_LIGHTNING_NOVA); - me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me)); + me->RemoveAurasDueToSpell(SPELL_PULSING_SHOCKWAVE); m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura m_uiLightningNova_Timer = urand(20000, 21000); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index d63d5e87923..3a707e7fa70 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -428,7 +428,7 @@ public: void SpellHit(Unit* /*pCaster*/, const SpellInfo* pSpell) override { // This is the dummy effect of the spells - if (pSpell->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_SHATTER, me)) + if (pSpell->Id == SPELL_SHATTER) if (me->GetEntry() == NPC_BRITTLE_GOLEM) me->DespawnOrUnsummon(); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp index 07cdfa3353c..d911bf07439 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp @@ -182,7 +182,7 @@ class spell_krystallus_shatter_effect : public SpellScriptLoader if (!GetHitUnit()) return; - float radius = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + float radius = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); if (!radius) return; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp index bb7a8592e04..41da9ec09ea 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp @@ -615,7 +615,7 @@ class boss_stormcaller_brundir : public CreatureScript break; case EVENT_GROUND: //me->SetLevitate(false); - me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_LIGHTNING_TENDRILS, me)); + me->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS); me->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_VISUAL); DoStartMovement(me->GetVictim()); events.CancelEvent(EVENT_GROUND); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 40c189a8da2..b6ac62257d0 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -1793,7 +1793,7 @@ class spell_vehicle_throw_passenger : public SpellScriptLoader } } } - if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->Effects[effIndex].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct + if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->GetEffect(effIndex)->CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct passenger->EnterVehicle(target, 0); else { diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 93fee8d1964..5952c9f8501 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -1583,7 +1583,7 @@ class spell_freya_iron_roots : public SpellScriptLoader void HandleSummon(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue); + uint32 entry = uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValue); Position pos = GetCaster()->GetPosition(); // Not good at all, but this prevents having roots in a different position then player diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index 419052baddc..5ac0024c032 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -454,11 +454,11 @@ class spell_ulduar_cancel_stone_grip : public SpellScriptLoader switch (target->GetMap()->GetDifficulty()) { - case RAID_DIFFICULTY_10MAN_NORMAL: - target->RemoveAura(GetSpellInfo()->Effects[EFFECT_0].CalcValue()); + case DIFFICULTY_10_N: + target->RemoveAura(GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue()); break; - case RAID_DIFFICULTY_25MAN_NORMAL: - target->RemoveAura(GetSpellInfo()->Effects[EFFECT_1].CalcValue()); + case DIFFICULTY_25_N: + target->RemoveAura(GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()); break; default: break; @@ -534,7 +534,7 @@ class spell_ulduar_stone_grip_absorb : public SpellScriptLoader if (!GetOwner()->ToCreature()) return; - uint32 rubbleStalkerEntry = (GetOwner()->GetMap()->GetDifficulty() == DUNGEON_DIFFICULTY_NORMAL ? 33809 : 33942); + uint32 rubbleStalkerEntry = (GetOwner()->GetMap()->GetDifficulty() == DIFFICULTY_NORMAL ? 33809 : 33942); Creature* rubbleStalker = GetOwner()->FindNearestCreature(rubbleStalkerEntry, 200.0f, true); if (rubbleStalker) rubbleStalker->CastSpell(rubbleStalker, SPELL_STONE_GRIP_CANCEL, true); @@ -643,7 +643,7 @@ class spell_kologarn_summon_focused_eyebeam : public SpellScriptLoader void HandleForceCast(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - GetCaster()->CastSpell(GetCaster(), GetSpellInfo()->Effects[effIndex].TriggerSpell, true); + GetCaster()->CastSpell(GetCaster(), GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, true); } void Register() override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index cad6b045120..947b1ce9b86 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -237,7 +237,7 @@ class boss_razorscale_controller : public CreatureScript { case ACTION_HARPOON_BUILD: events.ScheduleEvent(EVENT_BUILD_HARPOON_1, 50000); - if (me->GetMap()->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL) + if (me->GetMap()->GetSpawnMode() == DIFFICULTY_25_N) events.ScheduleEvent(EVENT_BUILD_HARPOON_3, 90000); break; case ACTION_PLACE_BROKEN_HARPOON: @@ -1075,7 +1075,7 @@ class spell_razorscale_devouring_flame : public SpellScriptLoader { PreventHitDefaultEffect(effIndex); Unit* caster = GetCaster(); - uint32 entry = uint32(GetSpellInfo()->Effects[effIndex].MiscValue); + uint32 entry = uint32(GetSpellInfo()->GetEffect(effIndex)->MiscValue); WorldLocation const* summonLocation = GetExplTargetDest(); if (!caster || !summonLocation) return; diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index d49a23c85dd..1e55eb37007 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -572,8 +572,8 @@ public: void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override { if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)) - for (uint8 i = 0; i < 3; ++i) - if (spell->Effects[i].Effect == SPELL_EFFECT_INTERRUPT_CAST) + for (SpellEffectInfo const* effect : spell->GetEffectsForDifficulty(me->GetMap()->GetDifficulty())) + if (effect->Effect == SPELL_EFFECT_INTERRUPT_CAST) if (me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_SOUL_SHOCK || me->GetCurrentSpell(CURRENT_GENERIC_SPELL)->m_spellInfo->Id == SPELL_DEADEN) me->InterruptSpell(CURRENT_GENERIC_SPELL, false); diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp index 2cee741cbf3..a3404e048ce 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp @@ -317,7 +317,7 @@ class spell_gruul_shatter_effect : public SpellScriptLoader if (!GetHitUnit()) return; - float radius = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + float radius = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); if (!radius) return; diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp index a0673d4aced..c0a7f85cb63 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp @@ -154,7 +154,7 @@ class spell_broggok_poison_cloud : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell)) + if (!sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_0)->TriggerSpell)) return false; return true; } @@ -163,7 +163,7 @@ class spell_broggok_poison_cloud : public SpellScriptLoader { PreventDefaultAction(); - uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + uint32 triggerSpell = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell; int32 mod = int32(((float(aurEff->GetTickNumber()) / aurEff->GetTotalTicks()) * 0.9f + 0.1f) * 10000 * 2 / 3); GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_RADIUS_MOD, mod, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index cd433000e8e..7e30ae1a931 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -542,7 +542,7 @@ class spell_astromancer_wrath_of_the_astromancer : public SpellScriptLoader return; Unit* target = GetUnitOwner(); - target->CastSpell(target, GetSpellInfo()->Effects[EFFECT_1].CalcValue(), false); + target->CastSpell(target, GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(), false); } void Register() override diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 0ff7d116a88..f899bb02cc0 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -89,7 +89,7 @@ class spell_dk_anti_magic_shell_raid : public SpellScriptLoader bool Load() override { - absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); + absorbPct = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(GetCaster()); return true; } @@ -138,8 +138,8 @@ class spell_dk_anti_magic_shell_self : public SpellScriptLoader uint32 absorbPct, hpPct; bool Load() override { - absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); - hpPct = GetSpellInfo()->Effects[EFFECT_1].CalcValue(GetCaster()); + absorbPct = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(GetCaster()); + hpPct = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(GetCaster()); return true; } @@ -203,7 +203,7 @@ class spell_dk_anti_magic_zone : public SpellScriptLoader bool Load() override { - absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); + absorbPct = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(GetCaster()); return true; } @@ -217,7 +217,7 @@ class spell_dk_anti_magic_zone : public SpellScriptLoader void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/) { SpellInfo const* talentSpell = sSpellMgr->EnsureSpellInfo(SPELL_DK_ANTI_MAGIC_SHELL_TALENT); - amount = talentSpell->Effects[EFFECT_0].CalcValue(GetCaster()); + amount = talentSpell->GetEffect(EFFECT_0)->CalcValue(GetCaster()); if (Player* player = GetCaster()->ToPlayer()) amount += int32(2 * player->GetTotalAttackPowerValue(BASE_ATTACK)); } @@ -628,7 +628,7 @@ class spell_dk_death_strike : public SpellScriptLoader if (AuraEffect* enabler = GetCaster()->GetAuraEffect(SPELL_DK_DEATH_STRIKE_ENABLER, EFFECT_0, GetCaster()->GetGUID())) { // Call CalculateAmount() to constantly fire the AuraEffect's HandleCalcAmount method - int32 heal = CalculatePct(enabler->CalculateAmount(GetCaster()), GetSpellInfo()->Effects[EFFECT_0].ChainAmplitude); + int32 heal = CalculatePct(enabler->CalculateAmount(GetCaster()), GetSpellInfo()->GetEffect(EFFECT_0)->ChainAmplitude); if (AuraEffect const* aurEff = GetCaster()->GetAuraEffectOfRankedSpell(SPELL_DK_IMPROVED_DEATH_STRIKE, EFFECT_2)) heal = AddPct(heal, aurEff->GetAmount()); @@ -1231,12 +1231,13 @@ class spell_dk_raise_dead : public SpellScriptLoader private: bool Validate(SpellInfo const* spellInfo) override { - if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue()) - || !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_2].CalcValue()) + // 6.x effects changed + /*if (!sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_1)->CalcValue()) + || !sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_2)->CalcValue()) || !sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT) || !sSpellMgr->GetSpellInfo(SPELL_DK_MASTER_OF_GHOULS)) - return false; - return true; + return false;*/ + return false; } bool Load() override @@ -1314,10 +1315,10 @@ class spell_dk_raise_dead : public SpellScriptLoader // Do we have talent Master of Ghouls? if (GetCaster()->HasAura(SPELL_DK_MASTER_OF_GHOULS)) // summon as pet - return GetSpellInfo()->Effects[EFFECT_2].CalcValue(); + return GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue(); // or guardian - return GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + return GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); } void HandleRaiseDead(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 184e12cdccb..ac977c3cdcd 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -175,7 +175,7 @@ class spell_dru_eclipse_energize : public SpellScriptLoader { case SPELL_DRUID_WRATH: { - energizeAmount = -GetSpellInfo()->Effects[effIndex].BasePoints; // -13 + energizeAmount = -GetSpellInfo()->GetEffect(effIndex)->BasePoints; // -13 // If we are set to fill the lunar side or we've just logged in with 0 power.. if ((!caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER)) || caster->GetPower(POWER_ECLIPSE) == 0) @@ -192,7 +192,7 @@ class spell_dru_eclipse_energize : public SpellScriptLoader } case SPELL_DRUID_STARFIRE: { - energizeAmount = GetSpellInfo()->Effects[effIndex].BasePoints; // 20 + energizeAmount = GetSpellInfo()->GetEffect(effIndex)->BasePoints; // 20 // If we are set to fill the solar side or we've just logged in with 0 power.. if ((!caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER)) || caster->GetPower(POWER_ECLIPSE) == 0) @@ -213,7 +213,7 @@ class spell_dru_eclipse_energize : public SpellScriptLoader if ((!caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER)) || caster->GetPower(POWER_ECLIPSE) == 0) { - energizeAmount = GetSpellInfo()->Effects[effIndex].BasePoints; // 15 + energizeAmount = GetSpellInfo()->GetEffect(effIndex)->BasePoints; // 15 caster->CastCustomSpell(caster, SPELL_DRUID_STARSURGE_ENERGIZE, &energizeAmount, 0, 0, true); // If the energize was due to 0 power, cast the eclipse marker aura @@ -222,7 +222,7 @@ class spell_dru_eclipse_energize : public SpellScriptLoader } else if (!caster->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_MARKER) && caster->HasAura(SPELL_DRUID_LUNAR_ECLIPSE_MARKER)) { - energizeAmount = -GetSpellInfo()->Effects[effIndex].BasePoints; // -15 + energizeAmount = -GetSpellInfo()->GetEffect(effIndex)->BasePoints; // -15 caster->CastCustomSpell(caster, SPELL_DRUID_STARSURGE_ENERGIZE, &energizeAmount, 0, 0, true); } // The energizing effect brought us out of the lunar eclipse, remove the aura @@ -430,7 +430,7 @@ class spell_dru_idol_lifebloom : public SpellScriptLoader spellMod->op = SPELLMOD_DOT; spellMod->type = SPELLMOD_FLAT; spellMod->spellId = GetId(); - spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; + spellMod->mask = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->SpellClassMask; } spellMod->value = aurEff->GetAmount() / 7; } @@ -757,7 +757,7 @@ class spell_dru_savage_defense : public SpellScriptLoader bool Load() override { - absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); + absorbPct = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(GetCaster()); return true; } @@ -1191,7 +1191,7 @@ class spell_dru_wild_growth : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - if (spellInfo->Effects[EFFECT_2].IsEffect() || spellInfo->Effects[EFFECT_2].CalcValue() <= 0) + if (spellInfo->GetEffect(EFFECT_2)->IsEffect() || spellInfo->GetEffect(EFFECT_2)->CalcValue() <= 0) return false; return true; } @@ -1200,7 +1200,7 @@ class spell_dru_wild_growth : public SpellScriptLoader { targets.remove_if(RaidCheck(GetCaster())); - uint32 const maxTargets = uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster())); + uint32 const maxTargets = uint32(GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue(GetCaster())); if (targets.size() > maxTargets) { diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index badb19c12c3..87619460ee7 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -59,7 +59,7 @@ class spell_gen_absorb0_hitlimit1 : public SpellScriptLoader bool Load() override { // Max absorb stored in 1 dummy effect - limit = GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + limit = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); return true; } @@ -207,9 +207,9 @@ class spell_gen_alchemist_stone : public SpellScriptLoader uint32 spellId = 0; int32 bp = int32(eventInfo.GetDamageInfo()->GetDamage() * 0.4f); - if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(SPELL_EFFECT_HEAL)) + if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_HEAL)) spellId = ALECHEMIST_STONE_HEAL; - else if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(SPELL_EFFECT_ENERGIZE)) + else if (eventInfo.GetDamageInfo()->GetSpellInfo()->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_ENERGIZE)) spellId = ALECHEMIST_STONE_MANA; if (!spellId) @@ -1180,13 +1180,14 @@ class spell_gen_defend : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) override { - if (!sSpellMgr->GetSpellInfo(SPELL_VISUAL_SHIELD_1)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_VISUAL_SHIELD_2)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_VISUAL_SHIELD_3)) - return false; - return true; + // 6.x effects changed + //if (!sSpellMgr->GetSpellInfo(SPELL_VISUAL_SHIELD_1)) + // return false; + //if (!sSpellMgr->GetSpellInfo(SPELL_VISUAL_SHIELD_2)) + // return false; + //if (!sSpellMgr->GetSpellInfo(SPELL_VISUAL_SHIELD_3)) + // return false; + return false; } void RefreshVisualShields(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) @@ -1222,23 +1223,24 @@ class spell_gen_defend : public SpellScriptLoader { SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId); + // 6.x effects removed + // Defend spells cast by NPCs (add visuals) - if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) + /*if (spell->GetEffect(EFFECT_0)->ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) { AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); - } - + }*/ // Remove Defend spell from player when he dismounts - if (spell->Effects[EFFECT_2].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) - OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + //if (spell->GetEffect(EFFECT_2)->ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) + // OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); // Defend spells cast by players (add/remove visuals) - if (spell->Effects[EFFECT_1].ApplyAuraName == SPELL_AURA_DUMMY) + /*if (spell->GetEffect(EFFECT_1)->ApplyAuraName == SPELL_AURA_DUMMY) { AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); - } + }*/ } }; @@ -1264,7 +1266,7 @@ class spell_gen_despawn_self : public SpellScriptLoader void HandleDummy(SpellEffIndex effIndex) { - if (GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_DUMMY || GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_SCRIPT_EFFECT) + if (GetSpellInfo()->GetEffect(effIndex)->Effect == SPELL_EFFECT_DUMMY || GetSpellInfo()->GetEffect(effIndex)->Effect == SPELL_EFFECT_SCRIPT_EFFECT) GetCaster()->ToCreature()->DespawnOrUnsummon(); } @@ -1945,10 +1947,10 @@ class spell_gen_mounted_charge: public SpellScriptLoader { SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId); - if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT)) + if (spell->HasEffect(DIFFICULTY_NONE, SPELL_EFFECT_SCRIPT_EFFECT)) OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT); - if (spell->Effects[EFFECT_0].Effect == SPELL_EFFECT_CHARGE) + if (spell->GetEffect(EFFECT_0)->Effect == SPELL_EFFECT_CHARGE) OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleChargeEffect, EFFECT_0, SPELL_EFFECT_CHARGE); } }; @@ -2426,8 +2428,8 @@ class spell_gen_oracle_wolvar_reputation : public SpellScriptLoader void HandleDummy(SpellEffIndex effIndex) { Player* player = GetCaster()->ToPlayer(); - uint32 factionId = GetSpellInfo()->Effects[effIndex].CalcValue(); - int32 repChange = GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + uint32 factionId = GetSpellInfo()->GetEffect(effIndex)->CalcValue(); + int32 repChange = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId); if (!factionEntry) @@ -3845,7 +3847,7 @@ public: void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/) { - if (GetCaster()->HasAura(SPELL_MIXOLOGY) && GetCaster()->HasSpell(GetSpellInfo()->Effects[EFFECT_0].TriggerSpell)) + if (GetCaster()->HasAura(SPELL_MIXOLOGY) && GetCaster()->HasSpell(GetSpellInfo()->GetEffect(EFFECT_0)->TriggerSpell)) { switch (GetId()) { diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index 5c84f3045f8..a5eec35d95b 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -691,7 +691,7 @@ class spell_brewfest_relay_race_intro_force_player_to_throw : public SpellScript PreventHitDefaultEffect(effIndex); // All this spells trigger a spell that requires reagents; if the // triggered spell is cast as "triggered", reagents are not consumed - GetHitUnit()->CastSpell((Unit*)NULL, GetSpellInfo()->Effects[effIndex].TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); + GetHitUnit()->CastSpell((Unit*)NULL, GetSpellInfo()->GetEffect(effIndex)->TriggerSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST)); } void Register() override diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index f8ef7862c35..9f7f0dc4a5b 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -231,42 +231,6 @@ class spell_hun_disengage : public SpellScriptLoader } }; -// 82926 - Fire! -class spell_hun_fire : public SpellScriptLoader -{ - public: - spell_hun_fire() : SpellScriptLoader("spell_hun_fire") { } - - class spell_hun_fire_AuraScript : public AuraScript - { - PrepareAuraScript(spell_hun_fire_AuraScript); - - void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod) - { - if (!spellMod) - { - spellMod = new SpellModifier(GetAura()); - spellMod->op = SPELLMOD_CASTING_TIME; - spellMod->type = SPELLMOD_PCT; - spellMod->spellId = GetId(); - spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; - } - - spellMod->value = -aurEff->GetAmount(); - } - - void Register() override - { - DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_hun_fire_AuraScript::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_hun_fire_AuraScript(); - } -}; - // -19572 - Improved Mend Pet class spell_hun_improved_mend_pet : public SpellScriptLoader { @@ -308,42 +272,6 @@ class spell_hun_improved_mend_pet : public SpellScriptLoader } }; -// -19464 Improved Serpent Sting -class spell_hun_improved_serpent_sting : public SpellScriptLoader -{ - public: - spell_hun_improved_serpent_sting() : SpellScriptLoader("spell_hun_improved_serpent_sting") { } - - class spell_hun_improved_serpent_sting_AuraScript : public AuraScript - { - PrepareAuraScript(spell_hun_improved_serpent_sting_AuraScript); - - void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod) - { - if (!spellMod) - { - spellMod = new SpellModifier(GetAura()); - spellMod->op = SpellModOp(aurEff->GetMiscValue()); - spellMod->type = SPELLMOD_PCT; - spellMod->spellId = GetId(); - spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; - } - - spellMod->value = aurEff->GetAmount(); - } - - void Register() override - { - DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_hun_improved_serpent_sting_AuraScript::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_hun_improved_serpent_sting_AuraScript(); - } -}; - // 53412 - Invigoration class spell_hun_invigoration : public SpellScriptLoader { @@ -430,7 +358,7 @@ class spell_hun_masters_call : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_MASTERS_CALL_TRIGGERED) || - !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].CalcValue())) + !sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_0)->CalcValue())) return false; return true; } @@ -1087,9 +1015,7 @@ void AddSC_hunter_spell_scripts() new spell_hun_chimera_shot(); new spell_hun_cobra_shot(); new spell_hun_disengage(); - new spell_hun_fire(); new spell_hun_improved_mend_pet(); - new spell_hun_improved_serpent_sting(); new spell_hun_invigoration(); new spell_hun_last_stand_pet(); new spell_hun_masters_call(); diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 17c72ba5561..23f0c7772e9 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -497,7 +497,7 @@ class spell_mage_fire_frost_ward : public SpellScriptLoader void Absorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) { - Unit* target = GetTarget(); + /*Unit* target = GetTarget(); if (AuraEffect* talentAurEff = target->GetAuraEffectOfRankedSpell(SPELL_MAGE_FROST_WARDING_R1, EFFECT_0)) { int32 chance = talentAurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); // SPELL_EFFECT_DUMMY with NO_TARGET @@ -510,7 +510,7 @@ class spell_mage_fire_frost_ward : public SpellScriptLoader absorbAmount = 0; PreventDefaultAction(); } - } + }*/ } void Register() override @@ -738,7 +738,7 @@ class spell_mage_living_bomb : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) { - if (!sSpellMgr->GetSpellInfo(uint32(spellInfo->Effects[EFFECT_1].CalcValue()))) + if (!sSpellMgr->GetSpellInfo(uint32(spellInfo->GetEffect(EFFECT_1)->CalcValue()))) return false; return true; } @@ -836,7 +836,7 @@ class spell_mage_ignite : public SpellScriptLoader SpellInfo const* igniteDot = sSpellMgr->EnsureSpellInfo(SPELL_MAGE_IGNITE); int32 pct = 8 * GetSpellInfo()->GetRank(); - int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks()); + int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks(DIFFICULTY_NONE)); amount += eventInfo.GetProcTarget()->GetRemainingPeriodicAmount(eventInfo.GetActor()->GetGUID(), SPELL_MAGE_IGNITE, SPELL_AURA_PERIODIC_DAMAGE); GetTarget()->CastCustomSpell(SPELL_MAGE_IGNITE, SPELLVALUE_BASE_POINT0, amount, eventInfo.GetProcTarget(), true, NULL, aurEff); } @@ -1254,7 +1254,7 @@ class spell_mage_ring_of_frost : public SpellScriptLoader void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { std::list<Creature*> MinionList; - GetTarget()->GetAllMinionsByEntry(MinionList, GetSpellInfo()->Effects[EFFECT_0].MiscValue); + GetTarget()->GetAllMinionsByEntry(MinionList, GetSpellInfo()->GetEffect(EFFECT_0)->MiscValue); // Get the last summoned RoF, save it and despawn older ones for (std::list<Creature*>::iterator itr = MinionList.begin(); itr != MinionList.end(); itr++) @@ -1313,7 +1313,7 @@ class spell_mage_ring_of_frost_freeze : public SpellScriptLoader void FilterTargets(std::list<WorldObject*>& targets) { - float outRadius = sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON)->Effects[EFFECT_0].CalcRadius(); + float outRadius = sSpellMgr->GetSpellInfo(SPELL_MAGE_RING_OF_FROST_SUMMON)->GetEffect(EFFECT_0)->CalcRadius(); float inRadius = 4.7f; for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 1dab620a9c7..f4afee89d6f 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -401,62 +401,6 @@ class spell_pal_blessing_of_faith : public SpellScriptLoader } }; -// 64205 - Divine Sacrifice -class spell_pal_divine_sacrifice : public SpellScriptLoader -{ - public: - spell_pal_divine_sacrifice() : SpellScriptLoader("spell_pal_divine_sacrifice") { } - - class spell_pal_divine_sacrifice_AuraScript : public AuraScript - { - PrepareAuraScript(spell_pal_divine_sacrifice_AuraScript); - - uint32 groupSize, minHpPct; - int32 remainingAmount; - - bool Load() override - { - - if (Unit* caster = GetCaster()) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - if (caster->ToPlayer()->GetGroup()) - groupSize = caster->ToPlayer()->GetGroup()->GetMembersCount(); - else - groupSize = 1; - } - else - return false; - - remainingAmount = (caster->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue(caster)) * groupSize); - minHpPct = GetSpellInfo()->Effects[EFFECT_1].CalcValue(caster); - return true; - } - return false; - } - - void Split(AuraEffect* /*aurEff*/, DamageInfo & /*dmgInfo*/, uint32 & splitAmount) - { - remainingAmount -= splitAmount; - // break when absorbed everything it could, or if the casters hp drops below 20% - if (Unit* caster = GetCaster()) - if (remainingAmount <= 0 || (caster->GetHealthPct() < minHpPct)) - caster->RemoveAura(SPELL_PALADIN_DIVINE_SACRIFICE); - } - - void Register() override - { - OnEffectSplit += AuraEffectSplitFn(spell_pal_divine_sacrifice_AuraScript::Split, EFFECT_0); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_pal_divine_sacrifice_AuraScript(); - } -}; - // 53385 - Divine Storm class spell_pal_divine_storm : public SpellScriptLoader { @@ -485,7 +429,7 @@ class spell_pal_divine_storm : public SpellScriptLoader bool Load() override { - healPct = GetSpellInfo()->Effects[EFFECT_1].CalcValue(GetCaster()); + healPct = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(GetCaster()); return true; } @@ -1279,7 +1223,6 @@ void AddSC_paladin_spell_scripts() new spell_pal_avenging_wrath(); new spell_pal_beacon_of_light(); new spell_pal_blessing_of_faith(); - new spell_pal_divine_sacrifice(); new spell_pal_divine_storm(); new spell_pal_divine_storm_dummy(); new spell_pal_exorcism_and_holy_wrath_damage(); diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp index 9fd55ae057e..042f1c321ee 100644 --- a/src/server/scripts/Spells/spell_pet.cpp +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -915,7 +915,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value - AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue()); + AddPct(mod, spellInfo->GetEffect(EFFECT_0)->CalcValue()); } ownerBonus = owner->GetStat(STAT_STAMINA)*mod; @@ -958,7 +958,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value - mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); + mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1)->CalcValue()); } bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod; @@ -988,7 +988,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value - mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); + mod += CalculatePct(1.0f, spellInfo->GetEffect(EFFECT_1)->CalcValue()); } bonusDamage = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod; @@ -1450,7 +1450,7 @@ public: amount = -90; // Night of the dead else if (Aura* aur = owner->GetAuraOfRankedSpell(SPELL_NIGHT_OF_THE_DEAD)) - amount = aur->GetSpellInfo()->Effects[EFFECT_2].CalcValue(); + amount = aur->GetSpellInfo()->GetEffect(EFFECT_2)->CalcValue(); } } } @@ -1502,7 +1502,7 @@ public: // Ravenous Dead. Check just if owner has Ravenous Dead since it's effect is not an aura if (AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0)) - mod += aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()/100; // Ravenous Dead edits the original scale + mod += aurEff->GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()/100; // Ravenous Dead edits the original scale // Glyph of the Ghoul if (AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_DEATH_KNIGHT_GLYPH_OF_GHOUL, 0)) @@ -1547,7 +1547,7 @@ public: aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); if (aurEff) { - mod += CalculatePct(mod, aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale + mod += CalculatePct(mod, aurEff->GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()); // Ravenous Dead edits the original scale } // Glyph of the Ghoul aurEff = owner->GetAuraEffect(58686, 0); diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 8ec5450072f..c5a6fcaa4e7 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -369,7 +369,7 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader PreventDefaultAction(); SpellInfo const* triggeredSpellInfo = sSpellMgr->EnsureSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL); - int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks()); + int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks(DIFFICULTY_NONE)); GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff); } @@ -402,7 +402,7 @@ class spell_pri_improved_power_word_shield : public SpellScriptLoader spellMod->op = SpellModOp(aurEff->GetMiscValue()); spellMod->type = SPELLMOD_PCT; spellMod->spellId = GetId(); - spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; + spellMod->mask = GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->SpellClassMask; } spellMod->value = aurEff->GetAmount(); @@ -483,7 +483,7 @@ class spell_pri_guardian_spirit : public SpellScriptLoader bool Load() override { - healPct = GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + healPct = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); return true; } diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 580549a3d99..e9cf81f2e64 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -635,12 +635,12 @@ class spell_q12683_take_sputum_sample : public SpellScriptLoader void HandleDummy(SpellEffIndex /*effIndex*/) { - uint32 reqAuraId = GetSpellInfo()->Effects[EFFECT_1].CalcValue(); + uint32 reqAuraId = GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue(); Unit* caster = GetCaster(); if (caster->HasAuraEffect(reqAuraId, 0)) { - uint32 spellId = GetSpellInfo()->Effects[EFFECT_0].CalcValue(); + uint32 spellId = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(); caster->CastSpell(caster, spellId, true, NULL); } } @@ -1850,7 +1850,7 @@ class spell_q13086_cannons_target : public SpellScriptLoader bool Validate(SpellInfo const* spellInfo) override { - if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].CalcValue())) + if (!sSpellMgr->GetSpellInfo(spellInfo->GetEffect(EFFECT_0)->CalcValue())) return false; return true; } @@ -2011,7 +2011,7 @@ class spell_q12308_escape_from_silverbrook_summon_worgen : public SpellScriptLoa void ModDest(SpellDestination& dest) { - float dist = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + float dist = GetSpellInfo()->GetEffect(EFFECT_0)->CalcRadius(GetCaster()); float angle = frand(0.75f, 1.25f) * float(M_PI); Position pos = GetCaster()->GetNearPosition(dist, angle); @@ -2151,7 +2151,7 @@ class spell_q12619_emblazon_runeblade : public SpellScriptLoader { PreventDefaultAction(); if (Unit* caster = GetCaster()) - caster->CastSpell(caster, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, NULL, aurEff); + caster->CastSpell(caster, GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->TriggerSpell, true, NULL, aurEff); } void Register() override diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 9b3b38875af..78ebe0734b5 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -145,7 +145,8 @@ class spell_rog_cheat_death : public SpellScriptLoader bool Load() override { - absorbChance = GetSpellInfo()->Effects[EFFECT_0].CalcValue(); + // 6.x has basepoint = 0 ! + absorbChance = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(); return GetUnitOwner()->GetTypeId() == TYPEID_PLAYER; } @@ -491,57 +492,6 @@ class spell_rog_master_of_subtlety : public SpellScriptLoader } }; -// 31130 - Nerves of Steel -class spell_rog_nerves_of_steel : public SpellScriptLoader -{ - public: - spell_rog_nerves_of_steel() : SpellScriptLoader("spell_rog_nerves_of_steel") { } - - class spell_rog_nerves_of_steel_AuraScript : public AuraScript - { - PrepareAuraScript(spell_rog_nerves_of_steel_AuraScript); - - public: - spell_rog_nerves_of_steel_AuraScript() - { - absorbPct = 0; - } - - private: - uint32 absorbPct; - - bool Load() override - { - absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster()); - return true; - } - - void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/) - { - // Set absorbtion amount to unlimited - amount = -1; - } - - void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount) - { - // reduces all damage taken while stun or fear - if (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_FLEEING) || (GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1<<MECHANIC_STUN))) - absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct); - } - - void Register() override - { - DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_rog_nerves_of_steel_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); - OnEffectAbsorb += AuraEffectAbsorbFn(spell_rog_nerves_of_steel_AuraScript::Absorb, EFFECT_0); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_rog_nerves_of_steel_AuraScript(); - } -}; - // 58428 - Overkill class spell_rog_overkill : public SpellScriptLoader { @@ -642,51 +592,6 @@ class spell_rog_preparation : public SpellScriptLoader } }; -// 51685 - Prey on the Weak -class spell_rog_prey_on_the_weak : public SpellScriptLoader -{ - public: - spell_rog_prey_on_the_weak() : SpellScriptLoader("spell_rog_prey_on_the_weak") { } - - class spell_rog_prey_on_the_weak_AuraScript : public AuraScript - { - PrepareAuraScript(spell_rog_prey_on_the_weak_AuraScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_PREY_ON_THE_WEAK)) - return false; - return true; - } - - void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) - { - Unit* target = GetTarget(); - Unit* victim = target->GetVictim(); - if (victim && (target->GetHealthPct() > victim->GetHealthPct())) - { - if (!target->HasAura(SPELL_ROGUE_PREY_ON_THE_WEAK)) - { - int32 bp = GetSpellInfo()->Effects[EFFECT_0].CalcValue(); - target->CastCustomSpell(target, SPELL_ROGUE_PREY_ON_THE_WEAK, &bp, nullptr, nullptr, true); - } - } - else - target->RemoveAurasDueToSpell(SPELL_ROGUE_PREY_ON_THE_WEAK); - } - - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_rog_prey_on_the_weak_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_rog_prey_on_the_weak_AuraScript(); - } -}; - // 73651 - Recuperate class spell_rog_recuperate : public SpellScriptLoader { @@ -714,7 +619,7 @@ class spell_rog_recuperate : public SpellScriptLoader canBeRecalculated = false; if (Unit* caster = GetCaster()) { - int32 baseAmount = GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster) * 1000; + int32 baseAmount = GetSpellInfo()->GetEffect(EFFECT_0)->CalcValue(caster) * 1000; // Improved Recuperate if (AuraEffect const* auraEffect = caster->GetDummyAuraEffect(SPELLFAMILY_ROGUE, ICON_ROGUE_IMPROVED_RECUPERATE, EFFECT_0)) baseAmount += auraEffect->GetAmount(); @@ -1028,10 +933,8 @@ void AddSC_rogue_spell_scripts() new spell_rog_deadly_poison(); new spell_rog_killing_spree(); new spell_rog_master_of_subtlety(); - new spell_rog_nerves_of_steel(); new spell_rog_overkill(); new spell_rog_preparation(); - new spell_rog_prey_on_the_weak(); new spell_rog_recuperate(); new spell_rog_rupture(); new spell_rog_shiv(); diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 5e8e3a1070f..3aace7213c0 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -236,7 +236,7 @@ class spell_sha_chain_heal : public SpellScriptLoader if (AuraEffect* aurEff = GetHitUnit()->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, GetCaster()->GetGUID())) { riptide = true; - amount = aurEff->GetSpellInfo()->Effects[EFFECT_2].CalcValue(); + amount = aurEff->GetSpellInfo()->GetEffect(DIFFICULTY_NONE, EFFECT_2)->CalcValue(); // Consume it GetHitUnit()->RemoveAura(aurEff->GetBase()); } @@ -561,44 +561,6 @@ class spell_sha_flame_shock : public SpellScriptLoader } }; -// 77794 - Focused Insight -class spell_sha_focused_insight : public SpellScriptLoader -{ - public: - spell_sha_focused_insight() : SpellScriptLoader("spell_sha_focused_insight") { } - - class spell_sha_focused_insight_AuraScript : public AuraScript - { - PrepareAuraScript(spell_sha_focused_insight_AuraScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_FOCUSED_INSIGHT)) - return false; - return true; - } - - void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/) - { - PreventDefaultAction(); - int32 basePoints0 = aurEff->GetAmount(); - int32 basePoints1 = aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); - - GetTarget()->CastCustomSpell(GetTarget(), SPELL_SHAMAN_FOCUSED_INSIGHT, &basePoints0, &basePoints1, &basePoints1, true, NULL, aurEff); - } - - void Register() override - { - OnEffectProc += AuraEffectProcFn(spell_sha_focused_insight_AuraScript::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_sha_focused_insight_AuraScript(); - } -}; - // 55440 - Glyph of Healing Wave class spell_sha_glyph_of_healing_wave : public SpellScriptLoader { @@ -1072,7 +1034,7 @@ class spell_sha_nature_guardian : public SpellScriptLoader eventInfo.GetProcTarget()->getThreatManager().modifyThreatPercent(GetTarget(), -10); if (Player* player = GetTarget()->ToPlayer()) - player->AddSpellCooldown(GetSpellInfo()->Id, 0, time(NULL) + aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()); + player->AddSpellCooldown(GetSpellInfo()->Id, 0, time(NULL) + aurEff->GetSpellInfo()->GetEffect(EFFECT_1)->CalcValue()); } void Register() override @@ -1242,7 +1204,6 @@ void AddSC_shaman_spell_scripts() new spell_sha_feedback(); new spell_sha_fire_nova(); new spell_sha_flame_shock(); - new spell_sha_focused_insight(); new spell_sha_glyph_of_healing_wave(); new spell_sha_healing_stream_totem(); new spell_sha_heroism(); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 128cddef1c1..924a6113063 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -201,15 +201,16 @@ class spell_warl_conflagrate : public SpellScriptLoader return true; } - void HandleHit(SpellEffIndex /*effIndex*/) - { - if (AuraEffect const* aurEff = GetHitUnit()->GetAuraEffect(SPELL_WARLOCK_IMMOLATE, EFFECT_2, GetCaster()->GetGUID())) - SetHitDamage(CalculatePct(aurEff->GetAmount(), GetSpellInfo()->Effects[EFFECT_1].CalcValue(GetCaster()))); - } + // 6.x dmg formula in tooltip + // void HandleHit(SpellEffIndex /*effIndex*/) + // { + // if (AuraEffect const* aurEff = GetHitUnit()->GetAuraEffect(SPELL_WARLOCK_IMMOLATE, EFFECT_2, GetCaster()->GetGUID())) + // SetHitDamage(CalculatePct(aurEff->GetAmount(), GetSpellInfo()->Effects[EFFECT_1].CalcValue(GetCaster()))); + // } void Register() override { - OnEffectHitTarget += SpellEffectFn(spell_warl_conflagrate_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + //OnEffectHitTarget += SpellEffectFn(spell_warl_conflagrate_SpellScript::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } }; @@ -563,43 +564,6 @@ class spell_warl_everlasting_affliction : public SpellScriptLoader } }; -// 77799 - Fel Flame - Updated to 4.3.4 -class spell_warl_fel_flame : public SpellScriptLoader -{ - public: - spell_warl_fel_flame() : SpellScriptLoader("spell_warl_fel_flame") { } - - class spell_warl_fel_flame_SpellScript : public SpellScript - { - PrepareSpellScript(spell_warl_fel_flame_SpellScript); - - void OnHitTarget(SpellEffIndex /*effIndex*/) - { - Unit* caster = GetCaster(); - Unit* target = GetHitUnit(); - Aura* aura = target->GetAura(SPELL_WARLOCK_UNSTABLE_AFFLICTION, caster->GetGUID()); - if (!aura) - aura = target->GetAura(SPELL_WARLOCK_IMMOLATE, caster->GetGUID()); - - if (!aura) - return; - - int32 newDuration = aura->GetDuration() + GetSpellInfo()->Effects[EFFECT_1].CalcValue() * 1000; - aura->SetDuration(std::min(newDuration, aura->GetMaxDuration())); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_warl_fel_flame_SpellScript::OnHitTarget, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_warl_fel_flame_SpellScript; - } -}; - // -47230 - Fel Synergy class spell_warl_fel_synergy : public SpellScriptLoader { @@ -868,7 +832,8 @@ class spell_warl_improved_soul_fire : public SpellScriptLoader // 1454 - Life Tap /// Updated 4.3.4 -class spell_warl_life_tap : public SpellScriptLoader +// 6.x fully changed this +/*class spell_warl_life_tap : public SpellScriptLoader { public: spell_warl_life_tap() : SpellScriptLoader("spell_warl_life_tap") { } @@ -882,7 +847,7 @@ class spell_warl_life_tap : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_PLAYER; } - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_LIFE_TAP_ENERGIZE) || !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2)) @@ -890,7 +855,7 @@ class spell_warl_life_tap : public SpellScriptLoader return true; } - void HandleDummy(SpellEffIndex /*effIndex*/) + void HandleDummy(SpellEffIndex effIndex) { Player* caster = GetCaster()->ToPlayer(); if (Unit* target = GetHitUnit()) @@ -935,7 +900,7 @@ class spell_warl_life_tap : public SpellScriptLoader { return new spell_warl_life_tap_SpellScript(); } -}; +};*/ // 687 - Demon Armor // 28176 - Fel Armor @@ -1249,7 +1214,9 @@ class spell_warl_soul_swap_dot_marker : public SpellScriptLoader if (!warlock || !swapVictim) return; - flag128 classMask = GetSpellInfo()->Effects[effIndex].SpellClassMask; + // effect existance checked in dbc, should not be removed by core at any time, so no need to check for null + SpellEffectInfo const* effect = GetSpellInfo()->GetEffect(DIFFICULTY_NONE, EFFECT_0); + flag128 classMask = effect->SpellClassMask; Unit::AuraApplicationMap const& appliedAuras = swapVictim->GetAppliedAuras(); SoulSwapOverrideAuraScript* swapSpellScript = NULL; @@ -1452,14 +1419,14 @@ void AddSC_warlock_spell_scripts() new spell_warl_demonic_empowerment(); new spell_warl_demon_soul(); new spell_warl_everlasting_affliction(); - new spell_warl_fel_flame(); + //new spell_warl_fel_flame(); new spell_warl_fel_synergy(); new spell_warl_glyph_of_shadowflame(); new spell_warl_haunt(); new spell_warl_health_funnel(); new spell_warl_healthstone_heal(); new spell_warl_improved_soul_fire(); - new spell_warl_life_tap(); + //new spell_warl_life_tap(); new spell_warl_nether_ward_overrride(); new spell_warl_seduction(); new spell_warl_seed_of_corruption(); diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 3b6b68d3fce..c4699f6b60c 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -120,34 +120,6 @@ class spell_warr_bloodthirst : public SpellScriptLoader }; /// Updated 4.3.4 -class spell_warr_bloodthirst_heal : public SpellScriptLoader -{ - public: - spell_warr_bloodthirst_heal() : SpellScriptLoader("spell_warr_bloodthirst_heal") { } - - class spell_warr_bloodthirst_heal_SpellScript : public SpellScript - { - PrepareSpellScript(spell_warr_bloodthirst_heal_SpellScript); - - void HandleHeal(SpellEffIndex /*effIndex*/) - { - if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_WARRIOR_BLOODTHIRST_DAMAGE)) - SetHitHeal(GetCaster()->CountPctFromMaxHealth(spellInfo->Effects[EFFECT_1].CalcValue(GetCaster())) / 100); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_warr_bloodthirst_heal_SpellScript::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_warr_bloodthirst_heal_SpellScript(); - } -}; - -/// Updated 4.3.4 class spell_warr_charge : public SpellScriptLoader { public: @@ -216,59 +188,6 @@ class spell_warr_concussion_blow : public SpellScriptLoader } }; -// -12162 - Deep Wounds -class spell_warr_deep_wounds : public SpellScriptLoader -{ - public: - spell_warr_deep_wounds() : SpellScriptLoader("spell_warr_deep_wounds") { } - - class spell_warr_deep_wounds_SpellScript : public SpellScript - { - PrepareSpellScript(spell_warr_deep_wounds_SpellScript); - - bool Validate(SpellInfo const* /*spellInfo*/) override - { - if (!sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_RANK_1) || - !sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_RANK_2) || - !sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_RANK_3) || - !sSpellMgr->GetSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC)) - return false; - return true; - } - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - int32 damage = GetEffectValue(); - Unit* caster = GetCaster(); - if (Unit* target = GetHitUnit()) - { - ApplyPct(damage, 16 * GetSpellInfo()->GetRank()); - - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC); - uint32 ticks = uint32(spellInfo->GetDuration()) / spellInfo->Effects[EFFECT_0].ApplyAuraPeriod; - - // Add remaining ticks to damage done - if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC, EFFECT_0, caster->GetGUID())) - damage += aurEff->GetDamage() * int32(ticks - aurEff->GetTickNumber()); - - damage /= int32(ticks); - - caster->CastCustomSpell(target, SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC, &damage, NULL, NULL, true); - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_warr_deep_wounds_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_warr_deep_wounds_SpellScript(); - } -}; - /// Updated 4.3.4 class spell_warr_execute : public SpellScriptLoader { @@ -281,7 +200,7 @@ class spell_warr_execute : public SpellScriptLoader void HandleEffect(SpellEffIndex /*effIndex*/) { - Unit* caster = GetCaster(); + /*Unit* caster = GetCaster(); if (GetHitUnit()) { SpellInfo const* spellInfo = GetSpellInfo(); @@ -302,7 +221,7 @@ class spell_warr_execute : public SpellScriptLoader /// Formula taken from the DBC: "${$ap*0.874*$m1/100-1} = 20 rage" int32 moreDamage = int32(rageUsed * (caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.874f * GetEffectValue() / 100.0f - 1) / 200); SetHitDamage(baseDamage + moreDamage); - } + }*/ } void Register() override @@ -317,42 +236,6 @@ class spell_warr_execute : public SpellScriptLoader } }; -// 58387 - Glyph of Sunder Armor -class spell_warr_glyph_of_sunder_armor : public SpellScriptLoader -{ - public: - spell_warr_glyph_of_sunder_armor() : SpellScriptLoader("spell_warr_glyph_of_sunder_armor") { } - - class spell_warr_glyph_of_sunder_armor_AuraScript : public AuraScript - { - PrepareAuraScript(spell_warr_glyph_of_sunder_armor_AuraScript); - - void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod) - { - if (!spellMod) - { - spellMod = new SpellModifier(aurEff->GetBase()); - spellMod->op = SpellModOp(aurEff->GetMiscValue()); - spellMod->type = SPELLMOD_FLAT; - spellMod->spellId = GetId(); - spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask; - } - - spellMod->value = aurEff->GetAmount(); - } - - void Register() override - { - DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_warr_glyph_of_sunder_armor_AuraScript::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_warr_glyph_of_sunder_armor_AuraScript(); - } -}; - // 59725 - Improved Spell Reflection class spell_warr_improved_spell_reflection : public SpellScriptLoader { @@ -991,11 +874,11 @@ class spell_warr_vigilance : public SpellScriptLoader void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) { - PreventDefaultAction(); + /*PreventDefaultAction(); int32 damage = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue())); GetTarget()->CastSpell(_procTarget, SPELL_WARRIOR_VIGILANCE_PROC, true, NULL, aurEff); - _procTarget->CastCustomSpell(_procTarget, SPELL_WARRIOR_VENGEANCE, &damage, &damage, &damage, true, NULL, aurEff); + _procTarget->CastCustomSpell(_procTarget, SPELL_WARRIOR_VENGEANCE, &damage, &damage, &damage, true, NULL, aurEff);*/ } void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) @@ -1058,12 +941,9 @@ class spell_warr_vigilance_trigger : public SpellScriptLoader void AddSC_warrior_spell_scripts() { new spell_warr_bloodthirst(); - new spell_warr_bloodthirst_heal(); new spell_warr_charge(); new spell_warr_concussion_blow(); - new spell_warr_deep_wounds(); new spell_warr_execute(); - new spell_warr_glyph_of_sunder_armor(); new spell_warr_improved_spell_reflection(); new spell_warr_intimidating_shout(); new spell_warr_lambs_to_the_slaughter(); diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp index 17c37c7eba0..3e89041a9e9 100644 --- a/src/server/scripts/World/npc_professions.cpp +++ b/src/server/scripts/World/npc_professions.cpp @@ -234,9 +234,12 @@ bool EquippedOk(Player* player, uint32 spellId) if (!spell) return false; - for (uint8 i = 0; i < 3; ++i) + for (SpellEffectInfo const* effect : spell->GetEffectsForDifficulty(DIFFICULTY_NONE)) { - uint32 reqSpell = spell->Effects[i].TriggerSpell; + if (!effect) + continue; + + uint32 reqSpell = effect->TriggerSpell; if (!reqSpell) continue; diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 57c0ddf066e..34699c19648 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2159,8 +2159,8 @@ public: const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (spellInfo && spellInfo->Effects[0].Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD) - return spellInfo->Effects[0].MiscValue; + if (spellInfo && spellInfo->GetEffect(EFFECT_0)->Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD) + return spellInfo->GetEffect(EFFECT_0)->MiscValue; return 0; } |