From 50cc233244a7c53d1c0eefb14bc55b7ffe49b7b3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:32:24 +0000 Subject: [PATCH 1/8] Initial plan From f7596c65066d7d999f6f40662c5af8f34fba097e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:41:30 +0000 Subject: [PATCH 2/8] Perf/readability: header and handler improvements - IsInstanceMythic helper, fix double lookups, fix operator[] insertions, remove dead code Co-authored-by: Nyeriah <47818697+Nyeriah@users.noreply.github.com> --- src/ZoneDifficulty.h | 5 +- src/mod_zone_difficulty_handler.cpp | 142 +++++++++++++--------------- 2 files changed, 70 insertions(+), 77 deletions(-) diff --git a/src/ZoneDifficulty.h b/src/ZoneDifficulty.h index d57d772a..55336a25 100644 --- a/src/ZoneDifficulty.h +++ b/src/ZoneDifficulty.h @@ -175,14 +175,15 @@ class ZoneDifficulty void MythicmodeEvent(Unit* unit, uint32 entry, uint32 key); bool HasNormalMode(int8 mode) { return (mode & MODE_NORMAL) == MODE_NORMAL; } bool HasMythicmode(int8 mode) { return (mode & MODE_HARD) == MODE_HARD; } + [[nodiscard]] bool IsInstanceMythic(uint32 instanceId) const; bool HasCompletedFullTier(uint32 category, uint32 playerGUID); bool OverrideModeMatches(uint32 instanceId, uint32 spellId, uint32 mapId); [[nodiscard]] bool CheckCompletionStatus(Creature* creature, Player* player, uint32 category) const; [[nodiscard]] bool IsValidNerfTarget(Unit* target); - [[nodiscard]] bool VectorContainsUint32(std::vector vec, uint32 element); + [[nodiscard]] bool VectorContainsUint32(const std::vector& vec, uint32 element); [[nodiscard]] bool IsMythicmodeMap(uint32 mapid); [[nodiscard]] bool ShouldNerfInDuels(Unit* target); - [[nodiscard]] bool ShouldNerfMap(uint32 mapId) { return NerfInfo.find(mapId) != NerfInfo.end(); }; + [[nodiscard]] bool ShouldNerfMap(uint32 mapId) { return NerfInfo.count(mapId) > 0; }; [[nodiscard]] int32 GetLowestMatchingPhase(uint32 mapId, uint32 phaseMask); void RewardItem(Player* player, uint8 category, uint8 itemType, uint8 counter, Creature* creature, uint32 itemEntry); void LogAndAnnounceKill(Map* map, bool isMythic); diff --git a/src/mod_zone_difficulty_handler.cpp b/src/mod_zone_difficulty_handler.cpp index c6ded0c4..fec765e9 100644 --- a/src/mod_zone_difficulty_handler.cpp +++ b/src/mod_zone_difficulty_handler.cpp @@ -26,6 +26,12 @@ ZoneDifficulty* ZoneDifficulty::instance() return &instance; } +bool ZoneDifficulty::IsInstanceMythic(uint32 instanceId) const +{ + auto it = MythicmodeInstanceData.find(instanceId); + return it != MythicmodeInstanceData.end() && it->second; +} + void ZoneDifficulty::LoadMapDifficultySettings() { if (!sZoneDifficulty->IsEnabled) @@ -167,12 +173,15 @@ void ZoneDifficulty::LoadMapDifficultySettings() { do { - if ((*result)[3].Get() > 0) + uint8 enabled = (*result)[3].Get(); + if (enabled > 0) { - sZoneDifficulty->SpellNerfOverrides[(*result)[0].Get()][(*result)[1].Get()].NerfPct = (*result)[2].Get(); - sZoneDifficulty->SpellNerfOverrides[(*result)[0].Get()][(*result)[1].Get()].ModeMask = (*result)[3].Get(); + uint32 spellId = (*result)[0].Get(); + uint32 mapId = (*result)[1].Get(); + auto& entry = sZoneDifficulty->SpellNerfOverrides[spellId][mapId]; + entry.NerfPct = (*result)[2].Get(); + entry.ModeMask = (*result)[3].Get(); } - } while (result->NextRow()); } @@ -215,7 +224,6 @@ void ZoneDifficulty::LoadMapDifficultySettings() data.RewardType = (*result)[3].Get(); sZoneDifficulty->MythicmodeLoot[MapID].push_back(data); - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: New creature for map {} with entry: {}", MapID, data.EncounterEntry); Expansion[MapID] = data.RewardType; @@ -231,7 +239,6 @@ void ZoneDifficulty::LoadMapDifficultySettings() do { sZoneDifficulty->DailyHeroicQuests.push_back((*result)[0].Get()); - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Adding daily heroic quest with id {}.", (*result)[0].Get()); } while (result->NextRow()); } else @@ -258,7 +265,6 @@ void ZoneDifficulty::LoadMapDifficultySettings() data.NormalOverride = hpModifierNormal; sZoneDifficulty->CreatureOverrides[creatureEntry] = data; - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: New creature with entry: {} has exception for hp: {}", creatureEntry, hpModifier); } } while (result->NextRow()); } @@ -299,7 +305,6 @@ void ZoneDifficulty::LoadMapDifficultySettings() { LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Unknown type for `Target`: {} in zone_difficulty_mythicmode_ai", data.Target); } - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: New creature with entry: {} has exception for hp: {}", creatureEntry, hpModifier); } } while (result->NextRow()); } @@ -308,19 +313,10 @@ void ZoneDifficulty::LoadMapDifficultySettings() LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Query failed: SELECT * FROM zone_difficulty_mythicmode_ai"); } - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Starting load of rewards."); if (QueryResult result = WorldDatabase.Query("SELECT ContentType, ItemType, Entry, Price, Enchant, EnchantSlot, Achievement, Enabled FROM zone_difficulty_mythicmode_rewards")) { - /* debug - * uint32 i = 0; - * end debug - */ do { - /* debug - * ++i; - * end debug - */ ZoneDifficultyRewardData data; uint32 contentType = (*result)[0].Get(); uint32 itemType = (*result)[1].Get(); @@ -334,17 +330,10 @@ void ZoneDifficulty::LoadMapDifficultySettings() if (enabled) { if (data.Achievement >= 0) - { sZoneDifficulty->Rewards[contentType][itemType].push_back(data); - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Loading item with entry {} has enchant {} in slot {}. contentType: {} itemType: {}", data.Entry, data.Enchant, data.EnchantSlot, contentType, itemType); - } else - { sZoneDifficulty->TierRewards[contentType] = data; - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Loading tier reward with entry {} has enchant {} in slot {}. contentType: {} itemType: {}", data.Entry, data.Enchant, data.EnchantSlot, contentType, itemType); - } } - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Total items in Rewards map: {}.", i); } while (result->NextRow()); } else @@ -365,13 +354,6 @@ void ZoneDifficulty::LoadMapDifficultySettings() void ZoneDifficulty::LoadMythicmodeInstanceData() { std::vector instanceIDs = sMapMgr->GetInstanceIDs(); - /* debugging - * for (int i = 0; i < int(instanceIDs.size()); i++) - * { - * LOG_INFO("module", "MOD-ZONE-DIFFICULTY: ZoneDifficulty::LoadMythicmodeInstanceData: id {} exists: {}:", i, instanceIDs[i]); - * } - * end debugging - */ if (QueryResult result = CharacterDatabase.Query("SELECT * FROM zone_difficulty_instance_saves")) { do @@ -388,8 +370,6 @@ void ZoneDifficulty::LoadMythicmodeInstanceData() { CharacterDatabase.Execute("DELETE FROM zone_difficulty_instance_saves WHERE InstanceID = {}", InstanceId); } - - } while (result->NextRow()); } } @@ -422,9 +402,7 @@ void ZoneDifficulty::LoadMythicmodeScoreData() uint8 Type = (*result)[1].Get(); uint32 Score = (*result)[2].Get(); - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Loading from DB for player with GUID {}: Type = {}, Score = {}", GUID, Type, Score); sZoneDifficulty->MythicmodeScore[GUID][Type] = Score; - } while (result->NextRow()); } @@ -436,13 +414,17 @@ void ZoneDifficulty::LoadMythicmodeScoreData() uint8 BossID = (*result)[1].Get(); uint32 PlayerGuid = (*result)[2].Get(); - // Set all BossID which aren't true to false for that mapID - if (sZoneDifficulty->Logs[PlayerGuid].find(MapId) == sZoneDifficulty->Logs[PlayerGuid].end()) + auto& playerLogs = sZoneDifficulty->Logs[PlayerGuid]; + if (playerLogs.find(MapId) == playerLogs.end()) { - for (int i = 0; i < sZoneDifficulty->EncounterCounter[MapId]; ++i) - sZoneDifficulty->Logs[PlayerGuid][MapId][i] = false; + auto encounterIt = sZoneDifficulty->EncounterCounter.find(MapId); + if (encounterIt != sZoneDifficulty->EncounterCounter.end()) + { + for (int i = 0; i < encounterIt->second; ++i) + playerLogs[MapId][i] = false; + } } - sZoneDifficulty->Logs[PlayerGuid][MapId][BossID] = true; + playerLogs[MapId][BossID] = true; } while (result->NextRow()); } } @@ -661,10 +643,7 @@ bool ZoneDifficulty::IsMythicmodeMap(uint32 mapId) if (!sZoneDifficulty->MythicmodeEnable) return false; - if (sZoneDifficulty->MythicmodeLoot.find(mapId) == sZoneDifficulty->MythicmodeLoot.end()) - return false; - - return true; + return sZoneDifficulty->MythicmodeLoot.count(mapId) > 0; } /** @@ -685,7 +664,7 @@ bool ZoneDifficulty::IsValidNerfTarget(Unit* target) * @param element One element which can potentially be part of the values in the vector * @return The result as bool */ -bool ZoneDifficulty::VectorContainsUint32(std::vector vec, uint32 element) +bool ZoneDifficulty::VectorContainsUint32(const std::vector& vec, uint32 element) { return find(vec.begin(), vec.end(), element) != vec.end(); } @@ -700,15 +679,19 @@ bool ZoneDifficulty::VectorContainsUint32(std::vector vec, uint32 elemen */ bool ZoneDifficulty::OverrideModeMatches(uint32 instanceId, uint32 spellId, uint32 mapId) { - if ((sZoneDifficulty->HasMythicmode(sZoneDifficulty->SpellNerfOverrides[spellId][mapId].ModeMask) && sZoneDifficulty->MythicmodeInstanceData[instanceId]) || - (sZoneDifficulty->HasNormalMode(sZoneDifficulty->SpellNerfOverrides[spellId][mapId].ModeMask) && !sZoneDifficulty->MythicmodeInstanceData[instanceId])) - { - return true; - } - else - { + auto spellIt = sZoneDifficulty->SpellNerfOverrides.find(spellId); + if (spellIt == sZoneDifficulty->SpellNerfOverrides.end()) return false; - } + + auto mapIt = spellIt->second.find(mapId); + if (mapIt == spellIt->second.end()) + return false; + + uint32 modeMask = mapIt->second.ModeMask; + bool isMythic = sZoneDifficulty->IsInstanceMythic(instanceId); + + return (sZoneDifficulty->HasMythicmode(modeMask) && isMythic) || + (sZoneDifficulty->HasNormalMode(modeMask) && !isMythic); } /** @@ -754,24 +737,22 @@ bool ZoneDifficulty::ShouldNerfInDuels(Unit* target) */ int32 ZoneDifficulty::GetLowestMatchingPhase(uint32 mapId, uint32 phaseMask) { - // Check if there is an entry for the mapId at all - if (sZoneDifficulty->ShouldNerfMap(mapId)) - { + auto mapIt = sZoneDifficulty->NerfInfo.find(mapId); + if (mapIt == sZoneDifficulty->NerfInfo.end()) + return -1; - // Check if 0 is assigned as a phase to cover all phases - if (sZoneDifficulty->NerfInfo[mapId].find(0) != sZoneDifficulty->NerfInfo[mapId].end()) - { - return 0; - } + auto& phaseMap = mapIt->second; - for (auto const& [key, value] : sZoneDifficulty->NerfInfo[mapId]) - { - if (key & phaseMask) - { - return key; - } - } + // Check if 0 is assigned as a phase to cover all phases + if (phaseMap.count(0)) + return 0; + + for (auto const& [key, value] : phaseMap) + { + if (key & phaseMask) + return key; } + return -1; } @@ -783,11 +764,11 @@ int32 ZoneDifficulty::GetLowestMatchingPhase(uint32 mapId, uint32 phaseMask) */ void ZoneDifficulty::SaveMythicmodeInstanceData(uint32 instanceId) { - if (sZoneDifficulty->MythicmodeInstanceData.find(instanceId) == sZoneDifficulty->MythicmodeInstanceData.end()) - { + auto it = sZoneDifficulty->MythicmodeInstanceData.find(instanceId); + if (it == sZoneDifficulty->MythicmodeInstanceData.end()) return; - } - CharacterDatabase.Execute("REPLACE INTO zone_difficulty_instance_saves (InstanceID, MythicmodeOn) VALUES ({}, {})", instanceId, sZoneDifficulty->MythicmodeInstanceData[instanceId]); + + CharacterDatabase.Execute("REPLACE INTO zone_difficulty_instance_saves (InstanceID, MythicmodeOn) VALUES ({}, {})", instanceId, it->second); } void ZoneDifficulty::MythicmodeEvent(Unit* unit, uint32 entry, uint32 key) @@ -976,14 +957,25 @@ bool ZoneDifficulty::HasCompletedFullTier(uint32 category, uint32 playerGuid) for (uint32 mapId : MapList) { - if (sZoneDifficulty->EncounterCounter.find(mapId) == sZoneDifficulty->EncounterCounter.end()) + auto encounterIt = sZoneDifficulty->EncounterCounter.find(mapId); + if (encounterIt == sZoneDifficulty->EncounterCounter.end()) { LOG_ERROR("module", "MOD-ZONE-DIFFICULTY: Map without data requested in ZoneDifficulty::HasCompletedFullTier {}", mapId); return false; } - for (uint8 i = 0; i < sZoneDifficulty->EncounterCounter[mapId]; ++i) + + auto playerLogIt = sZoneDifficulty->Logs.find(playerGuid); + if (playerLogIt == sZoneDifficulty->Logs.end()) + return false; + + auto mapLogIt = playerLogIt->second.find(mapId); + if (mapLogIt == playerLogIt->second.end()) + return false; + + for (uint8 i = 0; i < encounterIt->second; ++i) { - if (!sZoneDifficulty->Logs[playerGuid][mapId][i]) + auto bossIt = mapLogIt->second.find(i); + if (bossIt == mapLogIt->second.end() || !bossIt->second) return false; } } From 1ff8eec1cf7b8e9bcb9f004e9ef77399add1929c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:47:22 +0000 Subject: [PATCH 3/8] Perf/readability: scripts improvements - IsInstanceMythic, early returns in OnAllCreatureUpdate, fix double lookups, remove dead code Co-authored-by: Nyeriah <47818697+Nyeriah@users.noreply.github.com> --- src/mod_zone_difficulty_scripts.cpp | 429 ++++++++++++---------------- 1 file changed, 182 insertions(+), 247 deletions(-) diff --git a/src/mod_zone_difficulty_scripts.cpp b/src/mod_zone_difficulty_scripts.cpp index f711be9d..c415c5f1 100644 --- a/src/mod_zone_difficulty_scripts.cpp +++ b/src/mod_zone_difficulty_scripts.cpp @@ -64,7 +64,7 @@ class mod_zone_difficulty_unitscript : public UnitScript uint32 instanceId = target->GetMap()->GetInstanceId(); uint32 phaseMask = target->GetPhaseMask(); int phase = sZoneDifficulty->GetLowestMatchingPhase(mapId, phaseMask); - bool isMythic = sZoneDifficulty->MythicmodeInstanceData[instanceId]; + bool isMythic = sZoneDifficulty->IsInstanceMythic(instanceId); bool nerfInDuel = sZoneDifficulty->ShouldNerfInDuels(target); auto scaleAbsorb = [](int32 amount, float pct) -> int32 { @@ -128,73 +128,74 @@ class mod_zone_difficulty_unitscript : public UnitScript if (!sZoneDifficulty->MythicmodeInNormalDungeons && !target->GetMap()->IsRaidOrHeroicDungeon()) return; - if (sZoneDifficulty->IsValidNerfTarget(target)) + if (!sZoneDifficulty->IsValidNerfTarget(target)) + return; + + if (spellInfo) { - if (spellInfo) + if (spellInfo->HasEffect(SPELL_EFFECT_HEALTH_LEECH)) + return; + + for (auto const& eff : spellInfo->GetEffects()) { - if (spellInfo->HasEffect(SPELL_EFFECT_HEALTH_LEECH)) + if (eff.ApplyAuraName == SPELL_AURA_PERIODIC_LEECH) return; + } - for (auto const& eff : spellInfo->GetEffects()) - { - if (eff.ApplyAuraName == SPELL_AURA_PERIODIC_LEECH) - return; - } + // Skip spells not affected by vulnerability (potions) and bandages + if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || spellInfo->Mechanic == MECHANIC_BANDAGE) + return; + } - // Skip spells not affected by vulnerability (potions) and bandages - if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || spellInfo->Mechanic == MECHANIC_BANDAGE) - return; - } + uint32 mapId = target->GetMapId(); + bool nerfInDuel = sZoneDifficulty->ShouldNerfInDuels(target); - uint32 mapId = target->GetMapId(); - bool nerfInDuel = sZoneDifficulty->ShouldNerfInDuels(target); - //Check if the map of the target is subject of a nerf at all OR if the target is subject of a nerf in a duel - if (sZoneDifficulty->ShouldNerfMap(mapId) || sZoneDifficulty->ShouldNerfInDuels(target)) + if (!sZoneDifficulty->ShouldNerfMap(mapId) && !nerfInDuel) + return; + + // Spell-specific override check - must be first to override everything else. + if (spellInfo) + { + auto spellIt = sZoneDifficulty->SpellNerfOverrides.find(spellInfo->Id); + if (spellIt != sZoneDifficulty->SpellNerfOverrides.end()) { - //This check must be first and skip the rest to override everything else. - if (spellInfo) + uint32 instanceId = target->GetMap()->GetInstanceId(); + auto& overrideMap = spellIt->second; + + auto mapIt = overrideMap.find(mapId); + if (mapIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) { - if (sZoneDifficulty->SpellNerfOverrides.find(spellInfo->Id) != sZoneDifficulty->SpellNerfOverrides.end()) - { - if (sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].find(mapId) != sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].end()) - { - if (sZoneDifficulty->OverrideModeMatches(target->GetMap()->GetInstanceId(), spellInfo->Id, mapId)) - { - heal = heal * sZoneDifficulty->SpellNerfOverrides[spellInfo->Id][mapId].NerfPct; - return; - } - } - if (sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].find(0) != sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].end()) - { - if (sZoneDifficulty->OverrideModeMatches(target->GetMap()->GetInstanceId(), spellInfo->Id, mapId)) - { - heal = heal * sZoneDifficulty->SpellNerfOverrides[spellInfo->Id][0].NerfPct; - return; - } - } - } + heal = heal * mapIt->second.NerfPct; + return; } - uint32 phaseMask = target->GetPhaseMask(); - int matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(mapId, phaseMask); - int8 mode = sZoneDifficulty->NerfInfo[mapId][matchingPhase].Enabled; - if (matchingPhase != -1) + auto globalIt = overrideMap.find(0); + if (globalIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) { - Map* map = target->GetMap(); - uint32 instanceId = map->GetInstanceId(); - bool isMythicMode = sZoneDifficulty->MythicmodeInstanceData[instanceId]; - - if (!isMythicMode && sZoneDifficulty->HasNormalMode(mode)) - heal = heal * sZoneDifficulty->NerfInfo[mapId][matchingPhase].HealingNerfPct; - - if (isMythicMode && sZoneDifficulty->HasMythicmode(mode)) - if (map->IsRaid() || (map->IsHeroic() && map->IsDungeon())) - heal = heal * sZoneDifficulty->NerfInfo[mapId][matchingPhase].HealingNerfPctHard; + heal = heal * globalIt->second.NerfPct; + return; } - else if (sZoneDifficulty->NerfInfo[DUEL_INDEX][0].Enabled > 0 && nerfInDuel) - heal = heal * sZoneDifficulty->NerfInfo[DUEL_INDEX][0].HealingNerfPct; } } + + int matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(mapId, target->GetPhaseMask()); + if (matchingPhase != -1) + { + auto const& nerfData = sZoneDifficulty->NerfInfo[mapId][matchingPhase]; + Map* map = target->GetMap(); + bool isMythicMode = sZoneDifficulty->IsInstanceMythic(map->GetInstanceId()); + + if (!isMythicMode && sZoneDifficulty->HasNormalMode(nerfData.Enabled)) + heal = heal * nerfData.HealingNerfPct; + + if (isMythicMode && sZoneDifficulty->HasMythicmode(nerfData.Enabled)) + if (map->IsRaid() || (map->IsHeroic() && map->IsDungeon())) + heal = heal * nerfData.HealingNerfPctHard; + } + else if (nerfInDuel && sZoneDifficulty->NerfInfo[DUEL_INDEX][0].Enabled > 0) + { + heal = heal * sZoneDifficulty->NerfInfo[DUEL_INDEX][0].HealingNerfPct; + } } void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* spellInfo) override @@ -236,17 +237,16 @@ class mod_zone_difficulty_unitscript : public UnitScript if (sZoneDifficulty->ShouldNerfMap(mapId) && matchingPhase != -1) { - int8 mode = sZoneDifficulty->NerfInfo[mapId][matchingPhase].Enabled; + auto const& nerfData = sZoneDifficulty->NerfInfo[mapId][matchingPhase]; Map* map = target->GetMap(); - uint32 instanceId = map->GetInstanceId(); - bool isMythicMode = sZoneDifficulty->MythicmodeInstanceData[instanceId]; + bool isMythicMode = sZoneDifficulty->IsInstanceMythic(map->GetInstanceId()); - if (!isMythicMode && sZoneDifficulty->HasNormalMode(mode)) - damage = damage * sZoneDifficulty->NerfInfo[mapId][matchingPhase].SpellDamageBuffPct; + if (!isMythicMode && sZoneDifficulty->HasNormalMode(nerfData.Enabled)) + damage = damage * nerfData.SpellDamageBuffPct; - if (isMythicMode && sZoneDifficulty->HasMythicmode(mode)) + if (isMythicMode && sZoneDifficulty->HasMythicmode(nerfData.Enabled)) if (map->IsRaid() || (map->IsHeroic() && map->IsDungeon())) - damage = damage * sZoneDifficulty->NerfInfo[mapId][matchingPhase].SpellDamageBuffPctHard; + damage = damage * nerfData.SpellDamageBuffPctHard; } else if (sZoneDifficulty->ShouldNerfInDuels(target)) if (sZoneDifficulty->NerfInfo[DUEL_INDEX][0].Enabled > 0) @@ -274,34 +274,35 @@ class mod_zone_difficulty_unitscript : public UnitScript if (sZoneDifficulty->IsValidNerfTarget(target)) { uint32 mapId = target->GetMapId(); - uint32 phaseMask = target->GetPhaseMask(); - int32 matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(mapId, phaseMask); + int32 matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(mapId, target->GetPhaseMask()); + + // Spell-specific override check - must be first to override everything else. if (spellInfo) { - //This check must be first and skip the rest to override everything else. - if (sZoneDifficulty->SpellNerfOverrides.find(spellInfo->Id) != sZoneDifficulty->SpellNerfOverrides.end()) + auto spellIt = sZoneDifficulty->SpellNerfOverrides.find(spellInfo->Id); + if (spellIt != sZoneDifficulty->SpellNerfOverrides.end()) { - if (sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].find(mapId) != sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].end()) + uint32 instanceId = target->GetMap()->GetInstanceId(); + auto& overrideMap = spellIt->second; + + auto mapIt = overrideMap.find(mapId); + if (mapIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) { - if (sZoneDifficulty->OverrideModeMatches(target->GetMap()->GetInstanceId(), spellInfo->Id, mapId)) - { - damage = damage * sZoneDifficulty->SpellNerfOverrides[spellInfo->Id][mapId].NerfPct; - return; - } + damage = damage * mapIt->second.NerfPct; + return; } - else if (sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].find(0) != sZoneDifficulty->SpellNerfOverrides[spellInfo->Id].end()) + + auto globalIt = overrideMap.find(0); + if (globalIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) { - if (sZoneDifficulty->OverrideModeMatches(target->GetMap()->GetInstanceId(), spellInfo->Id, mapId)) - { - damage = damage * sZoneDifficulty->SpellNerfOverrides[spellInfo->Id][0].NerfPct; - return; - } + damage = damage * globalIt->second.NerfPct; + return; } } if (sZoneDifficulty->IsDebugInfoEnabled && target) { - if (Player* player = target->ToPlayer()) // Pointless check? Perhaps. + if (Player* player = target->ToPlayer()) { ChatHandler(player->GetSession()).PSendSysMessage("Spell: {} ({}) Before Nerf Value: {} ({} Normal Mode)", spellInfo->SpellName[player->GetSession()->GetSessionDbcLocale()], spellInfo->Id, damage, sZoneDifficulty->NerfInfo[mapId][matchingPhase].SpellDamageBuffPct); ChatHandler(player->GetSession()).PSendSysMessage("Spell: {} ({}) Before Nerf Value: {} ({} Mythic Mode)", spellInfo->SpellName[player->GetSession()->GetSessionDbcLocale()], spellInfo->Id, damage, sZoneDifficulty->NerfInfo[mapId][matchingPhase].SpellDamageBuffPctHard); @@ -311,24 +312,23 @@ class mod_zone_difficulty_unitscript : public UnitScript if (sZoneDifficulty->ShouldNerfMap(mapId) && matchingPhase != -1) { - int8 mode = sZoneDifficulty->NerfInfo[mapId][matchingPhase].Enabled; + auto const& nerfData = sZoneDifficulty->NerfInfo[mapId][matchingPhase]; Map* map = target->GetMap(); - uint32 instanceId = map->GetInstanceId(); - bool isMythicMode = sZoneDifficulty->MythicmodeInstanceData[instanceId]; + bool isMythicMode = sZoneDifficulty->IsInstanceMythic(map->GetInstanceId()); - if (!isMythicMode && sZoneDifficulty->HasNormalMode(mode)) - damage = damage * sZoneDifficulty->NerfInfo[mapId][matchingPhase].SpellDamageBuffPct; + if (!isMythicMode && sZoneDifficulty->HasNormalMode(nerfData.Enabled)) + damage = damage * nerfData.SpellDamageBuffPct; - if (isMythicMode && sZoneDifficulty->HasMythicmode(mode)) + if (isMythicMode && sZoneDifficulty->HasMythicmode(nerfData.Enabled)) if (map->IsRaid() || (map->IsHeroic() && map->IsDungeon())) - damage = damage * sZoneDifficulty->NerfInfo[mapId][matchingPhase].SpellDamageBuffPctHard; + damage = damage * nerfData.SpellDamageBuffPctHard; } else if (sZoneDifficulty->ShouldNerfInDuels(target)) if (sZoneDifficulty->NerfInfo[DUEL_INDEX][0].Enabled > 0) damage = damage * sZoneDifficulty->NerfInfo[DUEL_INDEX][0].SpellDamageBuffPct; if (sZoneDifficulty->IsDebugInfoEnabled && target) - if (Player* player = target->ToPlayer()) // Pointless check? Perhaps. + if (Player* player = target->ToPlayer()) ChatHandler(player->GetSession()).PSendSysMessage("Spell: {} ({}) Post Nerf Value: {}", spellInfo->SpellName[player->GetSession()->GetSessionDbcLocale()], spellInfo->Id, damage); } } @@ -349,21 +349,19 @@ class mod_zone_difficulty_unitscript : public UnitScript if (sZoneDifficulty->IsValidNerfTarget(target)) { uint32 mapId = target->GetMapId(); - uint32 phaseMask = target->GetPhaseMask(); - int matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(mapId, phaseMask); + int matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(mapId, target->GetPhaseMask()); if (sZoneDifficulty->ShouldNerfMap(mapId) && matchingPhase != -1) { - int8 mode = sZoneDifficulty->NerfInfo[mapId][matchingPhase].Enabled; + auto const& nerfData = sZoneDifficulty->NerfInfo[mapId][matchingPhase]; Map* map = target->GetMap(); - uint32 instanceId = map->GetInstanceId(); - bool isMythicMode = sZoneDifficulty->MythicmodeInstanceData[instanceId]; + bool isMythicMode = sZoneDifficulty->IsInstanceMythic(map->GetInstanceId()); - if (!isMythicMode && sZoneDifficulty->HasNormalMode(mode)) - damage = damage * sZoneDifficulty->NerfInfo[mapId][matchingPhase].MeleeDamageBuffPct; + if (!isMythicMode && sZoneDifficulty->HasNormalMode(nerfData.Enabled)) + damage = damage * nerfData.MeleeDamageBuffPct; - if (isMythicMode && sZoneDifficulty->HasMythicmode(mode)) + if (isMythicMode && sZoneDifficulty->HasMythicmode(nerfData.Enabled)) if (map->IsRaid() || (map->IsHeroic() && map->IsDungeon())) - damage = damage * sZoneDifficulty->NerfInfo[mapId][matchingPhase].MeleeDamageBuffPctHard; + damage = damage * nerfData.MeleeDamageBuffPctHard; } else if (sZoneDifficulty->ShouldNerfInDuels(target)) if (sZoneDifficulty->NerfInfo[DUEL_INDEX][0].Enabled > 0) @@ -376,10 +374,7 @@ class mod_zone_difficulty_unitscript : public UnitScript */ void OnUnitEnterCombat(Unit* unit, Unit* /*victim*/) override { - if (sZoneDifficulty->MythicmodeInstanceData.find(unit->GetInstanceId()) == sZoneDifficulty->MythicmodeInstanceData.end()) - return; - - if (!sZoneDifficulty->MythicmodeInstanceData[unit->GetInstanceId()]) + if (!sZoneDifficulty->IsInstanceMythic(unit->GetInstanceId())) return; if (Creature* creature = unit->ToCreature()) @@ -387,13 +382,14 @@ class mod_zone_difficulty_unitscript : public UnitScript return; uint32 entry = unit->GetEntry(); - if (sZoneDifficulty->MythicmodeAI.find(entry) == sZoneDifficulty->MythicmodeAI.end()) + auto aiIt = sZoneDifficulty->MythicmodeAI.find(entry); + if (aiIt == sZoneDifficulty->MythicmodeAI.end()) return; unit->m_Events.CancelEventGroup(EVENT_GROUP); uint32 i = 0; - for (ZoneDifficultyHAI& data : sZoneDifficulty->MythicmodeAI[entry]) + for (ZoneDifficultyHAI& data : aiIt->second) { if (data.Chance == 100 || data.Chance >= urand(1, 100)) { @@ -417,14 +413,14 @@ class mod_zone_difficulty_petscript : public PetScript void OnPetAddToWorld(Pet* pet) override { uint32 mapId = pet->GetMapId(); - if (sZoneDifficulty->DisallowedBuffs.find(mapId) != sZoneDifficulty->DisallowedBuffs.end()) + auto buffIt = sZoneDifficulty->DisallowedBuffs.find(mapId); + if (buffIt != sZoneDifficulty->DisallowedBuffs.end()) { - pet->m_Events.AddEventAtOffset([mapId, pet]() + auto debuffs = buffIt->second; + pet->m_Events.AddEventAtOffset([debuffs, pet]() { - for (uint32 aura : sZoneDifficulty->DisallowedBuffs[mapId]) - { + for (uint32 aura : debuffs) pet->RemoveAurasDueToSpell(aura); - } }, 2s); } } @@ -476,27 +472,22 @@ class mod_zone_difficulty_globalscript : public GlobalScript if (!sZoneDifficulty->MythicmodeEnable) return; - if (sZoneDifficulty->IsDebugInfoEnabled) - { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnBeforeSetBossState: bossId = {}, newState = {}, oldState = {}, MapId = {}, InstanceId = {}", id, newState, oldState, instance->GetId(), instance->GetInstanceId()); - } - uint32 instanceId = instance->GetInstanceId(); if (!sZoneDifficulty->IsMythicmodeMap(instance->GetId()) || (!sZoneDifficulty->MythicmodeInNormalDungeons && !instance->IsRaidOrHeroicDungeon())) - { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnBeforeSetBossState: Instance not handled because there is no Mythicmode loot data for map id: {}", instance->GetId()); return; - } + + bool isMythic = sZoneDifficulty->IsInstanceMythic(instanceId); + if (oldState != IN_PROGRESS && newState == IN_PROGRESS) { - if (sZoneDifficulty->MythicmodeInstanceData[instanceId]) + if (isMythic) sZoneDifficulty->EncountersInProgress[instanceId] = GameTime::GetGameTime().count(); } else if (oldState == IN_PROGRESS && newState == DONE) { - if (sZoneDifficulty->MythicmodeInstanceData[instanceId]) + if (isMythic) { if ((id == 7 /* Illidari Council*/ || id == 5 /* Reliquary of Souls*/) && instance->GetId() == 564) sZoneDifficulty->AddMythicmodeScore(instance, TYPE_RAID_T6, 1); @@ -504,14 +495,14 @@ class mod_zone_difficulty_globalscript : public GlobalScript if ((id == 0 /* Kalecgos */ || id == 4 /* Twins*/) && instance->GetId() == 580) sZoneDifficulty->AddMythicmodeScore(instance, TYPE_RAID_SWP, 1); - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Mythicmode is on."); - if (sZoneDifficulty->EncountersInProgress.find(instanceId) != sZoneDifficulty->EncountersInProgress.end() && sZoneDifficulty->EncountersInProgress[instanceId] != 0) + auto encounterIt = sZoneDifficulty->EncountersInProgress.find(instanceId); + if (encounterIt != sZoneDifficulty->EncountersInProgress.end() && encounterIt->second != 0) { instance->DoForAllPlayers([&](Player* player) { if (!player->IsGameMaster() && !player->IsDeveloper()) CharacterDatabase.Execute("REPLACE INTO `zone_difficulty_encounter_logs` VALUES({}, {}, {}, {}, {}, {}, {})", - instanceId, sZoneDifficulty->EncountersInProgress[instanceId], GameTime::GetGameTime().count(), instance->GetId(), id, player->GetGUID().GetCounter(), 64); + instanceId, encounterIt->second, GameTime::GetGameTime().count(), instance->GetId(), id, player->GetGUID().GetCounter(), 64); }); } } @@ -520,75 +511,54 @@ class mod_zone_difficulty_globalscript : public GlobalScript void OnInstanceIdRemoved(uint32 instanceId) override { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnInstanceIdRemoved: instanceId = {}", instanceId); - if (sZoneDifficulty->MythicmodeInstanceData.find(instanceId) != sZoneDifficulty->MythicmodeInstanceData.end()) - { - sZoneDifficulty->MythicmodeInstanceData.erase(instanceId); - } - + sZoneDifficulty->MythicmodeInstanceData.erase(instanceId); CharacterDatabase.Execute("DELETE FROM zone_difficulty_instance_saves WHERE InstanceID = {};", instanceId); } void OnAfterUpdateEncounterState(Map* map, EncounterCreditType /*type*/, uint32 /*creditEntry*/, Unit* source, Difficulty /*difficulty_fixed*/, DungeonEncounterList const* /*encounters*/, uint32 /*dungeonCompleted*/, bool /*updated*/) override { if (!sZoneDifficulty->MythicmodeEnable) - { return; - } + if (!source) - { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: source is a nullptr in OnAfterUpdateEncounterState"); return; - } - if (sZoneDifficulty->MythicmodeInstanceData.find(map->GetInstanceId()) != sZoneDifficulty->MythicmodeInstanceData.end()) + if (!sZoneDifficulty->IsInstanceMythic(map->GetInstanceId())) + return; + + uint32 mapId = map->GetId(); + if (!sZoneDifficulty->IsMythicmodeMap(mapId) || + (!sZoneDifficulty->MythicmodeInNormalDungeons && !map->IsRaidOrHeroicDungeon())) + return; + + uint32 score = 0; + bool sourceAwardsMythicmodeLoot = false; + auto lootIt = sZoneDifficulty->MythicmodeLoot.find(mapId); + if (lootIt != sZoneDifficulty->MythicmodeLoot.end()) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Encounter completed. Map relevant. Checking for source: {}", source->GetEntry()); - // Give additional loot, if the encounter was in Mythicmode. - if (sZoneDifficulty->MythicmodeInstanceData[map->GetInstanceId()]) + for (auto const& value : lootIt->second) { - uint32 mapId = map->GetId(); - uint32 score = 0; - if (!sZoneDifficulty->IsMythicmodeMap(mapId) || - (!sZoneDifficulty->MythicmodeInNormalDungeons && !map->IsRaidOrHeroicDungeon())) - { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: No additional loot stored in map with id {}.", map->GetInstanceId()); - return; - } - - bool SourceAwardsMythicmodeLoot = false; - //iterate over all listed creature entries for that map id and see, if the encounter should yield Mythicmode loot and if there is an override to the default behaviour - for (auto value : sZoneDifficulty->MythicmodeLoot[mapId]) + if (value.EncounterEntry == source->GetEntry()) { - if (value.EncounterEntry == source->GetEntry()) - { - SourceAwardsMythicmodeLoot = true; - if (!(value.Override & 1)) - score = 1; - - break; - } + sourceAwardsMythicmodeLoot = true; + if (!(value.Override & 1)) + score = 1; + break; } + } + } - if (!SourceAwardsMythicmodeLoot) - return; + if (!sourceAwardsMythicmodeLoot) + return; - if (map->IsHeroic() && map->IsNonRaidDungeon()) - { - sZoneDifficulty->AddMythicmodeScore(map, sZoneDifficulty->Expansion[mapId], score); - } - else if (map->IsRaid()) - { - sZoneDifficulty->AddMythicmodeScore(map, sZoneDifficulty->Expansion[mapId], score); - sZoneDifficulty->ProcessCreatureDeath(map, source->GetEntry()); - } - /* debug - * else - * { - * LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Map with id {} is not a raid or a dungeon. Mythicmode loot not granted.", map->GetInstanceId()); - * } - */ - } + if (map->IsHeroic() && map->IsNonRaidDungeon()) + { + sZoneDifficulty->AddMythicmodeScore(map, sZoneDifficulty->Expansion[mapId], score); + } + else if (map->IsRaid()) + { + sZoneDifficulty->AddMythicmodeScore(map, sZoneDifficulty->Expansion[mapId], score); + sZoneDifficulty->ProcessCreatureDeath(map, source->GetEntry()); } } }; @@ -600,20 +570,9 @@ class mod_zone_difficulty_rewardnpc : public CreatureScript bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override { - if (sZoneDifficulty->IsDebugInfoEnabled) - { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnGossipSelectRewardNpc action: {}", action); - } ClearGossipMenuFor(player); uint32 npcText = 0; - //Safety measure. There's a way for action 0 to happen even though it's not provided in the gossip menu. - if (action == 0) - { - CloseGossipMenuFor(player); - return true; - } - - if (action == 999998) + if (action == 0 || action == 999998) { CloseGossipMenuFor(player); return true; @@ -660,7 +619,6 @@ class mod_zone_difficulty_rewardnpc : public CreatureScript return true; } - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Sending full tier clearance reward for category {}", category); sZoneDifficulty->DeductMythicmodeScore(player, category, sZoneDifficulty->TierRewards[category].Price); sZoneDifficulty->SendItem(player, sZoneDifficulty->TierRewards[category]); @@ -736,7 +694,6 @@ class mod_zone_difficulty_rewardnpc : public CreatureScript ++category; counter = counter - 100; } - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Building gossip with category {} and counter {}", category, counter); if (sZoneDifficulty->UseVendorInterface) { @@ -746,7 +703,6 @@ class mod_zone_difficulty_rewardnpc : public CreatureScript for (size_t i = 0; i < sZoneDifficulty->Rewards[category][counter].size(); ++i) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Adding gossip option for entry {}", sZoneDifficulty->Rewards[category][counter][i].Entry); ItemTemplate const* proto = sObjectMgr->GetItemTemplate(sZoneDifficulty->Rewards[category][counter][i].Entry); std::string name = proto->Name1; if (ItemLocale const* leftIl = sObjectMgr->GetItemLocale(sZoneDifficulty->Rewards[category][counter][i].Entry)) @@ -770,9 +726,6 @@ class mod_zone_difficulty_rewardnpc : public CreatureScript ++itemType; counter = counter - 100; } - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Handling item with category {}, itemType {}, counter {}", category, itemType, counter); - - // Check if the player has enough score in the respective category. if (!sZoneDifficulty->CheckCompletionStatus(creature, player, category)) { @@ -831,7 +784,6 @@ class mod_zone_difficulty_rewardnpc : public CreatureScript bool OnGossipHello(Player* player, Creature* creature) override { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnGossipHelloRewardNpc"); uint32 npcText = NPC_TEXT_OFFER; AddGossipItemFor(player, GOSSIP_ICON_CHAT, "|TInterface\\icons\\inv_misc_questionmark:15|t Can you please remind me of my score?", GOSSIP_SENDER_MAIN, 999999); @@ -962,12 +914,11 @@ class mod_zone_difficulty_dungeonmaster : public CreatureScript uint32 instanceId = player->GetMap()->GetInstanceId(); if (action == 100) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Try turn on"); bool canTurnOn = true; // Forbid turning Mythicmode on ... // ...if a single encounter was completed on normal mode - if (sZoneDifficulty->MythicmodeInstanceData.find(instanceId) != sZoneDifficulty->MythicmodeInstanceData.end()) + if (sZoneDifficulty->MythicmodeInstanceData.count(instanceId)) { if (player->GetInstanceScript()->GetBossState(0) == DONE) { @@ -988,7 +939,6 @@ class mod_zone_difficulty_dungeonmaster : public CreatureScript if (canTurnOn) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Turn on Mythicmode for id {}", instanceId); sZoneDifficulty->MythicmodeInstanceData[instanceId] = true; sZoneDifficulty->SaveMythicmodeInstanceData(instanceId); sZoneDifficulty->SendWhisperToRaid("We're switching to the challenging version of the history lesson now. (Mythic Mode)", creature, player); @@ -1000,13 +950,11 @@ class mod_zone_difficulty_dungeonmaster : public CreatureScript { if (player->GetInstanceScript()->IsEncounterInProgress()) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: IsEncounterInProgress"); creature->Whisper("I am sorry, time-traveler. You can not change the version of the time-line currently. There is already a battle in progress.", LANG_UNIVERSAL, player); CloseGossipMenuFor(player); } if (player->GetInstanceScript()->GetBossState(0) != DONE) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Turn off Mythicmode for id {}", instanceId); sZoneDifficulty->MythicmodeInstanceData[instanceId] = false; sZoneDifficulty->SaveMythicmodeInstanceData(instanceId); sZoneDifficulty->SendWhisperToRaid("We're switching to the cinematic version of the history lesson now. (Normal mode)", creature, player); @@ -1021,7 +969,6 @@ class mod_zone_difficulty_dungeonmaster : public CreatureScript } else if (action == 102) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: Turn off Mythicmode for id {}", instanceId); sZoneDifficulty->MythicmodeInstanceData[instanceId] = false; sZoneDifficulty->SaveMythicmodeInstanceData(instanceId); sZoneDifficulty->SendWhisperToRaid("We're switching to the cinematic version of the history lesson now. (Normal mode)", creature, player); @@ -1033,7 +980,6 @@ class mod_zone_difficulty_dungeonmaster : public CreatureScript bool OnGossipHello(Player* player, Creature* creature) override { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnGossipHelloChromie"); Group* group = player->GetGroup(); if (group && group->IsLfgRandomInstance() && !player->GetMap()->IsRaid()) { @@ -1046,14 +992,12 @@ class mod_zone_difficulty_dungeonmaster : public CreatureScript return true; } uint32 npcText = NPC_TEXT_OTHER; - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnGossipHello Has Group"); if (player->IsGameMaster() || (group && group->IsLeader(player->GetGUID()))) { - //LOG_INFO("module", "MOD-ZONE-DIFFICULTY: OnGossipHello Is Leader"); AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Please Chromie, let us re-experience how all the things really happened back then. (Mythic Mode)", GOSSIP_SENDER_MAIN, 100); AddGossipItemFor(player, GOSSIP_ICON_CHAT, "I think we will be fine with the cinematic version from here. (Normal mode)", GOSSIP_SENDER_MAIN, 101); - npcText = sZoneDifficulty->MythicmodeInstanceData[player->GetMap()->GetInstanceId()] ? + npcText = sZoneDifficulty->IsInstanceMythic(player->GetMap()->GetInstanceId()) ? NPC_TEXT_LEADER_HARD : NPC_TEXT_LEADER_NORMAL; } else @@ -1075,16 +1019,15 @@ class mod_zone_difficulty_allcreaturescript : public AllCreatureScript if (!sZoneDifficulty->MythicmodeEnable) return; - // Heavily inspired by https://github.com/azerothcore/mod-autobalance/blob/1d82080237e62376b9a030502264c90b5b8f272b/src/AutoBalance.cpp Map* map = creature->GetMap(); if (!creature || !map) return; - if (!map->IsRaid() && (!(map->IsHeroic() && map->IsDungeon()))) + if (!map->IsRaid() && !(map->IsHeroic() && map->IsDungeon())) return; uint32 mapId = creature->GetMapId(); - if (sZoneDifficulty->NerfInfo.find(mapId) == sZoneDifficulty->NerfInfo.end()) + if (!sZoneDifficulty->ShouldNerfMap(mapId)) return; if ((creature->IsHunterPet() || creature->IsPet() || creature->IsSummon()) && creature->IsControlledByPlayer()) @@ -1094,60 +1037,52 @@ class mod_zone_difficulty_allcreaturescript : public AllCreatureScript return; CreatureTemplate const* creatureTemplate = creature->GetCreatureTemplate(); - //skip critters and special creatures (spell summons etc.) in instances if (creatureTemplate->maxlevel <= 1) return; + // Check phase match early to skip unnecessary health computation + int matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(mapId, creature->GetPhaseMask()); + if (matchingPhase == -1) + return; + + bool isMythic = sZoneDifficulty->IsInstanceMythic(map->GetInstanceId()); + uint32 entry = creature->GetEntry(); + CreatureBaseStats const* origCreatureStats = sObjectMgr->GetCreatureBaseStats(creature->GetLevel(), creatureTemplate->unit_class); uint32 baseHealth = origCreatureStats->GenerateHealth(creatureTemplate); uint32 scaledBaseHealth = baseHealth; - uint32 entry = creature->GetEntry(); - - uint32 phaseMask = creature->GetPhaseMask(); - int matchingPhase = sZoneDifficulty->GetLowestMatchingPhase(creature->GetMapId(), phaseMask); - bool isMythic = sZoneDifficulty->MythicmodeInstanceData[creature->GetMap()->GetInstanceId()]; - if (sZoneDifficulty->CreatureOverrides.find(entry) == sZoneDifficulty->CreatureOverrides.end()) + auto overrideIt = sZoneDifficulty->CreatureOverrides.find(entry); + if (overrideIt == sZoneDifficulty->CreatureOverrides.end()) { - // TEMPORARY!!! It conflicts with CC normal mode tuning, dont apply trash tuning to hyjal and ssc - if (creature->GetMap()->GetId() == 534 || creature->GetMap()->GetId() == 548) + // TEMPORARY: conflicts with CC normal mode tuning for Hyjal and SSC + if (mapId == 534 || mapId == 548) return; - // Trash mobs. Apply generic tuning. if (!creature->IsDungeonBoss() && isMythic) scaledBaseHealth = round(baseHealth * sZoneDifficulty->MythicmodeHpModifier); } else { - float multiplier = isMythic ? sZoneDifficulty->CreatureOverrides[entry].MythicOverride - : sZoneDifficulty->CreatureOverrides[entry].NormalOverride; + float multiplier = isMythic ? overrideIt->second.MythicOverride + : overrideIt->second.NormalOverride; if (!multiplier) - multiplier = 1.0f; // never 0 + multiplier = 1.0f; scaledBaseHealth = round(baseHealth * multiplier); } - if (matchingPhase != -1) - { - float scaledHealth = scaledBaseHealth; - scaledHealth *= creature->GetPctModifierValue(UNIT_MOD_HEALTH, BASE_PCT); - scaledHealth += creature->GetFlatModifierValue(UNIT_MOD_HEALTH, TOTAL_VALUE); - scaledHealth *= creature->GetPctModifierValue(UNIT_MOD_HEALTH, TOTAL_PCT); - - if (creature->GetMaxHealth() == scaledHealth) - return; + // Quick check: skip if BASE_VALUE is already at the target value + if (creature->GetFlatModifierValue(UNIT_MOD_HEALTH, BASE_VALUE) == (float)scaledBaseHealth) + return; - float percent = creature->GetHealthPct(); - creature->SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)scaledBaseHealth); - creature->UpdateMaxHealth(); - if (creature->IsAlive()) - { - uint32 scaledCurHealth = creature->CountPctFromMaxHealth(percent); - creature->SetHealth(scaledCurHealth); - } - creature->ResetPlayerDamageReq(); - } + float percent = creature->GetHealthPct(); + creature->SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)scaledBaseHealth); + creature->UpdateMaxHealth(); + if (creature->IsAlive()) + creature->SetHealth(creature->CountPctFromMaxHealth(percent)); + creature->ResetPlayerDamageReq(); } }; @@ -1163,13 +1098,11 @@ class mod_zone_difficulty_playerscript : public PlayerScript void OnPlayerMapChanged(Player* player) override { - uint32 mapId = player->GetMapId(); - if (sZoneDifficulty->DisallowedBuffs.find(mapId) != sZoneDifficulty->DisallowedBuffs.end()) + auto buffIt = sZoneDifficulty->DisallowedBuffs.find(player->GetMapId()); + if (buffIt != sZoneDifficulty->DisallowedBuffs.end()) { - for (auto aura : sZoneDifficulty->DisallowedBuffs[mapId]) - { + for (uint32 aura : buffIt->second) player->RemoveAura(aura); - } } } @@ -1178,20 +1111,22 @@ class mod_zone_difficulty_playerscript : public PlayerScript if (sZoneDifficulty->MythicmodeScore.empty()) return; - if (sZoneDifficulty->MythicmodeScore.find(player->GetGUID().GetCounter()) != sZoneDifficulty->MythicmodeScore.end()) + uint32 guid = player->GetGUID().GetCounter(); + auto scoreIt = sZoneDifficulty->MythicmodeScore.find(guid); + if (scoreIt != sZoneDifficulty->MythicmodeScore.end()) { for (int i = 1; i <= 16; ++i) { uint32 availableScore = 0; - - if (sZoneDifficulty->MythicmodeScore[player->GetGUID().GetCounter()].find(i) != sZoneDifficulty->MythicmodeScore[player->GetGUID().GetCounter()].end()) - availableScore = sZoneDifficulty->MythicmodeScore[player->GetGUID().GetCounter()][i]; + auto typeIt = scoreIt->second.find(i); + if (typeIt != scoreIt->second.end()) + availableScore = typeIt->second; player->UpdatePlayerSetting(ModZoneDifficultyString + "score", i, availableScore); } - sZoneDifficulty->MythicmodeScore.erase(player->GetGUID().GetCounter()); - CharacterDatabase.Execute("DELETE FROM zone_difficulty_mythicmode_score WHERE GUID = {}", player->GetGUID().GetCounter()); + sZoneDifficulty->MythicmodeScore.erase(scoreIt); + CharacterDatabase.Execute("DELETE FROM zone_difficulty_mythicmode_score WHERE GUID = {}", guid); } } From 797a419ddbe4cf0bf803bc4fd50e039eecb8efdc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:49:16 +0000 Subject: [PATCH 4/8] Final review and security scan passed Co-authored-by: Nyeriah <47818697+Nyeriah@users.noreply.github.com> --- _codeql_detected_source_root | 1 + 1 file changed, 1 insertion(+) create mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file From fafd860f6aaa9c617749ede33ea7fa5fcd8b3069 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:49:42 +0000 Subject: [PATCH 5/8] Remove CodeQL artifact and update .gitignore Co-authored-by: Nyeriah <47818697+Nyeriah@users.noreply.github.com> --- .gitignore | 1 + _codeql_detected_source_root | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 120000 _codeql_detected_source_root diff --git a/.gitignore b/.gitignore index cc69717f..dc927cf4 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,4 @@ local.properties .project .cproject .idea +_codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root deleted file mode 120000 index 945c9b46..00000000 --- a/_codeql_detected_source_root +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file From 58ef91bec1bd5b12088e29a054d2abd0392cb5d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 14:05:46 +0000 Subject: [PATCH 6/8] Initial plan From 3017b34630a6c56e09fc2b2ae8cc6710e12a6427 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 14:08:42 +0000 Subject: [PATCH 7/8] Refactor OverrideModeMatches, fix global override, narrowing cast, and hoist loop-invariant lookup Co-authored-by: Nyeriah <47818697+Nyeriah@users.noreply.github.com> --- src/ZoneDifficulty.h | 2 +- src/mod_zone_difficulty_handler.cpp | 28 +++++++++------------------- src/mod_zone_difficulty_scripts.cpp | 23 ++++++++++++++--------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/ZoneDifficulty.h b/src/ZoneDifficulty.h index 55336a25..9c5368f3 100644 --- a/src/ZoneDifficulty.h +++ b/src/ZoneDifficulty.h @@ -177,7 +177,7 @@ class ZoneDifficulty bool HasMythicmode(int8 mode) { return (mode & MODE_HARD) == MODE_HARD; } [[nodiscard]] bool IsInstanceMythic(uint32 instanceId) const; bool HasCompletedFullTier(uint32 category, uint32 playerGUID); - bool OverrideModeMatches(uint32 instanceId, uint32 spellId, uint32 mapId); + bool OverrideModeMatches(uint32 instanceId, uint32 modeMask); [[nodiscard]] bool CheckCompletionStatus(Creature* creature, Player* player, uint32 category) const; [[nodiscard]] bool IsValidNerfTarget(Unit* target); [[nodiscard]] bool VectorContainsUint32(const std::vector& vec, uint32 element); diff --git a/src/mod_zone_difficulty_handler.cpp b/src/mod_zone_difficulty_handler.cpp index fec765e9..02266d4b 100644 --- a/src/mod_zone_difficulty_handler.cpp +++ b/src/mod_zone_difficulty_handler.cpp @@ -411,7 +411,7 @@ void ZoneDifficulty::LoadMythicmodeScoreData() do { uint32 MapId = (*result)[0].Get(); - uint8 BossID = (*result)[1].Get(); + uint8 BossID = static_cast((*result)[1].Get()); uint32 PlayerGuid = (*result)[2].Get(); auto& playerLogs = sZoneDifficulty->Logs[PlayerGuid]; @@ -670,24 +670,14 @@ bool ZoneDifficulty::VectorContainsUint32(const std::vector& vec, uint32 } /** - * @brief Checks if the instance and spelloverride have matching modes + * @brief Checks if the instance mode matches the override's mode mask * - * @param instanceId - * @param spellId - * @param mapId + * @param instanceId The instance ID to check mythic status + * @param modeMask The mode bitmask from the override entry * @return The result as bool */ - bool ZoneDifficulty::OverrideModeMatches(uint32 instanceId, uint32 spellId, uint32 mapId) + bool ZoneDifficulty::OverrideModeMatches(uint32 instanceId, uint32 modeMask) { - auto spellIt = sZoneDifficulty->SpellNerfOverrides.find(spellId); - if (spellIt == sZoneDifficulty->SpellNerfOverrides.end()) - return false; - - auto mapIt = spellIt->second.find(mapId); - if (mapIt == spellIt->second.end()) - return false; - - uint32 modeMask = mapIt->second.ModeMask; bool isMythic = sZoneDifficulty->IsInstanceMythic(instanceId); return (sZoneDifficulty->HasMythicmode(modeMask) && isMythic) || @@ -955,6 +945,10 @@ bool ZoneDifficulty::HasCompletedFullTier(uint32 category, uint32 playerGuid) break; } + auto playerLogIt = sZoneDifficulty->Logs.find(playerGuid); + if (playerLogIt == sZoneDifficulty->Logs.end()) + return false; + for (uint32 mapId : MapList) { auto encounterIt = sZoneDifficulty->EncounterCounter.find(mapId); @@ -964,10 +958,6 @@ bool ZoneDifficulty::HasCompletedFullTier(uint32 category, uint32 playerGuid) return false; } - auto playerLogIt = sZoneDifficulty->Logs.find(playerGuid); - if (playerLogIt == sZoneDifficulty->Logs.end()) - return false; - auto mapLogIt = playerLogIt->second.find(mapId); if (mapLogIt == playerLogIt->second.end()) return false; diff --git a/src/mod_zone_difficulty_scripts.cpp b/src/mod_zone_difficulty_scripts.cpp index c415c5f1..f5a14a24 100644 --- a/src/mod_zone_difficulty_scripts.cpp +++ b/src/mod_zone_difficulty_scripts.cpp @@ -96,12 +96,17 @@ class mod_zone_difficulty_unitscript : public UnitScript if (overrideIt != sZoneDifficulty->SpellNerfOverrides.end()) { auto const& overrideMap = overrideIt->second; - if (sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) + + auto mapIt = overrideMap.find(mapId); + if (mapIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, mapIt->second.ModeMask)) + { + absorb = scaleAbsorb(absorb, mapIt->second.NerfPct); + } + else { - if (overrideMap.count(mapId)) - absorb = scaleAbsorb(absorb, overrideMap.at(mapId).NerfPct); - else if (overrideMap.count(0)) - absorb = scaleAbsorb(absorb, overrideMap.at(0).NerfPct); + auto globalIt = overrideMap.find(0); + if (globalIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, globalIt->second.ModeMask)) + absorb = scaleAbsorb(absorb, globalIt->second.NerfPct); } } @@ -163,14 +168,14 @@ class mod_zone_difficulty_unitscript : public UnitScript auto& overrideMap = spellIt->second; auto mapIt = overrideMap.find(mapId); - if (mapIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) + if (mapIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, mapIt->second.ModeMask)) { heal = heal * mapIt->second.NerfPct; return; } auto globalIt = overrideMap.find(0); - if (globalIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) + if (globalIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, globalIt->second.ModeMask)) { heal = heal * globalIt->second.NerfPct; return; @@ -286,14 +291,14 @@ class mod_zone_difficulty_unitscript : public UnitScript auto& overrideMap = spellIt->second; auto mapIt = overrideMap.find(mapId); - if (mapIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) + if (mapIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, mapIt->second.ModeMask)) { damage = damage * mapIt->second.NerfPct; return; } auto globalIt = overrideMap.find(0); - if (globalIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, spellInfo->Id, mapId)) + if (globalIt != overrideMap.end() && sZoneDifficulty->OverrideModeMatches(instanceId, globalIt->second.ModeMask)) { damage = damage * globalIt->second.NerfPct; return; From 53732950d0881545ee423bd1ab007960fe0483a3 Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sun, 15 Feb 2026 11:29:54 -0300 Subject: [PATCH 8/8] Update src/mod_zone_difficulty_scripts.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/mod_zone_difficulty_scripts.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mod_zone_difficulty_scripts.cpp b/src/mod_zone_difficulty_scripts.cpp index f5a14a24..50b56a8e 100644 --- a/src/mod_zone_difficulty_scripts.cpp +++ b/src/mod_zone_difficulty_scripts.cpp @@ -1024,8 +1024,11 @@ class mod_zone_difficulty_allcreaturescript : public AllCreatureScript if (!sZoneDifficulty->MythicmodeEnable) return; + if (!creature) + return; + Map* map = creature->GetMap(); - if (!creature || !map) + if (!map) return; if (!map->IsRaid() && !(map->IsHeroic() && map->IsDungeon()))