diff options
author | Shauren <shauren.trinity@gmail.com> | 2015-01-10 01:35:47 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2015-01-10 01:35:47 +0100 |
commit | faa583c7843af37d757bd46ca0bd226175dabc38 (patch) | |
tree | 5af657d84903b337bdb22c341bb01f4e6aab1392 /src/server/game | |
parent | f6b30fdf616bd289dd668f98a0aed8dbfb14eba8 (diff) |
Core/Maps: Updated map difficulties
Diffstat (limited to 'src/server/game')
53 files changed, 730 insertions, 422 deletions
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 351877fed6f..9b92840ecf0 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -275,7 +275,7 @@ struct ScriptedAI : public CreatureAI Difficulty GetDifficulty() const { return _difficulty; } // return true for 25 man or 25 man heroic mode - bool Is25ManRaid() const { return _difficulty & RAID_DIFFICULTY_MASK_25MAN; } + bool Is25ManRaid() const { return _difficulty == DIFFICULTY_25_N || _difficulty == DIFFICULTY_25_HC; } template<class T> inline const T& DUNGEON_MODE(const T& normal5, const T& heroic10) const diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 36edfab420c..ba2571884dc 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -2709,7 +2709,7 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(ModifierTreeNode const* break; } case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 20 - if (uint32(referencePlayer->GetMap()->GetDifficulty()) != reqValue) + if (uint32(referencePlayer->GetMap()->GetDifficultyID()) != reqValue) return false; break; case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE: diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index 406f4702c3b..18ead47c490 100644 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -41,7 +41,7 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float threat *= threatEntry->pctMod; // Energize is not affected by Mods - for (SpellEffectInfo const* effect : threatSpell->GetEffectsForDifficulty(hatedUnit->GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : threatSpell->GetEffectsForDifficulty(hatedUnit->GetMap()->GetDifficultyID())) if (effect && (effect->Effect == SPELL_EFFECT_ENERGIZE || effect->ApplyAuraName == SPELL_AURA_PERIODIC_ENERGIZE)) return threat; diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 20d49855b8f..2542706e507 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1234,30 +1234,34 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) 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) { - if ((1<<i) & *itr) + if ((1 << i) & *itr) { found = true; break; } } + if (found) continue; // build new shared mask with found effect - uint32 sharedMask = (1<<i); + uint32 sharedMask = 1 << i; ConditionList* cmp = effect->ImplicitTargetConditions; - for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex) + for (uint8 effIndex = i + 1; effIndex < MAX_SPELL_EFFECTS; ++effIndex) { SpellEffectInfo const* inner = spellInfo->GetEffect(DIFFICULTY_NONE, effIndex); if (!inner) continue; + if (inner->ImplicitTargetConditions == cmp) - sharedMask |= 1<<effIndex; + sharedMask |= 1 << effIndex; } + sharedMasks.push_back(sharedMask); } @@ -1304,7 +1308,7 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) if (!eff) continue; - if ((1<<i) & commonMask) + if ((1 << i) & commonMask) { const_cast<SpellEffectInfo*>(eff)->ImplicitTargetConditions = sharedList; assigned = true; diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp index a097605afb1..c2527b1d28f 100644 --- a/src/server/game/Conditions/DisableMgr.cpp +++ b/src/server/game/Conditions/DisableMgr.cpp @@ -333,7 +333,7 @@ bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags if (mapEntry->IsDungeon()) { uint8 disabledModes = itr->second.flags; - Difficulty targetDifficulty = player->GetDifficulty(mapEntry->IsRaid()); + Difficulty targetDifficulty = player->GetDifficultyID(mapEntry); GetDownscaledMapDifficultyData(entry, targetDifficulty); switch (targetDifficulty) { diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 671e2816a19..cf8701dc0d7 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -352,21 +352,28 @@ enum Difficulty 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_NORMAL_RAID = 14, + DIFFICULTY_HEROIC_RAID = 15, + DIFFICULTY_MYTHIC_RAID = 16, + DIFFICULTY_LFR_NEW = 17, + DIFFICULTY_EVENT_RAID = 18, + DIFFICULTY_EVENT_DUNGEON = 19, DIFFICULTY_EVENT_SCENARIO = 20, - DIFFICULTY_MAX = 21, + + MAX_DIFFICULTY }; -#define RAID_DIFFICULTY_MASK_25MAN 1 // since 25man difficulties are 1 and 3, we can check them like that +enum DifficultyFlags +{ + DIFFICULTY_FLAG_HEROIC = 0x01, + DIFFICULTY_FLAG_DEFAULT = 0x02, + DIFFICULTY_FLAG_CAN_SELECT = 0x04, // Player can select this difficulty in dropdown menu + DIFFICULTY_FLAG_CHALLENGE_MODE = 0x08, -#define MAX_DUNGEON_DIFFICULTY 3 -#define MAX_RAID_DIFFICULTY 4 -#define MAX_DIFFICULTY 4 + DIFFICULTY_FLAG_LEGACY = 0x20, + DIFFICULTY_FLAG_DISPLAY_HEROIC = 0x40, // Controls icon displayed on minimap when inside the instance + DIFFICULTY_FLAG_DISPLAY_MYTHIC = 0x80 // Controls icon displayed on minimap when inside the instance +}; enum SpawnMask { @@ -415,7 +422,9 @@ enum MapTypes // Lua_IsInInstance enum MapFlags { - MAP_FLAG_DYNAMIC_DIFFICULTY = 0x100 + MAP_FLAG_CAN_TOGGLE_DIFFICULTY = 0x0100, + MAP_FLAG_FLEX_LOCKING = 0x8000, // All difficulties share completed encounters lock, not bound to a single instance id + // heroic difficulty flag overrides it and uses instance id bind }; enum AbilytyLearnType diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 6c0cc92550c..783827a4f93 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -90,6 +90,7 @@ DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore(CurrencyTypesfmt); uint32 PowersByClass[MAX_CLASSES][MAX_POWERS]; DBCStorage <DestructibleModelDataEntry> sDestructibleModelDataStore(DestructibleModelDatafmt); +DBCStorage <DifficultyEntry> sDifficultyStore(DifficultyFmt); DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore(DungeonEncounterfmt); DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt); DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt); @@ -415,13 +416,14 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sCriteriaTreeStore, dbcPath, "CriteriaTree.dbc");//19342 LoadDBC(availableDbcLocales, bad_dbc_files, sCurrencyTypesStore, dbcPath, "CurrencyTypes.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sDestructibleModelDataStore, dbcPath, "DestructibleModelData.dbc");//19116 + LoadDBC(availableDbcLocales, bad_dbc_files, sDifficultyStore, dbcPath, "Difficulty.dbc");//19342 LoadDBC(availableDbcLocales, bad_dbc_files, sDungeonEncounterStore, dbcPath, "DungeonEncounter.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityCostsStore, dbcPath, "DurabilityCosts.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sDurabilityQualityStore, dbcPath, "DurabilityQuality.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesStore, dbcPath, "Emotes.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sEmotesTextStore, dbcPath, "EmotesText.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sFactionStore, dbcPath, "Faction.dbc");//19116 - for (uint32 i=0; i<sFactionStore.GetNumRows(); ++i) + for (uint32 i = 0; i < sFactionStore.GetNumRows(); ++i) { FactionEntry const* faction = sFactionStore.LookupEntry(i); if (faction && faction->ParentFactionID) @@ -491,10 +493,10 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sMapStore, dbcPath, "Map.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sMapDifficultyStore, dbcPath, "MapDifficulty.dbc");//19116 // fill data - sMapDifficultyMap[MAKE_PAIR32(0, 0)] = MapDifficulty(0, 0, false);//map 0 is missingg from MapDifficulty.dbc use this till its ported to sql + sMapDifficultyMap[0][0] = MapDifficulty(DIFFICULTY_NONE, 0, 0, false);//map 0 is missingg from MapDifficulty.dbc use this till its ported to sql for (uint32 i = 0; i < sMapDifficultyStore.GetNumRows(); ++i) if (MapDifficultyEntry const* entry = sMapDifficultyStore.LookupEntry(i)) - sMapDifficultyMap[MAKE_PAIR32(entry->MapID, entry->DifficultyID)] = MapDifficulty(entry->RaidDuration, entry->MaxPlayers, entry->Message_lang[0] > 0); + sMapDifficultyMap[entry->MapID][entry->DifficultyID] = MapDifficulty(entry->DifficultyID, entry->RaidDuration, entry->MaxPlayers, entry->Message_lang[0] > 0); sMapDifficultyStore.Clear(); LoadDBC(availableDbcLocales, bad_dbc_files, sModifierTreeStore, dbcPath, "ModifierTree.dbc");//19342 @@ -950,35 +952,63 @@ void Map2ZoneCoordinates(float& x, float& y, uint32 zone) if (!maEntry) return; - x = (x-maEntry->LocTop)/((maEntry->LocBottom-maEntry->LocTop)/100); - y = (y-maEntry->LocLeft)/((maEntry->LocRight-maEntry->LocLeft)/100); // client y coord from top to down + x = (x - maEntry->LocTop) / ((maEntry->LocBottom - maEntry->LocTop) / 100); + y = (y - maEntry->LocLeft) / ((maEntry->LocRight - maEntry->LocLeft) / 100); // client y coord from top to down std::swap(x, y); // client have map coords swapped } +MapDifficulty const* GetDefaultMapDifficulty(uint32 mapID) +{ + auto itr = sMapDifficultyMap.find(mapID); + if (itr == sMapDifficultyMap.end()) + return nullptr; + + if (itr->second.empty()) + return nullptr; + + for (auto& p : itr->second) + { + DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(p.first); + if (!difficulty) + continue; + + if (difficulty->Flags & DIFFICULTY_FLAG_DEFAULT) + return &p.second; + } + + return &itr->second.begin()->second; +} + MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty) { - MapDifficultyMap::const_iterator itr = sMapDifficultyMap.find(MAKE_PAIR32(mapId, difficulty)); - return itr != sMapDifficultyMap.end() ? &itr->second : NULL; + auto itr = sMapDifficultyMap.find(mapId); + if (itr == sMapDifficultyMap.end()) + return nullptr; + + auto diffItr = itr->second.find(difficulty); + if (diffItr == itr->second.end()) + return nullptr; + + return &diffItr->second; } MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty) { + DifficultyEntry const* diffEntry = sDifficultyStore.LookupEntry(difficulty); + if (!diffEntry) + return GetDefaultMapDifficulty(mapId); + uint32 tmpDiff = difficulty; MapDifficulty const* mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); - if (!mapDiff) + while (!mapDiff) { - 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) + tmpDiff = diffEntry->FallbackDifficultyID; + diffEntry = sDifficultyStore.LookupEntry(tmpDiff); + if (!diffEntry) + return GetDefaultMapDifficulty(mapId); // pull new data mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); // we are 10 normal or 25 normal - if (!mapDiff) - { - tmpDiff -= 1; - mapDiff = GetMapDifficultyData(mapId, Difficulty(tmpDiff)); // 10 normal - } } difficulty = Difficulty(tmpDiff); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index b73fbcf02f5..7bc8dcf5b64 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -70,7 +70,8 @@ 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; +typedef std::unordered_map<uint32, std::unordered_map<uint32, MapDifficulty>> MapDifficultyMap; +MapDifficulty const* GetDefaultMapDifficulty(uint32 mapID); MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty); MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty); @@ -156,6 +157,7 @@ extern DBCStorage <CriteriaEntry> sCriteriaStore; extern DBCStorage <CriteriaTreeEntry> sCriteriaTreeStore; extern DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore; extern DBCStorage <DestructibleModelDataEntry> sDestructibleModelDataStore; +extern DBCStorage <DifficultyEntry> sDifficultyStore; extern DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore; extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore; extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index a87083882e2..813f7ba4019 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -620,6 +620,23 @@ struct DestructibleModelDataEntry //uint32 HealEffectSpeed; // 23 }; +struct DifficultyEntry +{ + uint32 ID; // 0 + uint32 FallbackDifficultyID; // 1 + uint32 InstanceType; // 2 + uint32 MinPlayers; // 3 + uint32 MaxPlayers; // 4 + //int32 OldEnumValue; // 5 + uint32 Flags; // 6 + uint32 ToggleDifficultyID; // 7 + //uint32 GroupSizeHealthCurveID; // 8 + //uint32 GroupSizeDmgCurveID; // 9 + //uint32 GroupSizeSpellPointsCurveID; // 10 + //char const* NameLang; // 11 + //uint32 Unk; // 12 +}; + struct DungeonEncounterEntry { uint32 ID; // 0 @@ -1202,7 +1219,7 @@ struct MapEntry return ID == 0 || ID == 1 || ID == 530 || ID == 571 || ID == 870 || ID == 1116; } - bool IsDynamicDifficultyMap() const { return (Flags & MAP_FLAG_DYNAMIC_DIFFICULTY) != 0; } + bool IsDynamicDifficultyMap() const { return (Flags & MAP_FLAG_CAN_TOGGLE_DIFFICULTY) != 0; } }; struct MapDifficultyEntry @@ -1213,7 +1230,7 @@ struct MapDifficultyEntry char* Message_lang; // 3 m_message_lang (text showed when transfer to map failed) uint32 RaidDuration; // 4 m_raidDuration in secs, 0 if no fixed reset time uint32 MaxPlayers; // 5 m_maxPlayers some heroic versions have 0 when expected same amount as in normal version - //uint32 Unk1; // 6 + uint32 LockID; // 6 //uint32 Unk2; // 7 }; @@ -2021,9 +2038,11 @@ typedef std::map<uint32, VectorArray> NameGenContainer; // Structures not used for casting to loaded DBC data and not required then packing struct MapDifficulty { - MapDifficulty() : resetTime(0), maxPlayers(0), hasErrorMessage(false) { } - MapDifficulty(uint32 _resetTime, uint32 _maxPlayers, bool _hasErrorMessage) : resetTime(_resetTime), maxPlayers(_maxPlayers), hasErrorMessage(_hasErrorMessage) { } + MapDifficulty() : DifficultyID(0), resetTime(0), maxPlayers(0), hasErrorMessage(false) { } + MapDifficulty(uint32 difficultyID, uint32 _resetTime, uint32 _maxPlayers, bool _hasErrorMessage) + : DifficultyID(difficultyID), resetTime(_resetTime), maxPlayers(_maxPlayers), hasErrorMessage(_hasErrorMessage) { } + uint32 DifficultyID; uint32 resetTime; uint32 maxPlayers; bool hasErrorMessage; diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 540e1951b72..3f9f01cab16 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -52,6 +52,7 @@ char const Criteriafmt[] = "niiiiiiiixii"; char const CriteriaTreefmt[] = "niliixxx"; char const CurrencyTypesfmt[] = "nixxxxxiiixx"; char const DestructibleModelDatafmt[] = "nixxxixxxxixxxxixxxxxxxx"; +char const DifficultyFmt[] = "niiiixiixxxxx"; char const DungeonEncounterfmt[] = "niiixsxxx"; char const DurabilityCostsfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; char const DurabilityQualityfmt[] = "nf"; @@ -106,7 +107,7 @@ char const LockEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; char const PhaseEntryfmt[] = "ni"; char const MailTemplateEntryfmt[] = "nxs"; char const MapEntryfmt[] = "nxiixxsixxixiffxiiiixx"; -char const MapDifficultyEntryfmt[] = "diisiixx"; +char const MapDifficultyEntryfmt[] = "diisiiix"; char const MinorTalentEntryfmt[] = "niii"; char const MovieEntryfmt[] = "nxxxx"; char const ModifierTreefmt[] = "niiiiii"; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 064c1e4f105..0a2763f97b7 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -924,7 +924,7 @@ void LFGMgr::MakeNewGroup(LfgProposal const& proposal) } ASSERT(grp); - grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty)); + grp->SetDungeonDifficultyID(Difficulty(dungeon->difficulty)); ObjectGuid gguid = grp->GetGUID(); SetDungeon(gguid, dungeon->Entry()); SetState(gguid, LFG_STATE_DUNGEON); diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 86edaa2349e..c77ab9a36c5 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -74,7 +74,7 @@ void LFGPlayerScript::OnMapChanged(Player* player) { Map const* map = player->GetMap(); - if (sLFGMgr->inLfgDungeonMap(player->GetGUID(), map->GetId(), map->GetDifficulty())) + if (sLFGMgr->inLfgDungeonMap(player->GetGUID(), map->GetId(), map->GetDifficultyID())) { Group* group = player->GetGroup(); // This function is also called when players log in diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f4567fbc1b7..070263cd85e 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -269,27 +269,29 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) } // get difficulty 1 mode entry - CreatureTemplate const* cinfo = normalInfo; - for (uint8 diff = uint8(GetMap()->GetSpawnMode()); diff > 0;) + CreatureTemplate const* cinfo = nullptr; + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(GetMap()->GetSpawnMode()); + while (!cinfo && difficultyEntry) { - // we already have valid Map pointer for current creature! - if (normalInfo->DifficultyEntry[diff - 1]) - { - cinfo = sObjectMgr->GetCreatureTemplate(normalInfo->DifficultyEntry[diff - 1]); - if (cinfo) - break; // template found + int32 idx = CreatureTemplate::DifficultyIDToDifficultyEntryIndex(difficultyEntry->ID); + if (idx == -1) + break; - // check and reported at startup, so just ignore (restore normalInfo) - cinfo = normalInfo; + if (normalInfo->DifficultyEntry[idx]) + { + cinfo = sObjectMgr->GetCreatureTemplate(normalInfo->DifficultyEntry[idx]); + break; } - // for instances heroic to normal, other cases attempt to retrieve previous difficulty - if (diff >= DIFFICULTY_10_HC && GetMap()->IsRaid()) - diff -= 2; // to normal raid difficulty cases - else - --diff; + if (!difficultyEntry->FallbackDifficultyID) + break; + + difficultyEntry = sDifficultyStore.LookupEntry(difficultyEntry->FallbackDifficultyID); } + if (!cinfo) + cinfo = normalInfo; + // Initialize loot duplicate count depending on raid difficulty if (GetMap()->Is25ManRaid()) loot.maxDuplicates = 3; @@ -946,7 +948,7 @@ void Creature::SaveToDB() SaveToDB(mapId, data->spawnMask, GetPhaseMask()); } -void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) +void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) { // update in loaded data if (!m_DBTableGuid) @@ -1620,7 +1622,7 @@ 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 (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (!effect || !effect->IsEffect()) continue; @@ -1638,7 +1640,7 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo) const bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const { - SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty()); + SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID()); if (!effect) return true; if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (effect->Mechanic - 1))) @@ -1684,7 +1686,7 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) } bool bcontinue = true; - for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (effect && ((effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) || (effect->Effect == SPELL_EFFECT_INSTAKILL) || @@ -1732,7 +1734,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim) } bool bcontinue = true; - for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (effect && (effect->Effect == SPELL_EFFECT_HEAL)) { diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index ff43f73d1c6..842624e0c01 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -72,12 +72,13 @@ enum CreatureFlagsExtra #define MAX_CREATURE_QUEST_ITEMS 6 #define MAX_CREATURE_NAMES 4 #define CREATURE_MAX_SPELLS 8 +#define MAX_CREATURE_DIFFICULTIES 3 // from `creature_template` table struct CreatureTemplate { uint32 Entry; - uint32 DifficultyEntry[MAX_DIFFICULTY - 1]; + uint32 DifficultyEntry[MAX_CREATURE_DIFFICULTIES]; uint32 KillCredit[MAX_KILL_CREDIT]; uint32 Modelid1; uint32 Modelid2; @@ -170,6 +171,38 @@ struct CreatureTemplate // if can tame exotic then can tame any tameable return canTameExotic || !IsExotic(); } + + static int32 DifficultyIDToDifficultyEntryIndex(uint32 difficulty) + { + switch (difficulty) + { + case DIFFICULTY_NONE: + case DIFFICULTY_NORMAL: + case DIFFICULTY_10_N: + case DIFFICULTY_40: + case DIFFICULTY_N_SCENARIO: + case DIFFICULTY_NORMAL_RAID: + return -1; + case DIFFICULTY_HEROIC: + case DIFFICULTY_25_N: + case DIFFICULTY_HC_SCENARIO: + case DIFFICULTY_HEROIC_RAID: + return 0; + case DIFFICULTY_10_HC: + case DIFFICULTY_CHALLENGE: + case DIFFICULTY_MYTHIC_RAID: + return 1; + case DIFFICULTY_25_HC: + return 2; + case DIFFICULTY_LFR: + case DIFFICULTY_LFR_NEW: + case DIFFICULTY_EVENT_RAID: + case DIFFICULTY_EVENT_DUNGEON: + case DIFFICULTY_EVENT_SCENARIO: + default: + return -1; + } + } }; // Benchmarked: Faster than std::map (insert/find) @@ -274,7 +307,7 @@ struct CreatureData uint32 curhealth; uint32 curmana; uint8 movementType; - uint8 spawnMask; + uint32 spawnMask; uint32 npcflag; uint32 unit_flags; // enum UnitFlags mask values uint32 dynamicflags; @@ -549,7 +582,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject bool LoadCreatureFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true); void SaveToDB(); // overriden in Pet - virtual void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); + virtual void SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask); virtual void DeleteFromDB(); // overriden in Pet Loot loot; diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index 16fd7c11683..378061d2905 100644 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -48,7 +48,7 @@ class TempSummon : public Creature virtual void UnSummon(uint32 msTime = 0); void RemoveFromWorld() override; void SetTempSummonType(TempSummonType type); - void SaveToDB(uint32 /*mapid*/, uint8 /*spawnMask*/, uint32 /*phaseMask*/) override { } + void SaveToDB(uint32 /*mapid*/, uint32 /*spawnMask*/, uint32 /*phaseMask*/) override { } Unit* GetSummoner() const; Creature* GetSummonerCreatureBase() const; ObjectGuid GetSummonerGUID() const { return m_summonerGUID; } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 929f7b90689..78efc590566 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -773,7 +773,7 @@ void GameObject::SaveToDB() SaveToDB(GetMapId(), data->spawnMask, data->phaseMask); } -void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) +void GameObject::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) { const GameObjectTemplate* goI = GetGOInfo(); @@ -1809,7 +1809,7 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /*= true return; bool self = false; - for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (effect && effect->TargetA.GetTarget() == TARGET_UNIT_CASTER) { diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index a242e04ea37..239324c572d 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -828,7 +828,7 @@ struct GameObjectData int32 spawntimesecs; uint32 animprogress; GOState go_state; - uint8 spawnMask; + uint32 spawnMask; uint8 artKit; uint32 phaseid; uint32 phaseGroup; @@ -883,7 +883,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map std::string const& GetNameForLocaleIdx(LocaleConstant locale_idx) const override; void SaveToDB(); - void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); + void SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask); bool LoadFromDB(ObjectGuid::LowType guid, Map* map) { return LoadGameObjectFromDB(guid, map, false); } bool LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true); void DeleteFromDB(); diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 853eb5c691c..e9ace117dde 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -156,7 +156,7 @@ class Pet : public Guardian DeclinedName *m_declinedname; private: - void SaveToDB(uint32, uint8, uint32) override // override of Creature::SaveToDB - must not be called + void SaveToDB(uint32, uint32, uint32) override // override of Creature::SaveToDB - must not be called { ASSERT(false); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 9da2865277e..3ef12a96f8c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -790,8 +790,9 @@ Player::Player(WorldSession* session): Unit(true) m_HomebindTimer = 0; m_InstanceValid = true; m_dungeonDifficulty = DIFFICULTY_NORMAL; - m_raidDifficulty = DIFFICULTY_10_N; - m_raidMapDifficulty = DIFFICULTY_10_N; + m_raidDifficulty = DIFFICULTY_NORMAL_RAID; + m_legacyRaidDifficulty = DIFFICULTY_10_N; + m_raidMapDifficulty = DIFFICULTY_NORMAL_RAID; m_lastPotionId = 0; _talentMgr = new PlayerTalentInfo(); @@ -6696,7 +6697,7 @@ void Player::RewardReputation(Unit* victim, float rate) // support for: Championing - http://www.wowwiki.com/Championing Map const* map = GetMap(); if (map && map->IsNonRaidDungeon()) - if (LFGDungeonEntry const* dungeon = GetLFGDungeon(map->GetId(), map->GetDifficulty())) + if (LFGDungeonEntry const* dungeon = GetLFGDungeon(map->GetId(), map->GetDifficultyID())) if (dungeon->TargetLevel == 80) ChampioningFaction = GetChampioningFaction(); } @@ -11558,7 +11559,7 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje // check if looted object is inside the lfg dungeon Map const* map = lootedObject->GetMap(); - if (!sLFGMgr->inLfgDungeonMap(GetGroup()->GetGUID(), map->GetId(), map->GetDifficulty())) + if (!sLFGMgr->inLfgDungeonMap(GetGroup()->GetGUID(), map->GetId(), map->GetDifficultyID())) return EQUIP_ERR_OK; if (!proto) @@ -15927,7 +15928,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E // just if !ingroup || !noraidgroup || raidgroup QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty()))) + if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficultyID()))) { if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST)*/) { @@ -15980,7 +15981,7 @@ void Player::KilledPlayerCredit() // just if !ingroup || !noraidgroup || raidgroup QuestStatusData& q_status = m_QuestStatus[questid]; - if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty()))) + if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficultyID()))) { for (QuestObjective const& obj : qInfo->GetObjectives()) { @@ -16207,7 +16208,7 @@ bool Player::HasQuestForItem(uint32 itemid) const continue; // hide quest if player is in raid-group and quest is no raid quest - if (GetGroup() && GetGroup()->isRaidGroup() && !qInfo->IsAllowedInRaid(GetMap()->GetDifficulty())) + if (GetGroup() && GetGroup()->isRaidGroup() && !qInfo->IsAllowedInRaid(GetMap()->GetDifficultyID())) if (!InBattleground()) //there are two ways.. we can make every bg-quest a raidquest, or add this code here.. i don't know if this can be exploited by other quests, but i think all other quests depend on a specific area.. but keep this in mind, if something strange happens later continue; @@ -16645,13 +16646,13 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) // 12 13 14 15 16 17 18 19 20 21 22 23 24 //"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, " // 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 - //"resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, " + //"resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, " // 40 41 42 43 44 45 //"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, " // 46 47 48 49 50 51 52 53 54 55 56 //"health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, " - // 57 58 59 - //"knownTitles, actionBars, grantableLevels FROM characters WHERE guid = '%u'", guid); + // 57 58 59 60 61 + //"knownTitles, actionBars, grantableLevels, raidDifficulty, legacyRaidDifficulty FROM characters WHERE guid = '%u'", guid); PreparedQueryResult result = holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_FROM); if (!result) { @@ -16777,14 +16778,9 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) uint32 mapId = fields[15].GetUInt16(); uint32 instanceId = fields[52].GetUInt32(); - uint32 dungeonDiff = fields[39].GetUInt8() & 0x0F; - if (dungeonDiff >= MAX_DUNGEON_DIFFICULTY) - dungeonDiff = DIFFICULTY_NORMAL; - uint32 raidDiff = (fields[39].GetUInt8() >> 4) & 0x0F; - if (raidDiff >= MAX_RAID_DIFFICULTY) - raidDiff = DIFFICULTY_10_N; - SetDungeonDifficulty(Difficulty(dungeonDiff)); // may be changed in _LoadGroup - SetRaidDifficulty(Difficulty(raidDiff)); // may be changed in _LoadGroup + SetDungeonDifficultyID(CheckLoadedDungeonDifficultyID(Difficulty(fields[39].GetUInt8()))); + SetRaidDifficultyID(CheckLoadedRaidDifficultyID(Difficulty(fields[60].GetUInt8()))); + SetLegacyRaidDifficultyID(CheckLoadedLegacyRaidDifficultyID(Difficulty(fields[61].GetUInt8()))); std::string taxi_nodes = fields[38].GetString(); @@ -16979,7 +16975,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) // fix crash (because of if (Map* map = _FindMap(instanceId)) in MapInstanced::CreateInstance) if (instanceId) - if (InstanceSave* save = GetInstanceSave(mapId, mapEntry->IsRaid())) + if (InstanceSave* save = GetInstanceSave(mapId)) if (save->GetInstanceId() != instanceId) instanceId = 0; } @@ -17042,7 +17038,6 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) } SetMap(map); - StoreRaidMapDifficulty(); // randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE] // this must help in case next save after mass player load after server startup @@ -18300,8 +18295,9 @@ void Player::_LoadGroup(PreparedQueryResult result) if (getLevel() >= LEVELREQUIREMENT_HEROIC) { // the group leader may change the instance difficulty while the player is offline - SetDungeonDifficulty(group->GetDungeonDifficulty()); - SetRaidDifficulty(group->GetRaidDifficulty()); + SetDungeonDifficultyID(group->GetDungeonDifficultyID()); + SetRaidDifficultyID(group->GetRaidDifficultyID()); + SetLegacyRaidDifficultyID(group->GetLegacyRaidDifficultyID()); } } } @@ -18398,9 +18394,10 @@ InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, Difficulty difficulty return NULL; } -InstanceSave* Player::GetInstanceSave(uint32 mapid, bool raid) +InstanceSave* Player::GetInstanceSave(uint32 mapid) { - InstancePlayerBind* pBind = GetBoundInstance(mapid, GetDifficulty(raid)); + MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); + InstancePlayerBind* pBind = GetBoundInstance(mapid, GetDifficultyID(mapEntry)); InstanceSave* pSave = pBind ? pBind->save : NULL; if (!pBind || !pBind->perm) if (Group* group = GetGroup()) @@ -18442,7 +18439,7 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave* save, bool permanent, b { if (save) { - InstancePlayerBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()]; + InstancePlayerBind& bind = m_boundInstances[save->GetDifficultyID()][save->GetMapId()]; if (!load) { if (bind.save) @@ -18485,8 +18482,8 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave* save, bool permanent, b bind.save = save; bind.perm = permanent; if (!load) - TC_LOG_DEBUG("maps", "Player::BindToInstance: %s(%s) is now bound to map %d, instance %d, difficulty %d", GetName().c_str(), GetGUID().ToString().c_str(), save->GetMapId(), save->GetInstanceId(), save->GetDifficulty()); - sScriptMgr->OnPlayerBindToInstance(this, save->GetDifficulty(), save->GetMapId(), permanent); + TC_LOG_DEBUG("maps", "Player::BindToInstance: %s(%s) is now bound to map %d, instance %d, difficulty %d", GetName().c_str(), GetGUID().ToString().c_str(), save->GetMapId(), save->GetInstanceId(), save->GetDifficultyID()); + sScriptMgr->OnPlayerBindToInstance(this, save->GetDifficultyID(), save->GetMapId(), permanent); return &bind; } @@ -18531,14 +18528,14 @@ void Player::SendRaidInfo() if (itr->second.perm) { InstanceSave* save = itr->second.save; - bool isHeroic = save->GetDifficulty() == DIFFICULTY_10_HC || save->GetDifficulty() == DIFFICULTY_25_HC; + bool isHeroic = save->GetDifficultyID() == DIFFICULTY_10_HC || save->GetDifficultyID() == DIFFICULTY_25_HC; uint32 completedEncounters = 0; if (Map* map = sMapMgr->FindMap(save->GetMapId(), save->GetInstanceId())) if (InstanceScript* instanceScript = ((InstanceMap*)map)->GetInstanceScript()) completedEncounters = instanceScript->GetCompletedEncounterMask(); data << uint32(save->GetMapId()); // map id - data << uint32(save->GetDifficulty()); // difficulty + data << uint32(save->GetDifficultyID()); // difficulty data << uint32(isHeroic); // heroic data << uint64(save->GetInstanceId()); // instance id data << uint8(1); // expired = 0 @@ -18606,7 +18603,7 @@ void Player::ConvertInstancesToGroup(Player* player, Group* group, bool switchLe { for (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();) { - if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficulty(), itr->first)) + if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficultyID(), itr->first)) group->BindToInstance(itr->second.save, itr->second.perm, false); // permanent binds are not removed @@ -18672,7 +18669,7 @@ bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report if (!leader || !leader->HasAchieved(ar->achievement)) missingAchievement = ar->achievement; - Difficulty target_difficulty = GetDifficulty(mapEntry->IsRaid()); + Difficulty target_difficulty = GetDifficultyID(mapEntry); MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(target_map, target_difficulty); if (LevelMin || LevelMax || missingItem || missingQuest || missingAchievement) { @@ -18838,7 +18835,7 @@ void Player::SaveToDB(bool create /*=false*/) stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS)); stmt->setUInt16(index++, (uint16)GetMapId()); stmt->setUInt32(index++, (uint32)GetInstanceId()); - stmt->setUInt8(index++, (uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4)); + stmt->setUInt8(index++, (uint8(GetDungeonDifficultyID()) | uint8(GetRaidDifficultyID()) << 4)); stmt->setFloat(index++, finiteAlways(GetPositionX())); stmt->setFloat(index++, finiteAlways(GetPositionY())); stmt->setFloat(index++, finiteAlways(GetPositionZ())); @@ -18959,7 +18956,9 @@ void Player::SaveToDB(bool create /*=false*/) { stmt->setUInt16(index++, (uint16)GetMapId()); stmt->setUInt32(index++, (uint32)GetInstanceId()); - stmt->setUInt8(index++, (uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4)); + stmt->setUInt8(index++, uint8(GetDungeonDifficultyID())); + stmt->setUInt8(index++, uint8(GetRaidDifficultyID())); + stmt->setUInt8(index++, uint8(GetLegacyRaidDifficultyID())); stmt->setFloat(index++, finiteAlways(GetPositionX())); stmt->setFloat(index++, finiteAlways(GetPositionY())); stmt->setFloat(index++, finiteAlways(GetPositionZ())); @@ -18969,7 +18968,9 @@ void Player::SaveToDB(bool create /*=false*/) { stmt->setUInt16(index++, (uint16)GetTeleportDest().GetMapId()); stmt->setUInt32(index++, (uint32)0); - stmt->setUInt8(index++, (uint8(GetDungeonDifficulty()) | uint8(GetRaidDifficulty()) << 4)); + stmt->setUInt8(index++, uint8(GetDungeonDifficultyID())); + stmt->setUInt8(index++, uint8(GetRaidDifficultyID())); + stmt->setUInt8(index++, uint8(GetLegacyRaidDifficultyID())); stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionX())); stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionY())); stmt->setFloat(index++, finiteAlways(GetTeleportDest().GetPositionZ())); @@ -19963,24 +19964,19 @@ void Player::SendExplorationExperience(uint32 Area, uint32 Experience) GetSession()->SendPacket(&data); } -void Player::SendDungeonDifficulty(bool IsInGroup) +void Player::SendDungeonDifficulty() { - uint8 val = 0x00000001; - WorldPacket data(MSG_SET_DUNGEON_DIFFICULTY, 12); - data << (uint32)GetDungeonDifficulty(); - data << uint32(val); - data << uint32(IsInGroup); - GetSession()->SendPacket(&data); + WorldPackets::Misc::DungeonDifficultySet dungeonDifficultySet; + dungeonDifficultySet.DifficultyID = GetDungeonDifficultyID(); + GetSession()->SendPacket(dungeonDifficultySet.Write()); } -void Player::SendRaidDifficulty(bool IsInGroup, int32 forcedDifficulty) +void Player::SendRaidDifficulty(bool legacy, int32 forcedDifficulty /*= -1*/) { - uint8 val = 0x00000001; - WorldPacket data(MSG_SET_RAID_DIFFICULTY, 12); - data << uint32(forcedDifficulty == -1 ? GetRaidDifficulty() : forcedDifficulty); - data << uint32(val); - data << uint32(IsInGroup); - GetSession()->SendPacket(&data); + WorldPackets::Misc::RaidDifficultySet raidDifficultySet; + raidDifficultySet.DifficultyID = forcedDifficulty == -1 ? (legacy ? GetLegacyRaidDifficultyID() : GetRaidDifficultyID()) : forcedDifficulty; + raidDifficultySet.Legacy = legacy; + GetSession()->SendPacket(raidDifficultySet.Write()); } void Player::SendResetFailedNotify(uint32 /*mapid*/) @@ -19990,12 +19986,19 @@ void Player::SendResetFailedNotify(uint32 /*mapid*/) } /// Reset all solo instances and optionally send a message on success for each -void Player::ResetInstances(uint8 method, bool isRaid) +void Player::ResetInstances(uint8 method, bool isRaid, bool isLegacy) { // method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_JOIN // we assume that when the difficulty changes, all instances that can be reset will be - Difficulty diff = GetDifficulty(isRaid); + Difficulty diff = GetDungeonDifficultyID(); + if (isRaid) + { + if (!isLegacy) + diff = GetRaidDifficultyID(); + else + diff = GetLegacyRaidDifficultyID(); + } for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end();) { @@ -22867,11 +22870,11 @@ void Player::SendInitialPacketsBeforeAddToMap() WorldPackets::Misc::WorldServerInfo worldServerInfo; worldServerInfo.IneligibleForLootMask.Clear(); /// @todo worldServerInfo.WeeklyReset = sWorld->GetNextWeeklyQuestsResetTime() - WEEK; - worldServerInfo.InstanceGroupSize.Clear(); /// @todo + worldServerInfo.InstanceGroupSize.Set(GetMap()->GetMapDifficulty()->maxPlayers); worldServerInfo.IsTournamentRealm = 0; /// @todo worldServerInfo.RestrictedAccountMaxLevel.Clear(); /// @todo worldServerInfo.RestrictedAccountMaxMoney.Clear(); /// @todo - worldServerInfo.DifficultyID = GetMap()->GetDifficulty(); + worldServerInfo.DifficultyID = GetMap()->GetDifficultyID(); SendDirectMessage(worldServerInfo.Write()); // SMSG_TALENTS_INFO x 2 for pet (unspent points and talents in separate packets...) @@ -22925,17 +22928,13 @@ void Player::SendInitialPacketsAfterAddToMap() SendEnchantmentDurations(); // must be after add to map SendItemDurations(); // must be after add to map - // raid downscaling - send difficulty to player if (GetMap()->IsRaid()) { - if (GetMap()->GetDifficulty() != GetRaidDifficulty()) - { - StoreRaidMapDifficulty(); - SendRaidDifficulty(GetGroup() != NULL, GetStoredRaidDifficulty()); - } + DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(GetMap()->GetDifficultyID()); + SendRaidDifficulty((difficulty->Flags & DIFFICULTY_FLAG_LEGACY) != 0, GetMap()->GetDifficultyID()); } - else if (GetRaidDifficulty() != GetStoredRaidDifficulty()) - SendRaidDifficulty(GetGroup() != NULL); + else if (GetMap()->IsNonRaidDungeon()) + SendDungeonDifficulty(); } void Player::SendUpdateToOutOfRangeGroupMembers() @@ -23603,7 +23602,7 @@ bool Player::HasQuestForGO(int32 GOId) const if (!qInfo) continue; - if (GetGroup() && GetGroup()->isRaidGroup() && !qInfo->IsAllowedInRaid(GetMap()->GetDifficulty())) + if (GetGroup() && GetGroup()->isRaidGroup() && !qInfo->IsAllowedInRaid(GetMap()->GetDifficultyID())) continue; for (QuestObjective const& obj : qInfo->GetObjectives()) @@ -24323,7 +24322,7 @@ bool Player::inRandomLfgDungeon() if (sLFGMgr->selectedRandomLfgDungeon(GetGUID())) { Map const* map = GetMap(); - return sLFGMgr->inLfgDungeonMap(GetGUID(), map->GetId(), map->GetDifficulty()); + return sLFGMgr->inLfgDungeonMap(GetGUID(), map->GetId(), map->GetDifficultyID()); } return false; @@ -27070,3 +27069,64 @@ uint32 Player::CalculateTalentsPoints() const // 1 talent point for every 15 levels return getLevel() >= 100 ? 7 : uint32(floor(getLevel() / 15.f)); } + +Difficulty Player::GetDifficultyID(MapEntry const* mapEntry) const +{ + if (!mapEntry->IsRaid()) + return m_dungeonDifficulty; + + MapDifficulty const* defaultDifficulty = GetDefaultMapDifficulty(mapEntry->ID); + if (!defaultDifficulty) + return m_legacyRaidDifficulty; + + DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(defaultDifficulty->DifficultyID); + if (!difficulty || difficulty->Flags & DIFFICULTY_FLAG_LEGACY) + return m_legacyRaidDifficulty; + + return m_raidDifficulty; +} + +Difficulty Player::CheckLoadedDungeonDifficultyID(Difficulty difficulty) +{ + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); + if (!difficultyEntry) + return DIFFICULTY_NORMAL; + + if (difficultyEntry->InstanceType != MAP_INSTANCE) + return DIFFICULTY_NORMAL; + + if (!(difficultyEntry->Flags & DIFFICULTY_FLAG_CAN_SELECT)) + return DIFFICULTY_NORMAL; + + return difficulty; +} + +Difficulty Player::CheckLoadedRaidDifficultyID(Difficulty difficulty) +{ + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); + if (!difficultyEntry) + return DIFFICULTY_NORMAL_RAID; + + if (difficultyEntry->InstanceType != MAP_INSTANCE) + return DIFFICULTY_NORMAL_RAID; + + if (!(difficultyEntry->Flags & DIFFICULTY_FLAG_CAN_SELECT) || (difficultyEntry->Flags & DIFFICULTY_FLAG_LEGACY)) + return DIFFICULTY_NORMAL_RAID; + + return difficulty; +} + +Difficulty Player::CheckLoadedLegacyRaidDifficultyID(Difficulty difficulty) +{ + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); + if (!difficultyEntry) + return DIFFICULTY_10_N; + + if (difficultyEntry->InstanceType != MAP_INSTANCE) + return DIFFICULTY_10_N; + + if (!(difficultyEntry->Flags & DIFFICULTY_FLAG_CAN_SELECT) || !(difficultyEntry->Flags & DIFFICULTY_FLAG_LEGACY)) + return DIFFICULTY_10_N; + + return difficulty; +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1c76e594236..5b768ceee8d 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2006,13 +2006,16 @@ class Player : public Unit, public GridObject<Player> uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; } uint32 GetRBGPersonalRating() const { return 0; } - Difficulty GetDifficulty(bool isRaid) const { return isRaid ? m_raidDifficulty : m_dungeonDifficulty; } - Difficulty GetDungeonDifficulty() const { return m_dungeonDifficulty; } - Difficulty GetRaidDifficulty() const { return m_raidDifficulty; } - Difficulty GetStoredRaidDifficulty() const { return m_raidMapDifficulty; } // only for use in difficulty packet after exiting to raid map - void SetDungeonDifficulty(Difficulty dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; } - void SetRaidDifficulty(Difficulty raid_difficulty) { m_raidDifficulty = raid_difficulty; } - void StoreRaidMapDifficulty() { m_raidMapDifficulty = GetMap()->GetDifficulty(); } + Difficulty GetDifficultyID(MapEntry const* mapEntry) const; + Difficulty GetDungeonDifficultyID() const { return m_dungeonDifficulty; } + Difficulty GetRaidDifficultyID() const { return m_raidDifficulty; } + Difficulty GetLegacyRaidDifficultyID() const { return m_legacyRaidDifficulty; } + void SetDungeonDifficultyID(Difficulty dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; } + void SetRaidDifficultyID(Difficulty raid_difficulty) { m_raidDifficulty = raid_difficulty; } + void SetLegacyRaidDifficultyID(Difficulty raid_difficulty) { m_legacyRaidDifficulty = raid_difficulty; } + static Difficulty CheckLoadedDungeonDifficultyID(Difficulty difficulty); + static Difficulty CheckLoadedRaidDifficultyID(Difficulty difficulty); + static Difficulty CheckLoadedLegacyRaidDifficultyID(Difficulty difficulty); bool UpdateSkill(uint32 skill_id, uint32 step); bool UpdateSkillPro(uint16 skillId, int32 chance, uint32 step); @@ -2100,9 +2103,9 @@ class Player : public Unit, public GridObject<Player> void SendAutoRepeatCancel(Unit* target); void SendExplorationExperience(uint32 Area, uint32 Experience); - void SendDungeonDifficulty(bool IsInGroup); - void SendRaidDifficulty(bool IsInGroup, int32 forcedDifficulty = -1); - void ResetInstances(uint8 method, bool isRaid); + void SendDungeonDifficulty(); + void SendRaidDifficulty(bool legacy, int32 forcedDifficulty = -1); + void ResetInstances(uint8 method, bool isRaid, bool isLegacy); void SendResetInstanceSuccess(uint32 MapId); void SendResetInstanceFailed(uint32 reason, uint32 MapId); void SendResetFailedNotify(uint32 mapid); @@ -2468,7 +2471,7 @@ class Player : public Unit, public GridObject<Player> BoundInstancesMap m_boundInstances[MAX_DIFFICULTY]; InstancePlayerBind* GetBoundInstance(uint32 mapid, Difficulty difficulty); BoundInstancesMap& GetBoundInstances(Difficulty difficulty) { return m_boundInstances[difficulty]; } - InstanceSave* GetInstanceSave(uint32 mapid, bool raid); + InstanceSave* GetInstanceSave(uint32 mapid); void UnbindInstance(uint32 mapid, Difficulty difficulty, bool unload = false); void UnbindInstance(BoundInstancesMap::iterator &itr, Difficulty difficulty, bool unload = false); InstancePlayerBind* BindToInstance(InstanceSave* save, bool permanent, bool load = false); @@ -2732,6 +2735,7 @@ class Player : public Unit, public GridObject<Player> uint32 m_speakCount; Difficulty m_dungeonDifficulty; Difficulty m_raidDifficulty; + Difficulty m_legacyRaidDifficulty; Difficulty m_raidMapDifficulty; uint32 m_atLoginFlags; diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 3929af2e3e7..1a7a7fbb00a 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -145,7 +145,7 @@ bool Totem::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) con /// @todo possibly all negative auras immune? if (GetEntry() == 5925) return false; - if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), index)) + if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), index)) { switch (effect->ApplyAuraName) { diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 481d7fb3632..cbb62fcad73 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -990,7 +990,7 @@ bool Guardian::UpdateStats(Stats stat) if (aurEff) { 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)) + if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), EFFECT_1)) AddPct(mod, effect->CalcValue(owner)); // Ravenous Dead edits the original scale } // Glyph of the Ghoul diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a412cf43a7a..1469336a3a8 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1414,7 +1414,7 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s return false; // bleeding effects are not reduced by armor - if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), effIndex)) + if (SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), effIndex)) { if (effect->ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE || effect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE) @@ -2153,12 +2153,12 @@ int32 Unit::GetMechanicResistChance(SpellInfo const* spellInfo) const return 0; int32 resistMech = 0; - for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (!effect || !effect->IsEffect()) break; - int32 effectMech = spellInfo->GetEffectMechanic(effect->EffectIndex, GetMap()->GetDifficulty()); + int32 effectMech = spellInfo->GetEffectMechanic(effect->EffectIndex, GetMap()->GetDifficultyID()); if (effectMech) { int32 temp = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effectMech); @@ -2213,7 +2213,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, GetMap()->GetDifficulty()); + int32 effect_mech = spellInfo->GetEffectMechanic(eff, GetMap()->GetDifficultyID()); if (effect_mech) { int32 temp = victim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech); @@ -3107,7 +3107,7 @@ AuraApplication * Unit::_CreateAuraApplication(Aura* aura, uint32 effMask) AddInterruptMask(aurSpellInfo->AuraInterruptFlags); } - if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficulty())) + if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficultyID())) m_auraStateAuras.insert(AuraStateAurasMap::value_type(aState, aurApp)); aura->_ApplyForTarget(this, caster, aurApp); @@ -3138,7 +3138,7 @@ void Unit::_ApplyAura(AuraApplication * aurApp, uint32 effMask) return; // Update target aura state flag - if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficulty())) + if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficultyID())) ModifyAuraState(aState, true); if (aurApp->GetRemoveMode()) @@ -3193,7 +3193,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo } bool auraStateFound = false; - AuraStateType auraState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficulty()); + AuraStateType auraState = aura->GetSpellInfo()->GetAuraState(GetMap()->GetDifficultyID()); if (auraState) { bool canBreak = false; @@ -3269,12 +3269,12 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura) SpellInfo const* spellProto = aura->GetSpellInfo(); // passive spell special case (only non stackable with ranks) - if (spellProto->IsPassiveStackableWithRanks(GetMap()->GetDifficulty())) + if (spellProto->IsPassiveStackableWithRanks(GetMap()->GetDifficultyID())) return; if (!IsHighestExclusiveAura(aura)) { - if (!aura->GetSpellInfo()->IsAffectingArea(GetMap()->GetDifficulty())) + if (!aura->GetSpellInfo()->IsAffectingArea(GetMap()->GetDifficultyID())) { Unit* caster = aura->GetCaster(); if (caster && caster->GetTypeId() == TYPEID_PLAYER) @@ -3866,7 +3866,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(GetMap()->GetDifficulty(), type)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type)) ++iter; else _UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -3875,7 +3875,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(GetMap()->GetDifficulty(), type)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type)) ++iter; else RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -3887,7 +3887,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(GetMap()->GetDifficulty(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type2)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type2)) ++iter; else _UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -3896,7 +3896,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(GetMap()->GetDifficulty(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficulty(), type2)) + if (aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type1) || aura->GetSpellInfo()->HasAura(GetMap()->GetDifficultyID(), type2)) ++iter; else RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT); @@ -6574,7 +6574,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg } // not allow proc extra attack spell at extra attack - if (m_extraAttacks && triggerEntry->HasEffect(GetMap()->GetDifficulty(), SPELL_EFFECT_ADD_EXTRA_ATTACKS)) + if (m_extraAttacks && triggerEntry->HasEffect(GetMap()->GetDifficultyID(), SPELL_EFFECT_ADD_EXTRA_ATTACKS)) return false; // Custom requirements (not listed in procEx) Warning! damage dealing after this @@ -6790,7 +6790,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg return false; // extra attack should hit same target - if (triggerEntry->HasEffect(GetMap()->GetDifficulty(), SPELL_EFFECT_ADD_EXTRA_ATTACKS)) + if (triggerEntry->HasEffect(GetMap()->GetDifficultyID(), SPELL_EFFECT_ADD_EXTRA_ATTACKS)) target = victim; // try detect target manually if not set @@ -8838,7 +8838,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); } - for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (!effect) continue; @@ -8999,7 +8999,7 @@ uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, u if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectingSpell(spellProto)) AddPct(TakenTotalMod, (*i)->GetAmount()); - for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (!effect) continue; @@ -9142,7 +9142,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const } bool immuneToAllEffects = true; - for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { // State/effect immunities applied by aura expect full spell immunity // Ignore effects with mechanic, they are supposed to be checked separately @@ -9179,7 +9179,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons if (!spellInfo) return false; - SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficulty(), index); + SpellEffectInfo const* effect = spellInfo->GetEffect(GetMap()->GetDifficultyID(), index); if (!effect || !effect->IsEffect()) return false; @@ -9267,7 +9267,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType { bool normalized = false; if (spellProto) - for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) if (effect && effect->Effect == SPELL_EFFECT_NORMALIZED_WEAPON_DMG) { normalized = true; @@ -9873,7 +9873,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->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficulty())) : !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficulty())))) + if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficultyID())) : !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficultyID())))) return false; // can't attack dead @@ -9994,7 +9994,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co return false; // can't assist invisible - if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficulty()))) + if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea(GetMap()->GetDifficultyID()))) return false; // can't assist dead @@ -10762,7 +10762,7 @@ float Unit::ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index // function uses real base points (typically value - 1) int32 Unit::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints /*= nullptr*/, float* variance /*= nullptr*/) const { - SpellEffectInfo const* effect = spellProto->GetEffect(GetMap()->GetDifficulty(), effect_index); + SpellEffectInfo const* effect = spellProto->GetEffect(GetMap()->GetDifficultyID(), effect_index); if (variance) *variance = 0.0f; @@ -12785,7 +12785,7 @@ uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectTyp bool DirectDamage = false; bool AreaEffect = false; - for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (!effect) continue; @@ -12844,7 +12844,7 @@ 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 (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (!effect) continue; @@ -12912,7 +12912,7 @@ float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffect if (!spellInfo->IsChanneled() && DotDuration > 0) DotFactor = DotDuration / 15000.0f; - if (uint32 DotTicks = spellInfo->GetMaxTicks(GetMap()->GetDifficulty())) + if (uint32 DotTicks = spellInfo->GetMaxTicks(GetMap()->GetDifficultyID())) DotFactor /= DotTicks; } @@ -15012,7 +15012,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) { uint8 i = 0; bool valid = false; - for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) { if (!effect) continue; @@ -15036,7 +15036,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) else // This can happen during Player::_LoadAuras { int32 bp0[MAX_SPELL_EFFECTS]; - for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellEntry->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) if (effect) bp0[effect->EffectIndex] = effect->BasePoints; @@ -16244,7 +16244,7 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) // this also applies for transform auras if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(getTransForm())) - for (SpellEffectInfo const* effect : transform->GetEffectsForDifficulty(GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : transform->GetEffectsForDifficulty(GetMap()->GetDifficultyID())) if (effect && effect->IsAura(SPELL_AURA_TRANSFORM)) if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(effect->MiscValue)) { @@ -16421,7 +16421,7 @@ bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplicat { if (AuraApplication* aurApp = existingAurEff->GetBase()->GetApplicationOfTarget(GetGUID())) { - bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType, GetMap()->GetDifficulty()); + bool hasMoreThanOneEffect = base->HasMoreThanOneEffectForType(auraType, GetMap()->GetDifficultyID()); uint32 removedAuras = m_removedAurasCount; RemoveAura(aurApp); if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras + 1) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 00bb77a5a1e..270674fdba6 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -225,7 +225,20 @@ enum UnitBytes0Offsets { UNIT_BYTES_0_OFFSET_RACE = 0, UNIT_BYTES_0_OFFSET_CLASS = 1, - UNIT_BYTES_0_OFFSET_GENDER = 3, + UNIT_BYTES_0_OFFSET_GENDER = 3 +}; + +enum UnitBytes1Offsets +{ + UNIT_BYTES_1_OFFSET_STAND_STATE = 0, + UNIT_BYTES_1_OFFSET_VIS_FLAG = 2, + UNIT_BYTES_1_OFFSET_ANIM_TIER = 3 +}; + +enum UnitBytes2Offsets +{ + UNIT_BYTES_2_OFFSET_SHEATH_STATE = 0, + UNIT_BYTES_2_OFFSET_PVP_FLAG = 1, }; // byte flags value (UNIT_FIELD_BYTES_1, 3) diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 72b4d7be0b0..6c29b9a64a9 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -467,7 +467,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields) creatureTemplate.Entry = entry; - for (uint8 i = 0; i < MAX_DIFFICULTY - 1; ++i) + for (uint8 i = 0; i < MAX_CREATURE_DIFFICULTIES; ++i) creatureTemplate.DifficultyEntry[i] = fields[1 + i].GetUInt32(); for (uint8 i = 0; i < MAX_KILL_CREDIT; ++i) @@ -626,7 +626,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) return; bool ok = true; // bool to allow continue outside this loop - for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) + for (uint32 diff = 0; diff < MAX_CREATURE_DIFFICULTIES && ok; ++diff) { if (!cInfo->DifficultyEntry[diff]) continue; @@ -641,7 +641,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) } bool ok2 = true; - for (uint32 diff2 = 0; diff2 < MAX_DIFFICULTY - 1 && ok2; ++diff2) + for (uint32 diff2 = 0; diff2 < MAX_CREATURE_DIFFICULTIES && ok2; ++diff2) { ok2 = false; if (_difficultyEntries[diff2].find(cInfo->Entry) != _difficultyEntries[diff2].end()) @@ -1660,11 +1660,10 @@ void ObjectMgr::LoadCreatures() // Build single time for check spawnmask std::map<uint32, uint32> spawnMasks; - for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) - if (sMapStore.LookupEntry(i)) - for (int k = 0; k < MAX_DIFFICULTY; ++k) - if (GetMapDifficultyData(i, Difficulty(k))) - spawnMasks[i] |= (1 << k); + for (auto& mapDifficultyPair : sMapDifficultyMap) + for (auto& difficultyPair : mapDifficultyPair.second) + spawnMasks[mapDifficultyPair.first] |= (1 << difficultyPair.first); + _creatureDataStore.rehash(result->GetRowCount()); @@ -1697,7 +1696,7 @@ void ObjectMgr::LoadCreatures() data.curhealth = fields[12].GetUInt32(); data.curmana = fields[13].GetUInt32(); data.movementType = fields[14].GetUInt8(); - data.spawnMask = fields[15].GetUInt8(); + data.spawnMask = fields[15].GetUInt32(); data.phaseMask = fields[16].GetUInt32(); int16 gameEvent = fields[17].GetInt8(); uint32 PoolId = fields[18].GetUInt32(); @@ -1719,7 +1718,7 @@ void ObjectMgr::LoadCreatures() TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD ") that have wrong spawn mask %u including unsupported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid); bool ok = true; - for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) + for (uint32 diff = 0; diff < MAX_CREATURE_DIFFICULTIES && ok; ++diff) { if (_difficultyEntries[diff].find(data.id) != _difficultyEntries[diff].end()) { @@ -1813,7 +1812,7 @@ void ObjectMgr::LoadCreatures() void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* data) { - uint8 mask = data->spawnMask; + uint32 mask = data->spawnMask; for (uint8 i = 0; mask != 0; i++, mask >>= 1) { if (mask & 1) @@ -1827,7 +1826,7 @@ void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData const* data) { - uint8 mask = data->spawnMask; + uint32 mask = data->spawnMask; for (uint8 i = 0; mask != 0; i++, mask >>= 1) { if (mask & 1) @@ -1994,11 +1993,9 @@ void ObjectMgr::LoadGameobjects() // build single time for check spawnmask std::map<uint32, uint32> spawnMasks; - for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) - if (sMapStore.LookupEntry(i)) - for (int k = 0; k < MAX_DIFFICULTY; ++k) - if (GetMapDifficultyData(i, Difficulty(k))) - spawnMasks[i] |= (1 << k); + for (auto& mapDifficultyPair : sMapDifficultyMap) + for (auto& difficultyPair : mapDifficultyPair.second) + spawnMasks[mapDifficultyPair.first] |= (1 << difficultyPair.first); _gameObjectDataStore.rehash(result->GetRowCount()); @@ -2075,7 +2072,7 @@ void ObjectMgr::LoadGameobjects() } data.go_state = GOState(go_state); - data.spawnMask = fields[14].GetUInt8(); + data.spawnMask = fields[14].GetUInt32(); if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) that has wrong spawn mask %u including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); @@ -2147,7 +2144,7 @@ void ObjectMgr::LoadGameobjects() void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data) { - uint8 mask = data->spawnMask; + uint32 mask = data->spawnMask; for (uint8 i = 0; mask != 0; i++, mask >>= 1) { if (mask & 1) @@ -2161,7 +2158,7 @@ void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData con void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data) { - uint8 mask = data->spawnMask; + uint32 mask = data->spawnMask; for (uint8 i = 0; mask != 0; i++, mask >>= 1) { if (mask & 1) diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 5de0862c330..95bbe693335 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1437,8 +1437,8 @@ class ObjectMgr CacheVendorItemContainer _cacheVendorItemStore; CacheTrainerSpellContainer _cacheTrainerSpellStore; - std::set<uint32> _difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate - std::set<uint32> _hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate + std::set<uint32> _difficultyEntries[MAX_CREATURE_DIFFICULTIES]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate + std::set<uint32> _hasDifficultyEntries[MAX_CREATURE_DIFFICULTIES]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate ExpansionRequirementContainer _raceExpansionRequirementStore; ExpansionRequirementContainer _classExpansionRequirementStore; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 0bc69fc7183..9da1337b065 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(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_10_N), +m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_NORMAL_RAID), m_legacyRaidDifficulty(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) { @@ -112,12 +112,14 @@ bool Group::Create(Player* leader) m_masterLooterGuid.Clear(); m_dungeonDifficulty = DIFFICULTY_NORMAL; - m_raidDifficulty = DIFFICULTY_10_N; + m_raidDifficulty = DIFFICULTY_NORMAL_RAID; + m_legacyRaidDifficulty = DIFFICULTY_10_N; if (!isBGGroup() && !isBFGroup()) { - m_dungeonDifficulty = leader->GetDungeonDifficulty(); - m_raidDifficulty = leader->GetRaidDifficulty(); + m_dungeonDifficulty = leader->GetDungeonDifficultyID(); + m_raidDifficulty = leader->GetRaidDifficultyID(); + m_legacyRaidDifficulty = leader->GetLegacyRaidDifficultyID(); m_dbStoreId = sGroupMgr->GenerateNewGroupDbStoreId(); @@ -144,6 +146,7 @@ bool Group::Create(Player* leader) stmt->setUInt8(index++, uint8(m_groupType)); stmt->setUInt32(index++, uint8(m_dungeonDifficulty)); stmt->setUInt32(index++, uint8(m_raidDifficulty)); + stmt->setUInt32(index++, uint8(m_legacyRaidDifficulty)); stmt->setUInt64(index++, m_masterLooterGuid.GetCounter()); CharacterDatabase.Execute(stmt); @@ -180,17 +183,8 @@ void Group::LoadGroupFromDB(Field* fields) if (m_groupType & GROUPTYPE_RAID) _initRaidSubGroupsCounter(); - uint32 diff = fields[13].GetUInt8(); - if (diff >= MAX_DUNGEON_DIFFICULTY) - m_dungeonDifficulty = DIFFICULTY_NORMAL; - else - m_dungeonDifficulty = Difficulty(diff); - - uint32 r_diff = fields[14].GetUInt8(); - if (r_diff >= MAX_RAID_DIFFICULTY) - m_raidDifficulty = DIFFICULTY_10_N; - else - m_raidDifficulty = Difficulty(r_diff); + m_dungeonDifficulty = Player::CheckLoadedDungeonDifficultyID(Difficulty(fields[13].GetUInt8())); + m_raidDifficulty = Player::CheckLoadedRaidDifficultyID(Difficulty(fields[14].GetUInt8())); m_masterLooterGuid = ObjectGuid::Create<HighGuid::Player>(fields[15].GetUInt64()); @@ -437,19 +431,25 @@ bool Group::AddMember(Player* player) { // reset the new member's instances, unless he is currently in one of them // including raid/heroic instances that they are not permanently bound to! - player->ResetInstances(INSTANCE_RESET_GROUP_JOIN, false); - player->ResetInstances(INSTANCE_RESET_GROUP_JOIN, true); + player->ResetInstances(INSTANCE_RESET_GROUP_JOIN, false, false); + player->ResetInstances(INSTANCE_RESET_GROUP_JOIN, true, false); + player->ResetInstances(INSTANCE_RESET_GROUP_JOIN, true, true); if (player->getLevel() >= LEVELREQUIREMENT_HEROIC) { - if (player->GetDungeonDifficulty() != GetDungeonDifficulty()) + if (player->GetDungeonDifficultyID() != GetDungeonDifficultyID()) { - player->SetDungeonDifficulty(GetDungeonDifficulty()); - player->SendDungeonDifficulty(true); + player->SetDungeonDifficultyID(GetDungeonDifficultyID()); + player->SendDungeonDifficulty(); } - if (player->GetRaidDifficulty() != GetRaidDifficulty()) + if (player->GetRaidDifficultyID() != GetRaidDifficultyID()) { - player->SetRaidDifficulty(GetRaidDifficulty()); + player->SetRaidDifficultyID(GetRaidDifficultyID()); + player->SendRaidDifficulty(false); + } + if (player->GetLegacyRaidDifficultyID() != GetLegacyRaidDifficultyID()) + { + player->SetLegacyRaidDifficultyID(GetLegacyRaidDifficultyID()); player->SendRaidDifficulty(true); } } @@ -783,8 +783,9 @@ void Group::Disband(bool hideDestroy /* = false */) CharacterDatabase.CommitTransaction(trans); - ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, NULL); - ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL); + ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, false, NULL); + ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, false, NULL); + ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, true, NULL); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_LFG_DATA); stmt->setUInt32(0, m_dbStoreId); @@ -1924,7 +1925,7 @@ void Roll::targetObjectBuildLink() getTarget()->addLootValidatorRef(this); } -void Group::SetDungeonDifficulty(Difficulty difficulty) +void Group::SetDungeonDifficultyID(Difficulty difficulty) { m_dungeonDifficulty = difficulty; if (!isBGGroup() && !isBFGroup()) @@ -1943,12 +1944,12 @@ void Group::SetDungeonDifficulty(Difficulty difficulty) if (!player->GetSession()) continue; - player->SetDungeonDifficulty(difficulty); - player->SendDungeonDifficulty(true); + player->SetDungeonDifficultyID(difficulty); + player->SendDungeonDifficulty(); } } -void Group::SetRaidDifficulty(Difficulty difficulty) +void Group::SetRaidDifficultyID(Difficulty difficulty) { m_raidDifficulty = difficulty; if (!isBGGroup() && !isBFGroup()) @@ -1967,25 +1968,52 @@ void Group::SetRaidDifficulty(Difficulty difficulty) if (!player->GetSession()) continue; - player->SetRaidDifficulty(difficulty); - player->SendRaidDifficulty(true); + player->SetRaidDifficultyID(difficulty); + player->SendRaidDifficulty(false); } } -bool Group::InCombatToInstance(uint32 instanceId) +void Group::SetLegacyRaidDifficultyID(Difficulty difficulty) { + m_legacyRaidDifficulty = difficulty; + if (!isBGGroup() && !isBFGroup()) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEGACY_RAID_DIFFICULTY); + + stmt->setUInt8(0, uint8(m_legacyRaidDifficulty)); + stmt->setUInt32(1, m_dbStoreId); + + CharacterDatabase.Execute(stmt); + } + for (GroupReference* itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); - if (player && !player->getAttackers().empty() && player->GetInstanceId() == instanceId && (player->GetMap()->IsRaidOrHeroicDungeon())) - for (std::set<Unit*>::const_iterator i = player->getAttackers().begin(); i != player->getAttackers().end(); ++i) - if ((*i) && (*i)->GetTypeId() == TYPEID_UNIT && (*i)->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) - return true; + if (!player->GetSession()) + continue; + + player->SetLegacyRaidDifficultyID(difficulty); + player->SendRaidDifficulty(true); } - return false; } -void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo) +Difficulty Group::GetDifficultyID(MapEntry const* mapEntry) const +{ + if (!mapEntry->IsRaid()) + return m_dungeonDifficulty; + + MapDifficulty const* defaultDifficulty = GetDefaultMapDifficulty(mapEntry->ID); + if (!defaultDifficulty) + return m_legacyRaidDifficulty; + + DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(defaultDifficulty->DifficultyID); + if (!difficulty || difficulty->Flags & DIFFICULTY_FLAG_LEGACY) + return m_legacyRaidDifficulty; + + return m_raidDifficulty; +} + +void Group::ResetInstances(uint8 method, bool isRaid, bool isLegacy, Player* SendMsgTo) { if (isBGGroup() || isBFGroup()) return; @@ -1993,7 +2021,14 @@ void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo) // method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND // we assume that when the difficulty changes, all instances that can be reset will be - Difficulty diff = GetDifficulty(isRaid); + Difficulty diff = GetDungeonDifficultyID(); + if (isRaid) + { + if (!isLegacy) + diff = GetRaidDifficultyID(); + else + diff = GetLegacyRaidDifficultyID(); + } for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end();) { @@ -2082,9 +2117,7 @@ InstanceGroupBind* Group::GetBoundInstance(Player* player) InstanceGroupBind* Group::GetBoundInstance(Map* aMap) { - // Currently spawn numbering not different from map difficulty - Difficulty difficulty = GetDifficulty(aMap->IsRaid()); - return GetBoundInstance(difficulty, aMap->GetId()); + return GetBoundInstance(aMap->GetEntry()); } InstanceGroupBind* Group::GetBoundInstance(MapEntry const* mapEntry) @@ -2092,7 +2125,7 @@ InstanceGroupBind* Group::GetBoundInstance(MapEntry const* mapEntry) if (!mapEntry || !mapEntry->IsDungeon()) return NULL; - Difficulty difficulty = GetDifficulty(mapEntry->IsRaid()); + Difficulty difficulty = GetDifficultyID(mapEntry); return GetBoundInstance(difficulty, mapEntry->ID); } @@ -2113,7 +2146,7 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave* save, bool permanent, boo if (!save || isBGGroup() || isBFGroup()) return NULL; - InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()]; + InstanceGroupBind& bind = m_boundInstances[save->GetDifficultyID()][save->GetMapId()]; if (!load && (!bind.save || permanent != bind.perm || save != bind.save)) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GROUP_INSTANCE); @@ -2136,7 +2169,7 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave* save, bool permanent, boo bind.perm = permanent; if (!load) TC_LOG_DEBUG("maps", "Group::BindToInstance: %s, storage id: %u is now bound to map %d, instance %d, difficulty %d", - GetGUID().ToString().c_str(), m_dbStoreId, save->GetMapId(), save->GetInstanceId(), save->GetDifficulty()); + GetGUID().ToString().c_str(), m_dbStoreId, save->GetMapId(), save->GetInstanceId(), save->GetDifficultyID()); return &bind; } @@ -2396,26 +2429,6 @@ void Group::SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags fla SendUpdate(); } -Difficulty Group::GetDifficulty(bool isRaid) const -{ - return isRaid ? m_raidDifficulty : m_dungeonDifficulty; -} - -Difficulty Group::GetDungeonDifficulty() const -{ - return m_dungeonDifficulty; -} - -Difficulty Group::GetRaidDifficulty() const -{ - return m_raidDifficulty; -} - -bool Group::isRollLootActive() const -{ - return !RollId.empty(); -} - Group::Rolls::iterator Group::GetRoll(ObjectGuid Guid) { Rolls::iterator iter; diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 538be5ea508..ab256704ad5 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -258,14 +258,14 @@ class Group void SetGroupMemberFlag(ObjectGuid guid, bool apply, GroupMemberFlags flag); void RemoveUniqueGroupMemberFlag(GroupMemberFlags flag); - Difficulty GetDifficulty(bool isRaid) const; - Difficulty GetDungeonDifficulty() const; - Difficulty GetRaidDifficulty() const; - void SetDungeonDifficulty(Difficulty difficulty); - void SetRaidDifficulty(Difficulty difficulty); - uint16 InInstance(); - bool InCombatToInstance(uint32 instanceId); - void ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo); + void SetDungeonDifficultyID(Difficulty difficulty); + void SetRaidDifficultyID(Difficulty difficulty); + void SetLegacyRaidDifficultyID(Difficulty difficulty); + Difficulty GetDifficultyID(MapEntry const* mapEntry) const; + Difficulty GetDungeonDifficultyID() const { return m_dungeonDifficulty; } + Difficulty GetRaidDifficultyID() const { return m_raidDifficulty; } + Difficulty GetLegacyRaidDifficultyID() const { return m_legacyRaidDifficulty; } + void ResetInstances(uint8 method, bool isRaid, bool isLegacy, Player* SendMsgTo); // -no description- //void SendInit(WorldSession* session); @@ -297,7 +297,7 @@ class Group /*** LOOT SYSTEM ***/ /*********************************************************/ - bool isRollLootActive() const; + bool isRollLootActive() const { return !RollId.empty(); } void SendLootStartRoll(uint32 CountDown, uint32 mapid, const Roll &r); void SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, bool canNeed, Roll const& r); void SendLootRoll(ObjectGuid SourceGuid, ObjectGuid TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); @@ -348,6 +348,7 @@ class Group GroupType m_groupType; Difficulty m_dungeonDifficulty; Difficulty m_raidDifficulty; + Difficulty m_legacyRaidDifficulty; Battleground* m_bgGroup; Battlefield* m_bfGroup; ObjectGuid m_targetIcons[TARGETICONCOUNT]; diff --git a/src/server/game/Groups/GroupMgr.cpp b/src/server/game/Groups/GroupMgr.cpp index 217a2dfd442..f0a0aa5604f 100644 --- a/src/server/game/Groups/GroupMgr.cpp +++ b/src/server/game/Groups/GroupMgr.cpp @@ -220,11 +220,9 @@ void GroupMgr::LoadGroups() } uint32 diff = fields[4].GetUInt8(); - if (diff >= uint32(mapEntry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) - { - TC_LOG_ERROR("sql.sql", "Wrong dungeon difficulty use in group_instance table: %d", diff + 1); - diff = 0; // default for both difficaly types - } + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(diff); + if (!difficultyEntry || difficultyEntry->InstanceType != mapEntry->InstanceType) + continue; InstanceSave* save = sInstanceSaveMgr->AddInstanceSave(mapEntry->ID, fields[2].GetUInt32(), Difficulty(diff), time_t(fields[5].GetUInt32()), fields[6].GetUInt64() != 0, true); group->BindToInstance(save, fields[3].GetBool(), true); diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp index 457f2ae2faf..f2410f2ffd9 100644 --- a/src/server/game/Handlers/CalendarHandler.cpp +++ b/src/server/game/Handlers/CalendarHandler.cpp @@ -111,7 +111,7 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/) { InstanceSave const* save = itr->second.save; dataBuffer << uint32(save->GetMapId()); - dataBuffer << uint32(save->GetDifficulty()); + dataBuffer << uint32(save->GetDifficultyID()); dataBuffer << uint32(save->GetResetTime() - currTime); dataBuffer << uint64(save->GetInstanceId()); // instance save id as unique instance copy id ++boundCounter; @@ -726,7 +726,7 @@ void WorldSession::SendCalendarRaidLockout(InstanceSave const* save, bool add) } data << uint32(save->GetMapId()); - data << uint32(save->GetDifficulty()); + data << uint32(save->GetDifficultyID()); data << uint32(save->GetResetTime() - currTime); data << uint64(save->GetInstanceId()); SendPacket(&data); @@ -739,14 +739,14 @@ void WorldSession::SendCalendarRaidLockoutUpdated(InstanceSave const* save) ObjectGuid guid = _player->GetGUID(); TC_LOG_DEBUG("network", "SMSG_CALENDAR_RAID_LOCKOUT_UPDATED [%s] Map: %u, Difficulty %u", - guid.ToString().c_str(), save->GetMapId(), save->GetDifficulty()); + guid.ToString().c_str(), save->GetMapId(), save->GetDifficultyID()); time_t currTime = time(NULL); WorldPacket data(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, 4 + 4 + 4 + 4 + 8); data.AppendPackedTime(currTime); data << uint32(save->GetMapId()); - data << uint32(save->GetDifficulty()); + data << uint32(save->GetDifficultyID()); data << uint32(0); // Amount of seconds that has changed to the reset time data << uint32(save->GetResetTime() - currTime); SendPacket(&data); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index de074443a39..84e6ed34bb8 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -845,7 +845,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) SendTutorialsData(); pCurrChar->GetMotionMaster()->Initialize(); - pCurrChar->SendDungeonDifficulty(false); + pCurrChar->SendDungeonDifficulty(); WorldPackets::Character::LoginVerifyWorld loginVerifyWorld; loginVerifyWorld.MapID = pCurrChar->GetMapId(); @@ -873,7 +873,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) features.ScrollOfResurrectionMaxRequestsPerDay = 1; features.CfgRealmID = 2; features.CfgRealmRecID = 0; - features.VoiceEnabled = true; + features.VoiceEnabled = false; /// END OF DUMMY VALUES features.CharUndeleteEnabled = sWorld->getBoolConfig(CONFIG_FEATURE_SYSTEM_CHARACTER_UNDELETE_ENABLED); @@ -2489,6 +2489,7 @@ void WorldSession::SendCharRename(ResponseCodes result, WorldPackets::Character: void WorldSession::SendCharCustomize(ResponseCodes result, WorldPackets::Character::CharCustomizeInfo const* customizeInfo) { /// @todo: fix 6.x implementation + (void)result; (void)customizeInfo; /* WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1 + 8 + customizeInfo.NewName.size() + 1 + 6); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index 97b25d5fc1b..9f42c4591ea 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -134,7 +134,7 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData) return; } // just ignore us - if (player->GetInstanceId() != 0 && player->GetDungeonDifficulty() != GetPlayer()->GetDungeonDifficulty()) + if (player->GetInstanceId() != 0 && player->GetDungeonDifficultyID() != GetPlayer()->GetDungeonDifficultyID()) { SendPartyResult(PARTY_OP_INVITE, memberName, ERR_IGNORING_YOU_S); return; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 1bdb0fd703e..569bcf73ffa 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1540,26 +1540,38 @@ void WorldSession::HandleResetInstancesOpcode(WorldPacket& /*recvData*/) if (Group* group = _player->GetGroup()) { if (group->IsLeader(_player->GetGUID())) - group->ResetInstances(INSTANCE_RESET_ALL, false, _player); + group->ResetInstances(INSTANCE_RESET_ALL, false, false, _player); } else - _player->ResetInstances(INSTANCE_RESET_ALL, false); + _player->ResetInstances(INSTANCE_RESET_ALL, false, false); } -void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData) +void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty) { - TC_LOG_DEBUG("network", "MSG_SET_DUNGEON_DIFFICULTY"); + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(setDungeonDifficulty.DifficultyID); + if (!difficultyEntry) + { + TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent an invalid instance mode %d!", + _player->GetGUID().ToString().c_str(), setDungeonDifficulty.DifficultyID); + return; + } - uint32 mode; - recvData >> mode; + if (difficultyEntry->InstanceType != MAP_INSTANCE) + { + TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent an non-dungeon instance mode %d!", + _player->GetGUID().ToString().c_str(), difficultyEntry->ID); + return; + } - if (mode >= MAX_DUNGEON_DIFFICULTY) + if (!(difficultyEntry->Flags & DIFFICULTY_FLAG_CAN_SELECT)) { - TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent an invalid instance mode %d!", _player->GetGUID().ToString().c_str(), mode); + TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent unselectable instance mode %d!", + _player->GetGUID().ToString().c_str(), difficultyEntry->ID); return; } - if (Difficulty(mode) == _player->GetDungeonDifficulty()) + Difficulty difficultyID = Difficulty(difficultyEntry->ID); + if (difficultyID == _player->GetDungeonDifficultyID()) return; // cannot reset while in an instance @@ -1594,41 +1606,62 @@ void WorldSession::HandleSetDungeonDifficultyOpcode(WorldPacket& recvData) } // the difficulty is set even if the instances can't be reset //_player->SendDungeonDifficulty(true); - group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, _player); - group->SetDungeonDifficulty(Difficulty(mode)); + group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, false, _player); + group->SetDungeonDifficultyID(difficultyID); } } else { - _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false); - _player->SetDungeonDifficulty(Difficulty(mode)); + _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, false, false); + _player->SetDungeonDifficultyID(difficultyID); + _player->SendDungeonDifficulty(); } } -void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData) +void WorldSession::HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDifficulty& setRaidDifficulty) { - TC_LOG_DEBUG("network", "MSG_SET_RAID_DIFFICULTY"); + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(setRaidDifficulty.DifficultyID); + if (!difficultyEntry) + { + TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent an invalid instance mode %u!", + _player->GetGUID().ToString().c_str(), setRaidDifficulty.DifficultyID); + return; + } - uint32 mode; - recvData >> mode; + if (difficultyEntry->InstanceType != MAP_RAID) + { + TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent an non-dungeon instance mode %u!", + _player->GetGUID().ToString().c_str(), difficultyEntry->ID); + return; + } - if (mode >= MAX_RAID_DIFFICULTY) + if (!(difficultyEntry->Flags & DIFFICULTY_FLAG_CAN_SELECT)) { - TC_LOG_ERROR("network", "WorldSession::HandleSetRaidDifficultyOpcode: %s sent an invalid instance mode %d!", _player->GetGUID().ToString().c_str(), mode); + TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent unselectable instance mode %u!", + _player->GetGUID().ToString().c_str(), difficultyEntry->ID); return; } + if (((difficultyEntry->Flags & DIFFICULTY_FLAG_LEGACY) >> 5) != setRaidDifficulty.Legacy) + { + TC_LOG_DEBUG("network", "WorldSession::HandleSetDungeonDifficultyOpcode: %s sent not matching legacy difficulty %u!", + _player->GetGUID().ToString().c_str(), difficultyEntry->ID); + return; + } + + Difficulty difficultyID = Difficulty(difficultyEntry->ID); + if (difficultyID == (setRaidDifficulty.Legacy ? _player->GetLegacyRaidDifficultyID() : _player->GetRaidDifficultyID())) + return; + // cannot reset while in an instance Map* map = _player->FindMap(); if (map && map->IsDungeon()) { - TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: %s tried to reset the instance while inside!", _player->GetGUID().ToString().c_str()); + TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: player (Name: %s, %s) tried to reset the instance while player is inside!", + _player->GetName().c_str(), _player->GetGUID().ToString().c_str()); return; } - if (Difficulty(mode) == _player->GetRaidDifficulty()) - return; - Group* group = _player->GetGroup(); if (group) { @@ -1645,20 +1678,28 @@ void WorldSession::HandleSetRaidDifficultyOpcode(WorldPacket& recvData) if (groupGuy->GetMap()->IsRaid()) { - TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: %s tried to reset the instance while inside!", _player->GetGUID().ToString().c_str()); + TC_LOG_DEBUG("network", "WorldSession::HandleSetRaidDifficultyOpcode: %s tried to reset the instance while group member (Name: %s, %s) is inside!", + _player->GetGUID().ToString().c_str(), groupGuy->GetName().c_str(), groupGuy->GetGUID().ToString().c_str()); return; } } // the difficulty is set even if the instances can't be reset - //_player->SendDungeonDifficulty(true); - group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, _player); - group->SetRaidDifficulty(Difficulty(mode)); + group->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, setRaidDifficulty.Legacy != 0, _player); + if (setRaidDifficulty.Legacy) + group->SetLegacyRaidDifficultyID(difficultyID); + else + group->SetRaidDifficultyID(difficultyID); } } else { - _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true); - _player->SetRaidDifficulty(Difficulty(mode)); + _player->ResetInstances(INSTANCE_RESET_CHANGE_DIFFICULTY, true, setRaidDifficulty.Legacy != 0); + if (setRaidDifficulty.Legacy) + _player->SetLegacyRaidDifficultyID(difficultyID); + else + _player->SetRaidDifficultyID(difficultyID); + + _player->SendRaidDifficulty(setRaidDifficulty.Legacy != 0); } } diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index f4d9c7d10ca..e1e5ae49778 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -158,7 +158,7 @@ void WorldSession::HandleMoveWorldportAckOpcode() bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena(); if (mInstance) { - Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); + Difficulty diff = GetPlayer()->GetDifficultyID(mEntry); if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->ID, diff)) { if (mapDiff->resetTime) diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 2f5d7f9f8f1..9423cd78aa3 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -51,13 +51,13 @@ void InstanceSaveManager::Unload() for (InstanceSave::PlayerListType::iterator itr2 = save->m_playerList.begin(), next = itr2; itr2 != save->m_playerList.end(); itr2 = next) { ++next; - (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true); + (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficultyID(), true); } for (InstanceSave::GroupListType::iterator itr2 = save->m_groupList.begin(), next = itr2; itr2 != save->m_groupList.end(); itr2 = next) { ++next; - (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficulty(), true); + (*itr2)->UnbindInstance(save->GetMapId(), save->GetDifficultyID(), true); } delete save; @@ -86,7 +86,8 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance return NULL; } - if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY)) + DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty); + if (!difficultyEntry || difficultyEntry->InstanceType != entry->InstanceType) { TC_LOG_ERROR("misc", "InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty); return NULL; @@ -203,7 +204,7 @@ void InstanceSave::SaveToDB() stmt->setUInt32(0, m_instanceid); stmt->setUInt16(1, GetMapId()); stmt->setUInt32(2, uint32(GetResetTimeForDB())); - stmt->setUInt8(3, uint8(GetDifficulty())); + stmt->setUInt8(3, uint8(GetDifficultyID())); stmt->setUInt32(4, completedEncounters); stmt->setString(5, data); CharacterDatabase.Execute(stmt); @@ -213,7 +214,7 @@ time_t InstanceSave::GetResetTimeForDB() { // only save the reset time for normal instances const MapEntry* entry = sMapStore.LookupEntry(GetMapId()); - if (!entry || entry->IsRaid() || GetDifficulty() == DIFFICULTY_HEROIC) + if (!entry || entry->IsRaid() || GetDifficultyID() == DIFFICULTY_HEROIC) return 0; else return GetResetTime(); @@ -391,50 +392,53 @@ void InstanceSaveManager::LoadResetTimes() // calculate new global reset times for expired instances and those that have never been reset yet // add the global reset times to the priority queue - for (MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr) + for (auto& mapDifficultyPair : sMapDifficultyMap) { - uint32 map_diff_pair = itr->first; - uint32 mapid = PAIR32_LOPART(map_diff_pair); - Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair)); - MapDifficulty const* mapDiff = &itr->second; - if (!mapDiff->resetTime) - continue; - - // the reset_delay must be at least one day - uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME))/DAY) * DAY); - if (period < DAY) - period = DAY; + uint32 mapid = mapDifficultyPair.first; - time_t t = GetResetTimeFor(mapid, difficulty); - if (!t) + for (auto& difficultyPair : mapDifficultyPair.second) { - // initialize the reset time - t = today + period + diff; - CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u', '%u', '%u')", mapid, difficulty, (uint32)t); - } + Difficulty difficulty = Difficulty(difficultyPair.first); + MapDifficulty const* mapDiff = &difficultyPair.second; + if (!mapDiff->resetTime) + continue; - if (t < now) - { - // assume that expired instances have already been cleaned - // calculate the next reset time - t = (t / DAY) * DAY; - t += ((today - t) / period + 1) * period + diff; - CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); - } + // the reset_delay must be at least one day + uint32 period = uint32(((mapDiff->resetTime * sWorld->getRate(RATE_INSTANCE_RESET_TIME)) / DAY) * DAY); + if (period < DAY) + period = DAY; + + time_t t = GetResetTimeFor(mapid, difficulty); + if (!t) + { + // initialize the reset time + t = today + period + diff; + CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u', '%u', '%u')", mapid, difficulty, (uint32)t); + } - InitializeResetTimeFor(mapid, difficulty, t); + if (t < now) + { + // assume that expired instances have already been cleaned + // calculate the next reset time + t = (t / DAY) * DAY; + t += ((today - t) / period + 1) * period + diff; + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); + } - // schedule the global reset/warning - uint8 type; - for (type = 1; type < 4; ++type) - if (t - ResetTimeDelay[type-1] > now) - break; + InitializeResetTimeFor(mapid, difficulty, t); - ScheduleReset(true, t - ResetTimeDelay[type-1], InstResetEvent(type, mapid, difficulty, 0)); + // schedule the global reset/warning + uint8 type; + for (type = 1; type < 4; ++type) + if (t - ResetTimeDelay[type - 1] > now) + break; - ResetTimeMapDiffInstancesBounds range = mapDiffResetInstances.equal_range(map_diff_pair); - for (; range.first != range.second; ++range.first) - ScheduleReset(true, t - ResetTimeDelay[type-1], InstResetEvent(type, mapid, difficulty, range.first->second)); + ScheduleReset(true, t - ResetTimeDelay[type - 1], InstResetEvent(type, mapid, difficulty, 0)); + + ResetTimeMapDiffInstancesBounds range = mapDiffResetInstances.equal_range(MAKE_PAIR32(mapid, difficulty)); + for (; range.first != range.second; ++range.first) + ScheduleReset(true, t - ResetTimeDelay[type - 1], InstResetEvent(type, mapid, difficulty, range.first->second)); + } } } @@ -519,14 +523,14 @@ void InstanceSaveManager::_ResetSave(InstanceSaveHashMap::iterator &itr) while (!pList.empty()) { Player* player = *(pList.begin()); - player->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficulty(), true); + player->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficultyID(), true); } InstanceSave::GroupListType &gList = itr->second->m_groupList; while (!gList.empty()) { Group* group = *(gList.begin()); - group->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficulty(), true); + group->UnbindInstance(itr->second->GetMapId(), itr->second->GetDifficultyID(), true); } delete itr->second; @@ -583,7 +587,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b // remove all binds to instances of the given map for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();) { - if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) + if (itr->second->GetMapId() == mapid && itr->second->GetDifficultyID() == difficulty) _ResetSave(itr); else ++itr; diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index bba89a77e42..1b7f5502049 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -118,7 +118,7 @@ class InstanceSave /* currently it is possible to omit this information from this structure but that would depend on a lot of things that can easily change in future */ - Difficulty GetDifficulty() const { return m_difficulty; } + Difficulty GetDifficultyID() const { return m_difficulty; } /* used to flag the InstanceSave as to be deleted, so the caller can delete it */ void SetToDelete(bool toDelete) diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 29a2b96a985..b8f95b9407c 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -589,7 +589,7 @@ void InstanceScript::SendEncounterUnit(uint32 type, Unit* unit /*= NULL*/, uint8 void InstanceScript::UpdateEncounterState(EncounterCreditType type, uint32 creditEntry, Unit* /*source*/) { - DungeonEncounterList const* encounters = sObjectMgr->GetDungeonEncounterList(instance->GetId(), instance->GetDifficulty()); + DungeonEncounterList const* encounters = sObjectMgr->GetDungeonEncounterList(instance->GetId(), instance->GetDifficultyID()); if (!encounters) return; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 20473192f75..29041b5bccb 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2956,7 +2956,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) // cannot enter other instances if bound permanently if (playerBind->save != mapSave) { - TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%s) is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); + TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%s) is permanently bound to instance %s %d, %d, %d, %d, %d, %d but he is being put into instance %s %d, %d, %d, %d, %d, %d", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficultyID(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficultyID(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset()); return false; } } @@ -2968,9 +2968,9 @@ bool InstanceMap::AddPlayerToMap(Player* player) InstanceGroupBind* groupBind = group->GetBoundInstance(this); if (playerBind && playerBind->save != mapSave) { - TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%s) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %s and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); + TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%s) is being put into instance %s %d, %d, %d, %d, %d, %d but he is in group %s and is bound to instance %d, %d, %d, %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetMapName(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficultyID(), mapSave->GetPlayerCount(), mapSave->GetGroupCount(), mapSave->CanReset(), group->GetLeaderGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficultyID(), playerBind->save->GetPlayerCount(), playerBind->save->GetGroupCount(), playerBind->save->CanReset()); if (groupBind) - TC_LOG_ERROR("maps", "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); + TC_LOG_ERROR("maps", "InstanceMap::Add: the group is bound to the instance %s %d, %d, %d, %d, %d, %d", GetMapName(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficultyID(), groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount(), groupBind->save->CanReset()); //ASSERT(false); return false; } @@ -2982,7 +2982,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) // cannot jump to a different instance without resetting it if (groupBind->save != mapSave) { - TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%s) is being put into instance %d, %d, %d but he is in group %s which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); + TC_LOG_ERROR("maps", "InstanceMap::Add: player %s(%s) is being put into instance %d, %d, %d but he is in group %s which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUID().ToString().c_str(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficultyID(), group->GetLeaderGUID().ToString().c_str(), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficultyID()); TC_LOG_ERROR("maps", "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); if (groupBind->save) TC_LOG_ERROR("maps", "GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); @@ -3153,7 +3153,7 @@ void InstanceMap::PermBindAllPlayers(Player* source) Player* player = itr->GetSource(); // players inside an instance cannot be bound to other instances // some players may already be permanently bound, in this case nothing happens - InstancePlayerBind* bind = player->GetBoundInstance(save->GetMapId(), save->GetDifficulty()); + InstancePlayerBind* bind = player->GetBoundInstance(save->GetMapId(), save->GetDifficultyID()); if (!bind || !bind->perm) { player->BindToInstance(save, true); @@ -3183,7 +3183,7 @@ void InstanceMap::UnloadAll() void InstanceMap::SendResetWarnings(uint32 timeLeft) const { for (MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - itr->GetSource()->SendInstanceResetWarning(GetId(), itr->GetSource()->GetDifficulty(IsRaid()), timeLeft); + itr->GetSource()->SendInstanceResetWarning(GetId(), itr->GetSource()->GetDifficultyID(GetEntry()), timeLeft); } void InstanceMap::SetResetSchedule(bool on) @@ -3203,7 +3203,14 @@ void InstanceMap::SetResetSchedule(bool on) MapDifficulty const* Map::GetMapDifficulty() const { - return GetMapDifficultyData(GetId(), GetDifficulty()); + return GetMapDifficultyData(GetId(), GetDifficultyID()); +} + +bool Map::IsHeroic() const +{ + if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(i_spawnMode)) + return difficulty->Flags & DIFFICULTY_FLAG_HEROIC; + return false; } uint32 InstanceMap::GetMaxPlayers() const diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 7bd21b57072..94b89484e15 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -385,17 +385,16 @@ class Map : public GridRefManager<NGridType> const char* GetMapName() const; // have meaning only for instanced map (that have set real difficulty) - Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); } - bool IsRegularDifficulty() const { return GetDifficulty() == DIFFICULTY_NONE; } + Difficulty GetDifficultyID() const { return Difficulty(GetSpawnMode()); } 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 > 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 IsRaidOrHeroicDungeon() const { return IsRaid() || IsHeroic(); } + bool IsHeroic() const; + bool Is25ManRaid() const { return IsRaid() && (i_spawnMode == DIFFICULTY_25_N || i_spawnMode == DIFFICULTY_25_HC); } // 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(); } bool IsBattlegroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattlegroundOrArena(); } diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 1a9a5d5698d..cc0c99adc99 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -140,7 +140,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) } else { - InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficulty(IsRaid())); + InstancePlayerBind* pBind = player->GetBoundInstance(GetId(), player->GetDifficultyID(GetEntry())); InstanceSave* pSave = pBind ? pBind->save : NULL; // the player's permanent player bind is taken into consideration first @@ -164,7 +164,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) map = FindInstanceMap(newInstanceId); // it is possible that the save exists but the map doesn't if (!map) - map = CreateInstance(newInstanceId, pSave, pSave->GetDifficulty()); + map = CreateInstance(newInstanceId, pSave, pSave->GetDifficultyID()); } else { @@ -172,7 +172,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player) // the instance will be created for the first time newInstanceId = sMapMgr->GenerateInstanceId(); - Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficulty(IsRaid()) : player->GetDifficulty(IsRaid()); + Difficulty diff = player->GetGroup() ? player->GetGroup()->GetDifficultyID(GetEntry()) : player->GetDifficultyID(GetEntry()); //Seems it is now possible, but I do not know if it should be allowed //ASSERT(!FindInstanceMap(NewInstanceId)); map = FindInstanceMap(newInstanceId); diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index d2198d02013..a9acb2ef30a 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -133,7 +133,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) return false; Difficulty targetDifficulty, requestedDifficulty; - targetDifficulty = requestedDifficulty = player->GetDifficulty(entry->IsRaid()); + targetDifficulty = requestedDifficulty = player->GetDifficultyID(entry); // Get the highest available difficulty if current setting is higher than the instance allows MapDifficulty const* mapDiff = GetDownscaledMapDifficultyData(entry->ID, targetDifficulty); if (!mapDiff) @@ -203,7 +203,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) /* This check has to be moved to InstanceMap::CanEnter() // Player permanently bounded to different instance than groups one - InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficulty(entry->IsRaid())); + InstancePlayerBind* playerBoundedInstance = player->GetBoundInstance(mapid, player->GetDifficultyID(entry)); if (playerBoundedInstance && playerBoundedInstance->perm && playerBoundedInstance->save && boundedInstance->save->GetInstanceId() != playerBoundedInstance->save->GetInstanceId()) { @@ -216,7 +216,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck) if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup()))) { uint32 instanceIdToCheck = 0; - if (InstanceSave* save = player->GetInstanceSave(mapid, entry->IsRaid())) + if (InstanceSave* save = player->GetInstanceSave(mapid)) instanceIdToCheck = save->GetInstanceId(); // instanceId can never be 0 - will not be found diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 2801dbead33..cd5b79c95c3 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -316,9 +316,9 @@ bool Quest::IsRaidQuest(Difficulty difficulty) const case QUEST_INFO_RAID: return true; case QUEST_INFO_RAID_10: - return !(difficulty & RAID_DIFFICULTY_MASK_25MAN); + return difficulty == DIFFICULTY_10_N || difficulty == DIFFICULTY_10_HC; case QUEST_INFO_RAID_25: - return difficulty & RAID_DIFFICULTY_MASK_25MAN; + return difficulty == DIFFICULTY_25_N || difficulty == DIFFICULTY_25_HC; default: break; } diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp index a9955bf7449..937bd75c4b9 100644 --- a/src/server/game/Server/Packets/MiscPackets.cpp +++ b/src/server/game/Server/Packets/MiscPackets.cpp @@ -183,3 +183,27 @@ void WorldPackets::Misc::AreaTrigger::Read() Entered = _worldPacket.ReadBit(); FromClient = _worldPacket.ReadBit(); } + +void WorldPackets::Misc::SetDungeonDifficulty::Read() +{ + _worldPacket >> DifficultyID; +} + +void WorldPackets::Misc::SetRaidDifficulty::Read() +{ + _worldPacket >> DifficultyID; + _worldPacket >> Legacy; +} + +WorldPacket const* WorldPackets::Misc::DungeonDifficultySet::Write() +{ + _worldPacket << int32(DifficultyID); + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Misc::RaidDifficultySet::Write() +{ + _worldPacket << int32(DifficultyID); + _worldPacket << uint8(Legacy); + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h index f42d560f36d..ae12389e791 100644 --- a/src/server/game/Server/Packets/MiscPackets.h +++ b/src/server/game/Server/Packets/MiscPackets.h @@ -96,10 +96,10 @@ namespace WorldPackets { int32 Type = 0; // ID from CurrencyTypes.dbc int32 Quantity = 0; - Optional<int32> WeeklyQuantity; // Currency count obtained this Week. + Optional<int32> WeeklyQuantity; // Currency count obtained this Week. Optional<int32> MaxWeeklyQuantity; // Weekly Currency cap. Optional<int32> TrackedQuantity; - uint8 Flags = 0; // 0 = none, + uint8 Flags = 0; // 0 = none, }; SetupCurrency() : ServerPacket(SMSG_SETUP_CURRENCY, 22) { } @@ -221,6 +221,48 @@ namespace WorldPackets bool Entered = false; bool FromClient = false; }; + + class SetDungeonDifficulty final : public ClientPacket + { + public: + SetDungeonDifficulty(WorldPacket&& packet) : ClientPacket(CMSG_SET_DUNGEON_DIFFICULTY, std::move(packet)) { } + + void Read() override; + + int32 DifficultyID; + }; + + class SetRaidDifficulty final : public ClientPacket + { + public: + SetRaidDifficulty(WorldPacket&& packet) : ClientPacket(CMSG_SET_RAID_DIFFICULTY, std::move(packet)) { } + + void Read() override; + + int32 DifficultyID; + uint8 Legacy; + }; + + class DungeonDifficultySet final : public ServerPacket + { + public: + DungeonDifficultySet() : ServerPacket(SMSG_SET_DUNGEON_DIFFICULTY, 4) { } + + WorldPacket const* Write() override; + + int32 DifficultyID; + }; + + class RaidDifficultySet final : public ServerPacket + { + public: + RaidDifficultySet() : ServerPacket(SMSG_SET_RAID_DIFFICULTY, 4 + 1) { } + + WorldPacket const* Write() override; + + int32 DifficultyID; + uint8 Legacy; + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index d2956f64e27..d1502e0c863 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -603,6 +603,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_ALLOW_LOW_LEVEL_RAID2, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_CONTACT_NOTES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetContactNotesOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_CURRENCY_FLAGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_HANDLER(CMSG_SET_DUNGEON_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetDungeonDifficulty, &WorldSession::HandleSetDungeonDifficultyOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_EVERYONE_IS_ASSISTANT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_ATWAR, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_INACTIVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode ); @@ -612,7 +613,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PREFERED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PVP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_RAID_DIFFICULTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_HANDLER(CMSG_SET_RAID_DIFFICULTY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetRaidDifficulty, &WorldSession::HandleSetRaidDifficultyOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_RELATIVE_POSITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend ); DEFINE_HANDLER(CMSG_SET_SELECTION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Misc::SetSelection, &WorldSession::HandleSetSelectionOpcode); @@ -698,8 +699,6 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(MSG_RAID_READY_CHECK_FINISHED, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidReadyCheckFinishedOpcode); DEFINE_OPCODE_HANDLER_OLD(MSG_RAID_TARGET_UPDATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRaidTargetUpdateOpcode ); DEFINE_OPCODE_HANDLER_OLD(MSG_SAVE_GUILD_EMBLEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSaveGuildEmblemOpcode ); - DEFINE_OPCODE_HANDLER_OLD(MSG_SET_DUNGEON_DIFFICULTY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetDungeonDifficultyOpcode); - DEFINE_OPCODE_HANDLER_OLD(MSG_SET_RAID_DIFFICULTY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetRaidDifficultyOpcode ); DEFINE_OPCODE_HANDLER_OLD(MSG_TABARDVENDOR_ACTIVATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTabardVendorActivateOpcode); DEFINE_OPCODE_HANDLER_OLD(MSG_TALENT_WIPE_CONFIRM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleTalentWipeConfirmOpcode ); @@ -1306,6 +1305,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_ALL_TASK_PROGRESS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_CURRENCY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_DF_FAST_LAUNCH_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_DUNGEON_DIFFICULTY, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_ATWAR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_NOT_VISIBLE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_FACTION_STANDING, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); @@ -1321,6 +1321,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PLAY_HOVER_ANIM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PROFICIENCY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_PROJECTILE_POSITION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_RAID_DIFFICULTY, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SET_TIME_ZONE_INFORMATION, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SETUP_CURRENCY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOWTAXINODES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 3177cb77d2a..b33f218c898 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -552,6 +552,7 @@ enum OpcodeClient : uint32 CMSG_SET_ALLOW_LOW_LEVEL_RAID2 = 0xBADD, CMSG_SET_CONTACT_NOTES = 0xBADD, CMSG_SET_CURRENCY_FLAGS = 0xBADD, + CMSG_SET_DUNGEON_DIFFICULTY = 0x012F, CMSG_SET_EVERYONE_IS_ASSISTANT = 0xBADD, CMSG_SET_FACTION_ATWAR = 0xBADD, CMSG_SET_FACTION_CHEAT = 0xBADD, @@ -563,7 +564,7 @@ enum OpcodeClient : uint32 CMSG_SET_PLAYER_DECLINED_NAMES = 0xBADD, CMSG_SET_PREFERED_CEMETERY = 0xBADD, CMSG_SET_PVP = 0x19B9, - CMSG_SET_RAID_DIFFICULTY = 0xBADD, + CMSG_SET_RAID_DIFFICULTY = 0x1121, CMSG_SET_RELATIVE_POSITION = 0xBADD, CMSG_SET_SAVED_INSTANCE_EXTEND = 0xBADD, CMSG_SET_SELECTION = 0x05BD, @@ -671,8 +672,6 @@ enum OpcodeClient : uint32 MSG_RAID_READY_CHECK_FINISHED = 0xBADD, MSG_RAID_TARGET_UPDATE = 0xBADD, MSG_SAVE_GUILD_EMBLEM = 0xBADD, - MSG_SET_DUNGEON_DIFFICULTY = 0xBADD, - MSG_SET_RAID_DIFFICULTY = 0xBADD, MSG_TABARDVENDOR_ACTIVATE = 0xBADD, MSG_TALENT_WIPE_CONFIRM = 0xBADD }; @@ -1309,6 +1308,7 @@ enum OpcodeServer : uint32 SMSG_SET_ALL_TASK_PROGRESS = 0x1B52, SMSG_SET_CURRENCY = 0x17BE, SMSG_SET_DF_FAST_LAUNCH_RESULT = 0xBADD, + SMSG_SET_DUNGEON_DIFFICULTY = 0x0719, SMSG_SET_FACTION_ATWAR = 0xBADD, SMSG_SET_FACTION_NOT_VISIBLE = 0xBADD, SMSG_SET_FACTION_STANDING = 0xBADD, @@ -1324,6 +1324,7 @@ enum OpcodeServer : uint32 SMSG_SET_PLAY_HOVER_ANIM = 0x02D4, SMSG_SET_PROFICIENCY = 0x00D3, SMSG_SET_PROJECTILE_POSITION = 0xBADD, + SMSG_SET_RAID_DIFFICULTY = 0x051F, SMSG_SET_TIME_ZONE_INFORMATION = 0x153E, SMSG_SET_VIGNETTE = 0x09AC, SMSG_SETUP_CURRENCY = 0x0B06, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 1779530fcba..ae14b0667a9 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -171,6 +171,8 @@ namespace WorldPackets class ViolenceLevel; class TimeSyncResponse; class TutorialSetFlag; + class SetDungeonDifficulty; + class SetRaidDifficulty; } namespace Movement @@ -1028,8 +1030,8 @@ class WorldSession void HandleMinimapPingOpcode(WorldPacket& recvData); void HandleRandomRollOpcode(WorldPacket& recvData); void HandleFarSightOpcode(WorldPacket& recvData); - void HandleSetDungeonDifficultyOpcode(WorldPacket& recvData); - void HandleSetRaidDifficultyOpcode(WorldPacket& recvData); + void HandleSetDungeonDifficultyOpcode(WorldPackets::Misc::SetDungeonDifficulty& setDungeonDifficulty); + void HandleSetRaidDifficultyOpcode(WorldPackets::Misc::SetRaidDifficulty& setRaidDifficulty); void HandleMoveSetCanFlyAckOpcode(WorldPacket& recvData); void HandleSetTitleOpcode(WorldPacket& recvData); void HandleRealmSplitOpcode(WorldPacket& recvData); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b851db186dc..819942901cb 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5274,7 +5274,7 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo if (!triggeredSpellInfo) return; - Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? GetCaster() : target; + Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficultyID()) ? GetCaster() : target; if (!caster) return; @@ -5290,13 +5290,13 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo } else { - ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficulty()) ? GetCasterGUID() : target->GetGUID(); + ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficultyID()) ? GetCasterGUID() : target->GetGUID(); target->RemoveAura(triggeredSpellId, casterGUID, 0, aurApp->GetRemoveMode()); } } else if (mode & AURA_EFFECT_HANDLE_REAPPLY && apply) { - ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficulty()) ? GetCasterGUID() : target->GetGUID(); + ObjectGuid casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, caster->GetMap()->GetDifficultyID()) ? 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()); @@ -5848,7 +5848,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) if (triggeredSpellInfo) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficultyID()) ? caster : target) { triggerCaster->CastSpell(target, triggeredSpellInfo, true, NULL, this); TC_LOG_DEBUG("spells", "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id); @@ -5868,7 +5868,7 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* uint32 triggerSpellId = GetSpellEffectInfo()->TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficulty()) ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, target->GetMap()->GetDifficultyID()) ? caster : target) { int32 basepoints = GetAmount(); triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints, &basepoints, &basepoints, true, nullptr, this); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 435c5097604..28c2927bd8b 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -251,14 +251,14 @@ uint32 Aura::BuildEffectMaskForOwner(SpellInfo const* spellProto, uint32 avalibl { case TYPEID_UNIT: case TYPEID_PLAYER: - for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficultyID())) { if (effect && effect->IsUnitOwnedAuraEffect()) effMask |= 1 << effect->EffectIndex; } break; case TYPEID_DYNAMICOBJECT: - for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellProto->GetEffectsForDifficulty(owner->GetMap()->GetDifficultyID())) { if (effect && effect->Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) effMask |= 1 << effect->EffectIndex; @@ -390,7 +390,7 @@ SpellEffectInfo const* Aura::GetSpellEffectInfo(uint32 index) const void Aura::_InitEffects(uint32 effMask, Unit* caster, int32 *baseAmount) { // shouldn't be in constructor - functions in AuraEffect::AuraEffect use polymorphism - _spelEffectInfos = m_spellInfo->GetEffectsForDifficulty(GetOwner()->GetMap()->GetDifficulty()); + _spelEffectInfos = m_spellInfo->GetEffectsForDifficulty(GetOwner()->GetMap()->GetDifficultyID()); ASSERT(!_spelEffectInfos.empty()); @@ -1053,7 +1053,7 @@ bool Aura::CanBeSaved() const bool Aura::CanBeSentToClient() const { - return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect(GetOwner() ? GetOwner()->GetMap()->GetDifficulty() : DIFFICULTY_NONE) || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING); + return !IsPassive() || GetSpellInfo()->HasAreaAuraEffect(GetOwner() ? GetOwner()->GetMap()->GetDifficultyID() : DIFFICULTY_NONE) || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE) || HasEffectType(SPELL_AURA_CAST_WHILE_WALKING); } bool Aura::IsSingleTargetWith(Aura const* aura) const @@ -1661,7 +1661,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(GetOwner()->GetMap()->GetDifficulty(), SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(GetOwner()->GetMap()->GetDifficulty(), SPELL_AURA_TRACK_RESOURCES)) + if (m_spellInfo->HasAura(GetOwner()->GetMap()->GetDifficultyID(), SPELL_AURA_TRACK_RESOURCES) && existingSpellInfo->HasAura(GetOwner()->GetMap()->GetDifficultyID(), SPELL_AURA_TRACK_RESOURCES)) return sWorld->getBoolConfig(CONFIG_ALLOW_TRACK_BOTH_RESOURCES); // check spell specific stack rules diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index df1d8239b04..f2793cd0933 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -578,9 +578,9 @@ SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto) Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) : m_spellInfo(info), m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster), -m_spellValue(new SpellValue(caster->GetMap()->GetDifficulty(), m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster)) +m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster)) { - _effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficulty()); + _effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID()); m_customError = SPELL_CUSTOM_ERROR_NONE; m_skipCheck = skipCheck; @@ -3818,7 +3818,7 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas case SPELL_FAILED_TOO_MANY_OF_ITEM: { uint32 item = 0; - for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID())) if (effect->ItemType) item = effect->ItemType; ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); @@ -5544,7 +5544,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (map->IsDungeon()) { uint32 mapId = m_caster->GetMap()->GetId(); - Difficulty difficulty = m_caster->GetMap()->GetDifficulty(); + Difficulty difficulty = m_caster->GetMap()->GetDifficultyID(); if (map->IsRaid()) if (InstancePlayerBind* targetBind = target->GetBoundInstance(mapId, difficulty)) if (InstancePlayerBind* casterBind = m_caster->ToPlayer()->GetBoundInstance(mapId, difficulty)) @@ -7484,7 +7484,7 @@ void Spell::PrepareTriggersExecutedOnHit() SpellInfo const* auraSpellInfo = (*i)->GetSpellInfo(); uint32 auraSpellIdx = (*i)->GetEffIndex(); // todo 6.x - if (SpellEffectInfo const* auraEffect = auraSpellInfo->GetEffect(m_caster->GetMap()->GetDifficulty(), auraSpellIdx)) + if (SpellEffectInfo const* auraEffect = auraSpellInfo->GetEffect(m_caster->GetMap()->GetDifficultyID(), auraSpellIdx)) { if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(auraEffect->TriggerSpell)) { diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 3817cfc9405..ceb16e30536 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -421,7 +421,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) { // Consumption case 28865: - damage = (((InstanceMap*)m_caster->GetMap())->GetDifficulty() == DIFFICULTY_NONE ? 2750 : 4250); + damage = (((InstanceMap*)m_caster->GetMap())->GetDifficultyID() == DIFFICULTY_NONE ? 2750 : 4250); break; // percent from health with min case 25599: // Thundercrash @@ -747,13 +747,13 @@ void Spell::EffectTriggerSpell(SpellEffIndex /*effIndex*/) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty())) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID())) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH) { - if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty()) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID()) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -802,13 +802,13 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex /*effIndex*/) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty())) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID())) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT) { - if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficulty()) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo, m_caster->GetMap()->GetDifficultyID()) && (effectInfo->GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -2213,7 +2213,7 @@ 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(effectInfo->CalcValue()); - if (spellInfo && spellInfo->HasAura(m_originalCaster->GetMap()->GetDifficulty(), SPELL_AURA_CONTROL_VEHICLE)) + if (spellInfo && spellInfo->HasAura(m_originalCaster->GetMap()->GetDifficultyID(), SPELL_AURA_CONTROL_VEHICLE)) spellId = spellInfo->Id; // Hard coded enter vehicle spell diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 9474abd6da1..1f6b5238137 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1739,7 +1739,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a // aura limitations if (player) { - for (SpellEffectInfo const* effect : GetEffectsForDifficulty(player->GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(player->GetMap()->GetDifficultyID())) { if (!effect || !effect->IsAura()) continue; @@ -1910,7 +1910,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta return SPELL_FAILED_TARGET_AURASTATE; if (unitTarget->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) - if (HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_SELF_RESURRECT) || HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_RESURRECT) || HasEffect(caster->GetMap()->GetDifficulty(), SPELL_EFFECT_RESURRECT_NEW)) + if (HasEffect(caster->GetMap()->GetDifficultyID(), SPELL_EFFECT_SELF_RESURRECT) || HasEffect(caster->GetMap()->GetDifficultyID(), SPELL_EFFECT_RESURRECT) || HasEffect(caster->GetMap()->GetDifficultyID(), SPELL_EFFECT_RESURRECT_NEW)) return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; return SPELL_CAST_OK; @@ -1961,7 +1961,7 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const if (vehicle) { uint16 checkMask = 0; - for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID())) { if (effect && effect->ApplyAuraName == SPELL_AURA_MOD_SHAPESHIFT) { @@ -1972,7 +1972,7 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const } } - if (HasAura(caster->GetMap()->GetDifficulty(), SPELL_AURA_MOUNTED)) + if (HasAura(caster->GetMap()->GetDifficultyID(), SPELL_AURA_MOUNTED)) checkMask |= VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL; if (!checkMask) @@ -1986,7 +1986,7 @@ 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 (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficulty())) + for (SpellEffectInfo const* effect : GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID())) { if (!effect || effect->Effect != SPELL_EFFECT_SUMMON) continue; @@ -3076,7 +3076,7 @@ SpellCooldownsEntry const* SpellInfo::GetSpellCooldowns() const void SpellInfo::_UnloadImplicitTargetConditionLists() { // find the same instances of ConditionList and delete them. - for (uint32 d = 0; d < DIFFICULTY_MAX; ++d) + for (uint32 d = 0; d < MAX_DIFFICULTY; ++d) { for (uint32 i = 0; i < _effects.size(); ++i) { diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index f2a671fc968..7e60e11448d 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -574,7 +574,7 @@ public: 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); } + SpellEffectInfo const* GetEffect(WorldObject* obj, uint32 index) const { return GetEffect(obj->GetMap()->GetDifficultyID(), index); } SpellEffectInfoMap _effects; }; |