вывод из самбомудлей модов для азероткор

This commit is contained in:
2026-03-07 22:28:31 +04:00
parent 5877ea78cd
commit adcfe8e31d
1720 changed files with 1941740 additions and 40 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_ALL_CREATURE_SCRIPT_H
#define __AB_ALL_CREATURE_SCRIPT_H
#include "ScriptMgr.h"
class AutoBalance_AllCreatureScript : public AllCreatureScript
{
public:
AutoBalance_AllCreatureScript()
: AllCreatureScript("AutoBalance_AllCreatureScript")
{
}
void OnBeforeCreatureSelectLevel(const CreatureTemplate* /*creatureTemplate*/, Creature* creature, uint8& level) override;
void Creature_SelectLevel(const CreatureTemplate* /* cinfo */, Creature* creature) override;
void OnCreatureAddWorld(Creature* creature) override;
void OnCreatureRemoveWorld(Creature* creature) override;
void OnAllCreatureUpdate(Creature* creature, uint32 /*diff*/) override;
// Reset the passed creature to stock if the config has changed
bool ResetCreatureIfNeeded(Creature* creature);
void ModifyCreatureAttributes(Creature* creature);
private:
bool _isSummonCloneOfSummoner(Creature* summon);
};
#endif /* __AB_ALL_CREATURE_SCRIPT_H */
@@ -0,0 +1,227 @@
#include "ABAllMapScript.h"
#include "ABConfig.h"
#include "ABMapInfo.h"
#include "ABUtils.h"
#include "Chat.h"
#include "Message.h"
void AutoBalance_AllMapScript::OnPlayerEnterAll(Map* map, Player* player)
{
if (!EnableGlobal)
return;
if (!map->IsDungeon())
return;
LOG_DEBUG("module.AutoBalance", "AutoBalance:: ------------------------------------------------");
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player {}{} | enters {} ({}{})",
player->GetName(),
player->IsGameMaster() ? " (GM)" : "",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);
// get the map's info
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
// store the previous difficulty for comparison later
int prevAdjustedPlayerCount = mapABInfo->adjustedPlayerCount;
// add player to this map's player list
AddPlayerToMap(map, player);
// recalculate the zone's level stats
mapABInfo->highestCreatureLevel = 0;
mapABInfo->lowestCreatureLevel = 0;
//mapABInfo->avgCreatureLevel = 0;
mapABInfo->activeCreatureCount = 0;
WorldSession* session = player->GetSession();
LocaleConstant locale = session->GetSessionDbLocaleIndex();
// if the previous player count is the same as the new player count, update without force
if ((prevAdjustedPlayerCount == mapABInfo->adjustedPlayerCount) && (mapABInfo->adjustedPlayerCount != 1))
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player difficulty unchanged at {}. Updating map data (no force).",
mapABInfo->adjustedPlayerCount
);
// Update the map's data
UpdateMapDataIfNeeded(map, false);
}
else
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerEnterAll: Player difficulty changed from ({})->({}). Updating map data (force).",
prevAdjustedPlayerCount,
mapABInfo->adjustedPlayerCount
);
// Update the map's data, forced
UpdateMapDataIfNeeded(map, true);
}
// see which existing creatures are active
for (std::vector<Creature*>::iterator creatureIterator = mapABInfo->allMapCreatures.begin(); creatureIterator != mapABInfo->allMapCreatures.end(); ++creatureIterator)
{
AddCreatureToMapCreatureList(*creatureIterator, false, true);
}
// Notify players of the change
if (PlayerChangeNotify && mapABInfo->enabled)
{
if (map->GetEntry()->IsDungeon() && player)
{
if (mapABInfo->playerCount)
{
for (std::vector<Player*>::const_iterator playerIterator = mapABInfo->allMapPlayers.begin(); playerIterator != mapABInfo->allMapPlayers.end(); ++playerIterator)
{
Player* thisPlayer = *playerIterator;
if (thisPlayer)
{
ChatHandler chatHandle = ChatHandler(thisPlayer->GetSession());
InstanceMap* instanceMap = map->ToInstanceMap();
std::string instanceDifficulty; if (instanceMap->IsHeroic()) instanceDifficulty = "Heroic"; else instanceDifficulty = "Normal";
if (thisPlayer && thisPlayer == player) // This is the player that entered
{
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "welcome_to_player").c_str(),
map->GetMapName(),
instanceMap->GetMaxPlayers(),
instanceDifficulty.c_str(),
mapABInfo->playerCount,
mapABInfo->adjustedPlayerCount);
// notify GMs that they won't be accounted for
if (player->IsGameMaster())
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "welcome_to_gm").c_str());
}
else
{
// announce non-GMs entering the instance only
if (!player->IsGameMaster())
chatHandle.PSendSysMessage(ABGetLocaleText(locale, "announce_non_gm_entering_instance").c_str(), player->GetName().c_str(), mapABInfo->playerCount, mapABInfo->adjustedPlayerCount);
}
}
}
}
}
}
}
void AutoBalance_AllMapScript::OnPlayerLeaveAll(Map* map, Player* player)
{
if (!EnableGlobal)
return;
if (!map->IsDungeon())
return;
LOG_DEBUG("module.AutoBalance", "AutoBalance:: ------------------------------------------------");
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player {}{} | exits {} ({}{})",
player->GetName(),
player->IsGameMaster() ? " (GM)" : "",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : ""
);
// get the map's info
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
// store the previous difficulty for comparison later
int prevAdjustedPlayerCount = mapABInfo->adjustedPlayerCount;
// remove this player from this map's player list
bool playerWasRemoved = RemovePlayerFromMap(map, player);
// report the number of players in the map
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: There are {} player(s) left in the map.", mapABInfo->allMapPlayers.size());
// if a player was NOT removed, return now - stats don't need to be updated
if (!playerWasRemoved)
return;
// recalculate the zone's level stats
mapABInfo->highestCreatureLevel = 0;
mapABInfo->lowestCreatureLevel = 0;
//mapABInfo->avgCreatureLevel = 0;
mapABInfo->activeCreatureCount = 0;
// see which existing creatures are active
for (std::vector<Creature*>::iterator creatureIterator = mapABInfo->allMapCreatures.begin(); creatureIterator != mapABInfo->allMapCreatures.end(); ++creatureIterator)
AddCreatureToMapCreatureList(*creatureIterator, false, true);
// if the previous player count is the same as the new player count, update without force
if (prevAdjustedPlayerCount == mapABInfo->adjustedPlayerCount)
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player difficulty unchanged at {}. Updating map data (no force).",
mapABInfo->adjustedPlayerCount
);
// Update the map's data
UpdateMapDataIfNeeded(map, false);
}
else
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player difficulty changed from ({})->({}). Updating map data (force).",
prevAdjustedPlayerCount,
mapABInfo->adjustedPlayerCount
);
// Update the map's data, forced
UpdateMapDataIfNeeded(map, true);
}
// updates the player count and levels for the map
if (map->GetEntry() && map->GetEntry()->IsDungeon())
{
{
mapABInfo->playerCount = mapABInfo->allMapPlayers.size();
LOG_DEBUG("module.AutoBalance", "AutoBalance_AllMapScript::OnPlayerLeaveAll: Player {} left the instance.",
player->GetName(),
mapABInfo->playerCount,
mapABInfo->adjustedPlayerCount
);
}
}
// Notify remaining players in the instance that a player left
if (PlayerChangeNotify && mapABInfo->enabled)
{
if (map->GetEntry()->IsDungeon() && player && !player->IsGameMaster())
{
if (mapABInfo->playerCount)
{
for (std::vector<Player*>::const_iterator playerIterator = mapABInfo->allMapPlayers.begin(); playerIterator != mapABInfo->allMapPlayers.end(); ++playerIterator)
{
Player* thisPlayer = *playerIterator;
if (thisPlayer && thisPlayer != player)
{
ChatHandler chatHandle = ChatHandler(thisPlayer->GetSession());
if (mapABInfo->combatLocked)
{
chatHandle.PSendSysMessage(ABGetLocaleText(thisPlayer->GetSession()->GetSessionDbLocaleIndex(), "leaving_instance_combat").c_str(),
player->GetName().c_str(),
mapABInfo->adjustedPlayerCount);
}
else
{
chatHandle.PSendSysMessage(ABGetLocaleText(thisPlayer->GetSession()->GetSessionDbLocaleIndex(), "leaving_instance").c_str(),
player->GetName().c_str(),
mapABInfo->playerCount,
mapABInfo->adjustedPlayerCount);
}
}
}
}
}
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_ALL_MAP_SCRIPT_H
#define __AB_ALL_MAP_SCRIPT_H
#include "ScriptMgr.h"
class AutoBalance_AllMapScript : public AllMapScript
{
public:
AutoBalance_AllMapScript()
: AllMapScript("AutoBalance_AllMapScript", {
ALLMAPHOOK_ON_PLAYER_ENTER_ALL,
ALLMAPHOOK_ON_PLAYER_LEAVE_ALL
})
{
}
// hook triggers after the player has already entered the world
void OnPlayerEnterAll(Map* map, Player* player) override;
// hook triggers just before the player left the world
void OnPlayerLeaveAll(Map* map, Player* player) override;
};
#endif
@@ -0,0 +1,186 @@
#include "ABCommandScript.h"
#include "ABConfig.h"
#include "ABCreatureInfo.h"
#include "ABMapInfo.h"
#include "ABUtils.h"
#include "Message.h"
bool AutoBalance_CommandScript::HandleABSetOffsetCommand(ChatHandler* handler, const char* args)
{
if (!*args)
{
handler->PSendSysMessage(".autobalance setoffset #");
handler->PSendSysMessage(ABGetLocaleText(handler->GetSession()->GetSessionDbLocaleIndex(), "set_offset_command_description").c_str());
return false;
}
char* offset = strtok((char*)args, " ");
int32 offseti = -1;
if (offset)
{
offseti = (uint32)atoi(offset);
std::vector<std::string> args = { std::to_string(offseti) };
handler->PSendSysMessage(ABGetLocaleText(handler->GetSession()->GetSessionDbLocaleIndex(), "set_offset_command_success").c_str(), offseti);
PlayerCountDifficultyOffset = offseti;
globalConfigTime = GetCurrentConfigTime();
return true;
}
else
handler->PSendSysMessage(ABGetLocaleText(handler->GetSession()->GetSessionDbLocaleIndex(), "set_offset_command_error").c_str());
return false;
}
bool AutoBalance_CommandScript::HandleABGetOffsetCommand(ChatHandler* handler, const char* /*args*/)
{
handler->PSendSysMessage(ABGetLocaleText(handler->GetSession()->GetSessionDbLocaleIndex(), "get_offset_command_success").c_str(), PlayerCountDifficultyOffset);
return true;
}
bool AutoBalance_CommandScript::HandleABMapStatsCommand(ChatHandler* handler, const char* /*args*/)
{
Player* player = handler->GetPlayer();
auto locale = handler->GetSession()->GetSessionDbLocaleIndex();
AutoBalanceMapInfo* mapABInfo = GetMapInfo(player->GetMap());
if (player->GetMap()->IsDungeon())
{
handler->PSendSysMessage("---");
// Map basics
handler->PSendSysMessage("{} ({}-player {}) | ID {}-{}{}",
player->GetMap()->GetMapName(),
player->GetMap()->ToInstanceMap()->GetMaxPlayers(),
player->GetMap()->ToInstanceMap()->IsHeroic() ? "Heroic" : "Normal",
player->GetMapId(),
player->GetInstanceId(),
mapABInfo->enabled ? "" : " | AutoBalance DISABLED");
// if the map isn't enabled, don't display anything else
// if (!mapABInfo->enabled) { return true; }
// Player stats
handler->PSendSysMessage("Players on map: {} (Lvl {} - {})",
mapABInfo->playerCount,
mapABInfo->lowestPlayerLevel,
mapABInfo->highestPlayerLevel
);
// Adjusted player count (multiple scenarios)
if (mapABInfo->combatLockTripped)
handler->PSendSysMessage(ABGetLocaleText(locale, "adjusted_player_count_combat_locked").c_str(), mapABInfo->adjustedPlayerCount);
else if (mapABInfo->playerCount < mapABInfo->minPlayers && !PlayerCountDifficultyOffset)
handler->PSendSysMessage(ABGetLocaleText(locale, "adjusted_player_count_map_minimum").c_str(), mapABInfo->adjustedPlayerCount);
else if (mapABInfo->playerCount < mapABInfo->minPlayers && PlayerCountDifficultyOffset)
handler->PSendSysMessage(ABGetLocaleText(locale, "adjusted_player_count_map_minimum_difficulty_offset").c_str(), mapABInfo->adjustedPlayerCount, PlayerCountDifficultyOffset);
else if (PlayerCountDifficultyOffset)
handler->PSendSysMessage(ABGetLocaleText(locale, "adjusted_player_count_difficulty_offset").c_str(), mapABInfo->adjustedPlayerCount, PlayerCountDifficultyOffset);
else
handler->PSendSysMessage(ABGetLocaleText(locale, "adjusted_player_count").c_str(), mapABInfo->adjustedPlayerCount);
// LFG levels
handler->PSendSysMessage(ABGetLocaleText(locale, "lfg_range").c_str(), mapABInfo->lfgMinLevel, mapABInfo->lfgMaxLevel, mapABInfo->lfgTargetLevel);
// Calculated map level (creature average)
handler->PSendSysMessage(ABGetLocaleText(locale, "map_level").c_str(),
(uint8)(mapABInfo->avgCreatureLevel + 0.5f),
mapABInfo->isLevelScalingEnabled && mapABInfo->enabled ? "->" + std::to_string(mapABInfo->highestPlayerLevel) + ABGetLocaleText(locale, "level_scaling_enabled").c_str() : ABGetLocaleText(locale, "level_scaling_disabled").c_str()
);
// World Health Multiplier
handler->PSendSysMessage(ABGetLocaleText(locale, "world_health_multiplier").c_str(), mapABInfo->worldHealthMultiplier);
// World Damage and Healing Multiplier
if (mapABInfo->worldDamageHealingMultiplier != mapABInfo->scaledWorldDamageHealingMultiplier)
{
handler->PSendSysMessage(ABGetLocaleText(locale, "world_hostile_damage_healing_multiplier_to").c_str(),
mapABInfo->worldDamageHealingMultiplier,
mapABInfo->scaledWorldDamageHealingMultiplier
);
}
else
{
handler->PSendSysMessage(ABGetLocaleText(locale, "world_hostile_damage_healing_multiplier").c_str(),
mapABInfo->worldDamageHealingMultiplier
);
}
// Creature Stats
handler->PSendSysMessage(ABGetLocaleText(locale, "original_creature_level_range").c_str(),
mapABInfo->lowestCreatureLevel,
mapABInfo->highestCreatureLevel,
mapABInfo->avgCreatureLevel
);
handler->PSendSysMessage(ABGetLocaleText(locale, "active_total_creatures_in_map").c_str(),
mapABInfo->activeCreatureCount,
mapABInfo->allMapCreatures.size()
);
return true;
}
else
{
handler->PSendSysMessage(ABGetLocaleText(locale, "ab_command_only_in_instance").c_str());
return false;
}
}
bool AutoBalance_CommandScript::HandleABCreatureStatsCommand(ChatHandler* handler, const char* /*args*/)
{
Creature* target = handler->getSelectedCreature();
auto locale = handler->GetSession()->GetSessionDbLocaleIndex();
if (!target)
{
handler->SendSysMessage(LANG_SELECT_CREATURE);
handler->SetSentErrorMessage(true);
return false;
}
else if (!target->GetMap()->IsDungeon())
{
handler->PSendSysMessage(ABGetLocaleText(locale, "target_no_in_instance").c_str());
handler->SetSentErrorMessage(true);
return false;
}
AutoBalanceCreatureInfo* targetABInfo = target->CustomData.GetDefault<AutoBalanceCreatureInfo>("AutoBalanceCreatureInfo");
handler->PSendSysMessage("---");
handler->PSendSysMessage("{} ({}{}{}), {}",
target->GetName(),
targetABInfo->UnmodifiedLevel,
isCreatureRelevant(target) && targetABInfo->UnmodifiedLevel != target->GetLevel() ? "->" + std::to_string(targetABInfo->selectedLevel) : "",
isBossOrBossSummon(target) ? " | Boss" : "",
targetABInfo->isActive ? ABGetLocaleText(locale, "active_for_map_stats").c_str() : ABGetLocaleText(locale, "ignored_for_map_stats").c_str());
handler->PSendSysMessage(ABGetLocaleText(locale, "creature_difficulty_level").c_str(), targetABInfo->instancePlayerCount);
// summon
if (target->IsSummon() && targetABInfo->summoner && targetABInfo->isCloneOfSummoner)
handler->PSendSysMessage(ABGetLocaleText(locale, "clone_of_summon").c_str(), targetABInfo->summonerName, targetABInfo->summonerLevel);
else if (target->IsSummon() && targetABInfo->summoner)
handler->PSendSysMessage(ABGetLocaleText(locale, "summon_of_summon").c_str(), targetABInfo->summonerName, targetABInfo->summonerLevel);
else if (target->IsSummon())
handler->PSendSysMessage(ABGetLocaleText(locale, "summon_without_summoner").c_str());
// level scaled
if (targetABInfo->UnmodifiedLevel != target->GetLevel())
{
handler->PSendSysMessage(ABGetLocaleText(locale, "health_multiplier_to").c_str(), targetABInfo->HealthMultiplier, targetABInfo->ScaledHealthMultiplier);
handler->PSendSysMessage(ABGetLocaleText(locale, "mana_multiplier_to").c_str(), targetABInfo->ManaMultiplier, targetABInfo->ScaledManaMultiplier);
handler->PSendSysMessage(ABGetLocaleText(locale, "armor_multiplier_to").c_str(), targetABInfo->ArmorMultiplier, targetABInfo->ScaledArmorMultiplier);
handler->PSendSysMessage(ABGetLocaleText(locale, "damage_multiplier_to").c_str(), targetABInfo->DamageMultiplier, targetABInfo->ScaledDamageMultiplier);
}
// not level scaled
else
{
handler->PSendSysMessage(ABGetLocaleText(locale, "health_multiplier").c_str(), targetABInfo->HealthMultiplier);
handler->PSendSysMessage(ABGetLocaleText(locale, "mana_multiplier").c_str(), targetABInfo->ManaMultiplier);
handler->PSendSysMessage(ABGetLocaleText(locale, "armor_multiplier").c_str(), targetABInfo->ArmorMultiplier);
handler->PSendSysMessage(ABGetLocaleText(locale, "damage_multiplier").c_str(), targetABInfo->DamageMultiplier);
}
handler->PSendSysMessage(ABGetLocaleText(locale, "cc_duration_multiplier").c_str(), targetABInfo->CCDurationMultiplier);
handler->PSendSysMessage(ABGetLocaleText(locale, "xp_money_multiplier").c_str(), targetABInfo->XPModifier, targetABInfo->MoneyModifier);
return true;
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_COMMAND_SCRIPT_H
#define __AB_COMMAND_SCRIPT_H
#include "Chat.h"
#include "Config.h"
#include "ScriptMgr.h"
using namespace Acore::ChatCommands;
class AutoBalance_CommandScript : public CommandScript
{
public:
AutoBalance_CommandScript() : CommandScript("AutoBalance_CommandScript") { }
ChatCommandTable GetCommands() const override
{
static ChatCommandTable ABCommandTable =
{
{ "setoffset", HandleABSetOffsetCommand, SEC_GAMEMASTER, Console::Yes },
{ "getoffset", HandleABGetOffsetCommand, SEC_PLAYER, Console::Yes },
{ "mapstat", HandleABMapStatsCommand, SEC_PLAYER, Console::Yes },
{ "creaturestat", HandleABCreatureStatsCommand, SEC_PLAYER, Console::Yes }
};
static ChatCommandTable commandTable =
{
{ "autobalance", ABCommandTable },
{ "ab", ABCommandTable },
};
return commandTable;
};
static bool HandleABSetOffsetCommand(ChatHandler* handler, const char* args);
static bool HandleABGetOffsetCommand(ChatHandler* handler, const char* args);
static bool HandleABMapStatsCommand(ChatHandler* handler, const char* args);
static bool HandleABCreatureStatsCommand(ChatHandler* handler, const char* args);
};
#endif /* __AB_COMMAND_SCRIPT_H */
+349
View File
@@ -0,0 +1,349 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#include "ABConfig.h"
#include "ABUtils.h"
std::map <int, int> forcedCreatureIds;
std::list<uint32> disabledDungeonIds;
uint32 minPlayersNormal;
uint32 minPlayersHeroic;
uint32 minPlayersRaid;
uint32 minPlayersRaidHeroic;
std::map<uint32, uint8> minPlayersPerDungeonIdMap;
std::map<uint32, uint8> minPlayersPerHeroicDungeonIdMap;
std::map<uint32, AutoBalanceInflectionPointSettings> dungeonOverrides;
std::map<uint32, AutoBalanceInflectionPointSettings> bossOverrides;
std::map<uint32, AutoBalanceStatModifiers> statModifierOverrides;
std::map<uint32, AutoBalanceStatModifiers> statModifierBossOverrides;
std::map<uint32, AutoBalanceStatModifiers> statModifierCreatureOverrides;
std::map<uint8, AutoBalanceLevelScalingDynamicLevelSettings> levelScalingDynamicLevelOverrides;
std::map<uint32, uint32> levelScalingDistanceCheckOverrides;
// spell IDs that spend player health
// player abilities don't actually appear to be caught by `ModifySpellDamageTaken`,
// but I'm leaving them here in case they ever DO get caught by it
std::list<uint32> spellIdsThatSpendPlayerHealth =
{
45529, // Blood Tap
2687, // Bloodrage
27869, // Dark Rune
16666, // Demonic Rune
755, // Health Funnel (Rank 1)
3698, // Health Funnel (Rank 2)
3699, // Health Funnel (Rank 3)
3700, // Health Funnel (Rank 4)
11693, // Health Funnel (Rank 5)
11694, // Health Funnel (Rank 6)
11695, // Health Funnel (Rank 7)
27259, // Health Funnel (Rank 8)
47856, // Health Funnel (Rank 9)
1454, // Life Tap (Rank 1)
1455, // Life Tap (Rank 2)
1456, // Life Tap (Rank 3)
11687, // Life Tap (Rank 4)
11688, // Life Tap (Rank 5)
11689, // Life Tap (Rank 6)
27222, // Life Tap (Rank 7)
57946, // Life Tap (Rank 8)
29858, // Soulshatter
55213 // Unholy Frenzy
};
// spell IDs that should never be modified
// handles cases where a spell is reflecting damage or otherwise converting player damage to something else
std::list<uint32> spellIdsToNeverModify =
{
1177 // Twin Empathy (AQ40 Twin Emperors, only in `spell_dbc` database table)
};
// creature IDs that should never be considered clones
// handles cases where a creature is spawned by another creature, but is not a clone (doesn't retain health/mana values)
std::list<uint32> creatureIDsThatAreNotClones =
{
16152 // Attumen the Huntsman (Karazhan) combined form
};
int8 PlayerCountDifficultyOffset;
bool LevelScaling;
int8 LevelScalingSkipHigherLevels;
int8 LevelScalingSkipLowerLevels;
int8 LevelScalingDynamicLevelCeilingDungeons;
int8 LevelScalingDynamicLevelFloorDungeons;
int8 LevelScalingDynamicLevelCeilingRaids;
int8 LevelScalingDynamicLevelFloorRaids;
int8 LevelScalingDynamicLevelCeilingHeroicDungeons;
int8 LevelScalingDynamicLevelFloorHeroicDungeons;
int8 LevelScalingDynamicLevelCeilingHeroicRaids;
int8 LevelScalingDynamicLevelFloorHeroicRaids;
ScalingMethod LevelScalingMethod;
uint32 rewardRaid;
uint32 rewardDungeon;
uint32 MinPlayerReward;
bool Announcement;
bool LevelScalingEndGameBoost;
bool PlayerChangeNotify;
bool rewardEnabled;
float MinHPModifier;
float MinManaModifier;
float MinDamageModifier;
float MinCCDurationModifier;
float MaxCCDurationModifier;
//
// RewardScaling.*
//
ScalingMethod RewardScalingMethod;
bool RewardScalingXP;
bool RewardScalingMoney;
float RewardScalingXPModifier;
float RewardScalingMoneyModifier;
uint64_t globalConfigTime = GetCurrentConfigTime();
//
// Enable.*
//
bool EnableGlobal;
bool Enable5M;
bool Enable10M;
bool Enable15M;
bool Enable20M;
bool Enable25M;
bool Enable40M;
bool Enable5MHeroic;
bool Enable10MHeroic;
bool Enable25MHeroic;
bool EnableOtherNormal;
bool EnableOtherHeroic;
//
// InflectionPoint*
//
float InflectionPoint;
float InflectionPointCurveFloor;
float InflectionPointCurveCeiling;
float InflectionPointBoss;
float InflectionPointHeroic;
float InflectionPointHeroicCurveFloor;
float InflectionPointHeroicCurveCeiling;
float InflectionPointHeroicBoss;
float InflectionPointRaid;
float InflectionPointRaidCurveFloor;
float InflectionPointRaidCurveCeiling;
float InflectionPointRaidBoss;
float InflectionPointRaidHeroic;
float InflectionPointRaidHeroicCurveFloor;
float InflectionPointRaidHeroicCurveCeiling;
float InflectionPointRaidHeroicBoss;
float InflectionPointRaid10M;
float InflectionPointRaid10MCurveFloor;
float InflectionPointRaid10MCurveCeiling;
float InflectionPointRaid10MBoss;
float InflectionPointRaid10MHeroic;
float InflectionPointRaid10MHeroicCurveFloor;
float InflectionPointRaid10MHeroicCurveCeiling;
float InflectionPointRaid10MHeroicBoss;
float InflectionPointRaid15M;
float InflectionPointRaid15MCurveFloor;
float InflectionPointRaid15MCurveCeiling;
float InflectionPointRaid15MBoss;
float InflectionPointRaid20M;
float InflectionPointRaid20MCurveFloor;
float InflectionPointRaid20MCurveCeiling;
float InflectionPointRaid20MBoss;
float InflectionPointRaid25M;
float InflectionPointRaid25MCurveFloor;
float InflectionPointRaid25MCurveCeiling;
float InflectionPointRaid25MBoss;
float InflectionPointRaid25MHeroic;
float InflectionPointRaid25MHeroicCurveFloor;
float InflectionPointRaid25MHeroicCurveCeiling;
float InflectionPointRaid25MHeroicBoss;
float InflectionPointRaid40M;
float InflectionPointRaid40MCurveFloor;
float InflectionPointRaid40MCurveCeiling;
float InflectionPointRaid40MBoss;
//
// StatModifier*
//
float StatModifier_Global;
float StatModifier_Health;
float StatModifier_Mana;
float StatModifier_Armor;
float StatModifier_Damage;
float StatModifier_CCDuration;
float StatModifierHeroic_Global;
float StatModifierHeroic_Health;
float StatModifierHeroic_Mana;
float StatModifierHeroic_Armor;
float StatModifierHeroic_Damage;
float StatModifierHeroic_CCDuration;
float StatModifierRaid_Global;
float StatModifierRaid_Health;
float StatModifierRaid_Mana;
float StatModifierRaid_Armor;
float StatModifierRaid_Damage;
float StatModifierRaid_CCDuration;
float StatModifierRaidHeroic_Global;
float StatModifierRaidHeroic_Health;
float StatModifierRaidHeroic_Mana;
float StatModifierRaidHeroic_Armor;
float StatModifierRaidHeroic_Damage;
float StatModifierRaidHeroic_CCDuration;
float StatModifierRaid10M_Global;
float StatModifierRaid10M_Health;
float StatModifierRaid10M_Mana;
float StatModifierRaid10M_Armor;
float StatModifierRaid10M_Damage;
float StatModifierRaid10M_CCDuration;
float StatModifierRaid10MHeroic_Global;
float StatModifierRaid10MHeroic_Health;
float StatModifierRaid10MHeroic_Mana;
float StatModifierRaid10MHeroic_Armor;
float StatModifierRaid10MHeroic_Damage;
float StatModifierRaid10MHeroic_CCDuration;
float StatModifierRaid15M_Global;
float StatModifierRaid15M_Health;
float StatModifierRaid15M_Mana;
float StatModifierRaid15M_Armor;
float StatModifierRaid15M_Damage;
float StatModifierRaid15M_CCDuration;
float StatModifierRaid20M_Global;
float StatModifierRaid20M_Health;
float StatModifierRaid20M_Mana;
float StatModifierRaid20M_Armor;
float StatModifierRaid20M_Damage;
float StatModifierRaid20M_CCDuration;
float StatModifierRaid25M_Global;
float StatModifierRaid25M_Health;
float StatModifierRaid25M_Mana;
float StatModifierRaid25M_Armor;
float StatModifierRaid25M_Damage;
float StatModifierRaid25M_CCDuration;
float StatModifierRaid25MHeroic_Global;
float StatModifierRaid25MHeroic_Health;
float StatModifierRaid25MHeroic_Mana;
float StatModifierRaid25MHeroic_Armor;
float StatModifierRaid25MHeroic_Damage;
float StatModifierRaid25MHeroic_CCDuration;
float StatModifierRaid40M_Global;
float StatModifierRaid40M_Health;
float StatModifierRaid40M_Mana;
float StatModifierRaid40M_Armor;
float StatModifierRaid40M_Damage;
float StatModifierRaid40M_CCDuration;
//
// StatModifier* (Boss)
//
float StatModifier_Boss_Global;
float StatModifier_Boss_Health;
float StatModifier_Boss_Mana;
float StatModifier_Boss_Armor;
float StatModifier_Boss_Damage;
float StatModifier_Boss_CCDuration;
float StatModifierHeroic_Boss_Global;
float StatModifierHeroic_Boss_Health;
float StatModifierHeroic_Boss_Mana;
float StatModifierHeroic_Boss_Armor;
float StatModifierHeroic_Boss_Damage;
float StatModifierHeroic_Boss_CCDuration;
float StatModifierRaid_Boss_Global;
float StatModifierRaid_Boss_Health;
float StatModifierRaid_Boss_Mana;
float StatModifierRaid_Boss_Armor;
float StatModifierRaid_Boss_Damage;
float StatModifierRaid_Boss_CCDuration;
float StatModifierRaidHeroic_Boss_Global;
float StatModifierRaidHeroic_Boss_Health;
float StatModifierRaidHeroic_Boss_Mana;
float StatModifierRaidHeroic_Boss_Armor;
float StatModifierRaidHeroic_Boss_Damage;
float StatModifierRaidHeroic_Boss_CCDuration;
float StatModifierRaid10M_Boss_Global;
float StatModifierRaid10M_Boss_Health;
float StatModifierRaid10M_Boss_Mana;
float StatModifierRaid10M_Boss_Armor;
float StatModifierRaid10M_Boss_Damage;
float StatModifierRaid10M_Boss_CCDuration;
float StatModifierRaid10MHeroic_Boss_Global;
float StatModifierRaid10MHeroic_Boss_Health;
float StatModifierRaid10MHeroic_Boss_Mana;
float StatModifierRaid10MHeroic_Boss_Armor;
float StatModifierRaid10MHeroic_Boss_Damage;
float StatModifierRaid10MHeroic_Boss_CCDuration;
float StatModifierRaid15M_Boss_Global;
float StatModifierRaid15M_Boss_Health;
float StatModifierRaid15M_Boss_Mana;
float StatModifierRaid15M_Boss_Armor;
float StatModifierRaid15M_Boss_Damage;
float StatModifierRaid15M_Boss_CCDuration;
float StatModifierRaid20M_Boss_Global;
float StatModifierRaid20M_Boss_Health;
float StatModifierRaid20M_Boss_Mana;
float StatModifierRaid20M_Boss_Armor;
float StatModifierRaid20M_Boss_Damage;
float StatModifierRaid20M_Boss_CCDuration;
float StatModifierRaid25M_Boss_Global;
float StatModifierRaid25M_Boss_Health;
float StatModifierRaid25M_Boss_Mana;
float StatModifierRaid25M_Boss_Armor;
float StatModifierRaid25M_Boss_Damage;
float StatModifierRaid25M_Boss_CCDuration;
float StatModifierRaid25MHeroic_Boss_Global;
float StatModifierRaid25MHeroic_Boss_Health;
float StatModifierRaid25MHeroic_Boss_Mana;
float StatModifierRaid25MHeroic_Boss_Armor;
float StatModifierRaid25MHeroic_Boss_Damage;
float StatModifierRaid25MHeroic_Boss_CCDuration;
float StatModifierRaid40M_Boss_Global;
float StatModifierRaid40M_Boss_Health;
float StatModifierRaid40M_Boss_Mana;
float StatModifierRaid40M_Boss_Armor;
float StatModifierRaid40M_Boss_Damage;
float StatModifierRaid40M_Boss_CCDuration;
+321
View File
@@ -0,0 +1,321 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_CONFIG_H
#define __AB_CONFIG_H
#include "ABInflectionPointSettings.h"
#include "ABLevelScalingDynamicLevelSettings.h"
#include "ABStatModifiers.h"
#include "AutoBalance.h"
#include "SharedDefines.h"
#include <list>
#include <map>
extern std::map<uint32, AutoBalanceInflectionPointSettings> dungeonOverrides;
extern std::map<uint32, AutoBalanceInflectionPointSettings> bossOverrides;
extern std::map<uint32, AutoBalanceStatModifiers> statModifierOverrides;
extern std::map<uint32, AutoBalanceStatModifiers> statModifierBossOverrides;
extern std::map<uint32, AutoBalanceStatModifiers> statModifierCreatureOverrides;
extern std::map<uint8 , AutoBalanceLevelScalingDynamicLevelSettings> levelScalingDynamicLevelOverrides;
extern std::map<uint32, uint32> levelScalingDistanceCheckOverrides;
extern std::map <int, int> forcedCreatureIds;
extern std::list<uint32> disabledDungeonIds;
extern uint32 minPlayersNormal;
extern uint32 minPlayersHeroic;
extern uint32 minPlayersRaid;
extern uint32 minPlayersRaidHeroic;
extern std::map<uint32, uint8> minPlayersPerDungeonIdMap;
extern std::map<uint32, uint8> minPlayersPerHeroicDungeonIdMap;
extern std::list<uint32> spellIdsThatSpendPlayerHealth;
extern std::list<uint32> spellIdsToNeverModify;
extern std::list<uint32> creatureIDsThatAreNotClones;
extern int8 PlayerCountDifficultyOffset;
extern bool LevelScaling;
extern int8 LevelScalingSkipHigherLevels;
extern int8 LevelScalingSkipLowerLevels;
extern int8 LevelScalingDynamicLevelCeilingDungeons;
extern int8 LevelScalingDynamicLevelFloorDungeons;
extern int8 LevelScalingDynamicLevelCeilingRaids;
extern int8 LevelScalingDynamicLevelFloorRaids;
extern int8 LevelScalingDynamicLevelCeilingHeroicDungeons;
extern int8 LevelScalingDynamicLevelFloorHeroicDungeons;
extern int8 LevelScalingDynamicLevelCeilingHeroicRaids;
extern int8 LevelScalingDynamicLevelFloorHeroicRaids;
extern ScalingMethod LevelScalingMethod;
extern uint32 rewardRaid;
extern uint32 rewardDungeon;
extern uint32 MinPlayerReward;
extern bool Announcement;
extern bool LevelScalingEndGameBoost;
extern bool PlayerChangeNotify;
extern bool rewardEnabled;
extern float MinHPModifier;
extern float MinManaModifier;
extern float MinDamageModifier;
extern float MinCCDurationModifier;
extern float MaxCCDurationModifier;
//
// RewardScaling.*
//
extern ScalingMethod RewardScalingMethod;
extern bool RewardScalingXP;
extern bool RewardScalingMoney;
extern float RewardScalingXPModifier;
extern float RewardScalingMoneyModifier;
extern uint64_t globalConfigTime;
//
// Enable.*
//
extern bool EnableGlobal;
extern bool Enable5M;
extern bool Enable10M;
extern bool Enable15M;
extern bool Enable20M;
extern bool Enable25M;
extern bool Enable40M;
extern bool Enable5MHeroic;
extern bool Enable10MHeroic;
extern bool Enable25MHeroic;
extern bool EnableOtherNormal;
extern bool EnableOtherHeroic;
//
// InflectionPoint*
//
extern float InflectionPoint;
extern float InflectionPointCurveFloor;
extern float InflectionPointCurveCeiling;
extern float InflectionPointBoss;
extern float InflectionPointHeroic;
extern float InflectionPointHeroicCurveFloor;
extern float InflectionPointHeroicCurveCeiling;
extern float InflectionPointHeroicBoss;
extern float InflectionPointRaid;
extern float InflectionPointRaidCurveFloor;
extern float InflectionPointRaidCurveCeiling;
extern float InflectionPointRaidBoss;
extern float InflectionPointRaidHeroic;
extern float InflectionPointRaidHeroicCurveFloor;
extern float InflectionPointRaidHeroicCurveCeiling;
extern float InflectionPointRaidHeroicBoss;
extern float InflectionPointRaid10M;
extern float InflectionPointRaid10MCurveFloor;
extern float InflectionPointRaid10MCurveCeiling;
extern float InflectionPointRaid10MBoss;
extern float InflectionPointRaid10MHeroic;
extern float InflectionPointRaid10MHeroicCurveFloor;
extern float InflectionPointRaid10MHeroicCurveCeiling;
extern float InflectionPointRaid10MHeroicBoss;
extern float InflectionPointRaid15M;
extern float InflectionPointRaid15MCurveFloor;
extern float InflectionPointRaid15MCurveCeiling;
extern float InflectionPointRaid15MBoss;
extern float InflectionPointRaid20M;
extern float InflectionPointRaid20MCurveFloor;
extern float InflectionPointRaid20MCurveCeiling;
extern float InflectionPointRaid20MBoss;
extern float InflectionPointRaid25M;
extern float InflectionPointRaid25MCurveFloor;
extern float InflectionPointRaid25MCurveCeiling;
extern float InflectionPointRaid25MBoss;
extern float InflectionPointRaid25MHeroic;
extern float InflectionPointRaid25MHeroicCurveFloor;
extern float InflectionPointRaid25MHeroicCurveCeiling;
extern float InflectionPointRaid25MHeroicBoss;
extern float InflectionPointRaid40M;
extern float InflectionPointRaid40MCurveFloor;
extern float InflectionPointRaid40MCurveCeiling;
extern float InflectionPointRaid40MBoss;
//
// StatModifier*
//
extern float StatModifier_Global;
extern float StatModifier_Health;
extern float StatModifier_Mana;
extern float StatModifier_Armor;
extern float StatModifier_Damage;
extern float StatModifier_CCDuration;
extern float StatModifierHeroic_Global;
extern float StatModifierHeroic_Health;
extern float StatModifierHeroic_Mana;
extern float StatModifierHeroic_Armor;
extern float StatModifierHeroic_Damage;
extern float StatModifierHeroic_CCDuration;
extern float StatModifierRaid_Global;
extern float StatModifierRaid_Health;
extern float StatModifierRaid_Mana;
extern float StatModifierRaid_Armor;
extern float StatModifierRaid_Damage;
extern float StatModifierRaid_CCDuration;
extern float StatModifierRaidHeroic_Global;
extern float StatModifierRaidHeroic_Health;
extern float StatModifierRaidHeroic_Mana;
extern float StatModifierRaidHeroic_Armor;
extern float StatModifierRaidHeroic_Damage;
extern float StatModifierRaidHeroic_CCDuration;
extern float StatModifierRaid10M_Global;
extern float StatModifierRaid10M_Health;
extern float StatModifierRaid10M_Mana;
extern float StatModifierRaid10M_Armor;
extern float StatModifierRaid10M_Damage;
extern float StatModifierRaid10M_CCDuration;
extern float StatModifierRaid10MHeroic_Global;
extern float StatModifierRaid10MHeroic_Health;
extern float StatModifierRaid10MHeroic_Mana;
extern float StatModifierRaid10MHeroic_Armor;
extern float StatModifierRaid10MHeroic_Damage;
extern float StatModifierRaid10MHeroic_CCDuration;
extern float StatModifierRaid15M_Global;
extern float StatModifierRaid15M_Health;
extern float StatModifierRaid15M_Mana;
extern float StatModifierRaid15M_Armor;
extern float StatModifierRaid15M_Damage;
extern float StatModifierRaid15M_CCDuration;
extern float StatModifierRaid20M_Global;
extern float StatModifierRaid20M_Health;
extern float StatModifierRaid20M_Mana;
extern float StatModifierRaid20M_Armor;
extern float StatModifierRaid20M_Damage;
extern float StatModifierRaid20M_CCDuration;
extern float StatModifierRaid25M_Global;
extern float StatModifierRaid25M_Health;
extern float StatModifierRaid25M_Mana;
extern float StatModifierRaid25M_Armor;
extern float StatModifierRaid25M_Damage;
extern float StatModifierRaid25M_CCDuration;
extern float StatModifierRaid25MHeroic_Global;
extern float StatModifierRaid25MHeroic_Health;
extern float StatModifierRaid25MHeroic_Mana;
extern float StatModifierRaid25MHeroic_Armor;
extern float StatModifierRaid25MHeroic_Damage;
extern float StatModifierRaid25MHeroic_CCDuration;
extern float StatModifierRaid40M_Global;
extern float StatModifierRaid40M_Health;
extern float StatModifierRaid40M_Mana;
extern float StatModifierRaid40M_Armor;
extern float StatModifierRaid40M_Damage;
extern float StatModifierRaid40M_CCDuration;
//
// StatModifier* (Boss)
//
extern float StatModifier_Boss_Global;
extern float StatModifier_Boss_Health;
extern float StatModifier_Boss_Mana;
extern float StatModifier_Boss_Armor;
extern float StatModifier_Boss_Damage;
extern float StatModifier_Boss_CCDuration;
extern float StatModifierHeroic_Boss_Global;
extern float StatModifierHeroic_Boss_Health;
extern float StatModifierHeroic_Boss_Mana;
extern float StatModifierHeroic_Boss_Armor;
extern float StatModifierHeroic_Boss_Damage;
extern float StatModifierHeroic_Boss_CCDuration;
extern float StatModifierRaid_Boss_Global;
extern float StatModifierRaid_Boss_Health;
extern float StatModifierRaid_Boss_Mana;
extern float StatModifierRaid_Boss_Armor;
extern float StatModifierRaid_Boss_Damage;
extern float StatModifierRaid_Boss_CCDuration;
extern float StatModifierRaidHeroic_Boss_Global;
extern float StatModifierRaidHeroic_Boss_Health;
extern float StatModifierRaidHeroic_Boss_Mana;
extern float StatModifierRaidHeroic_Boss_Armor;
extern float StatModifierRaidHeroic_Boss_Damage;
extern float StatModifierRaidHeroic_Boss_CCDuration;
extern float StatModifierRaid10M_Boss_Global;
extern float StatModifierRaid10M_Boss_Health;
extern float StatModifierRaid10M_Boss_Mana;
extern float StatModifierRaid10M_Boss_Armor;
extern float StatModifierRaid10M_Boss_Damage;
extern float StatModifierRaid10M_Boss_CCDuration;
extern float StatModifierRaid10MHeroic_Boss_Global;
extern float StatModifierRaid10MHeroic_Boss_Health;
extern float StatModifierRaid10MHeroic_Boss_Mana;
extern float StatModifierRaid10MHeroic_Boss_Armor;
extern float StatModifierRaid10MHeroic_Boss_Damage;
extern float StatModifierRaid10MHeroic_Boss_CCDuration;
extern float StatModifierRaid15M_Boss_Global;
extern float StatModifierRaid15M_Boss_Health;
extern float StatModifierRaid15M_Boss_Mana;
extern float StatModifierRaid15M_Boss_Armor;
extern float StatModifierRaid15M_Boss_Damage;
extern float StatModifierRaid15M_Boss_CCDuration;
extern float StatModifierRaid40M_Boss_Damage;
extern float StatModifierRaid20M_Boss_Global;
extern float StatModifierRaid20M_Boss_Health;
extern float StatModifierRaid20M_Boss_Mana;
extern float StatModifierRaid20M_Boss_Armor;
extern float StatModifierRaid20M_Boss_Damage;
extern float StatModifierRaid20M_Boss_CCDuration;
extern float StatModifierRaid25M_Boss_Global;
extern float StatModifierRaid25M_Boss_Health;
extern float StatModifierRaid25M_Boss_Mana;
extern float StatModifierRaid25M_Boss_Armor;
extern float StatModifierRaid25M_Boss_Damage;
extern float StatModifierRaid25M_Boss_CCDuration;
extern float StatModifierRaid25MHeroic_Boss_Global;
extern float StatModifierRaid25MHeroic_Boss_Health;
extern float StatModifierRaid25MHeroic_Boss_Mana;
extern float StatModifierRaid25MHeroic_Boss_Armor;
extern float StatModifierRaid25MHeroic_Boss_Damage;
extern float StatModifierRaid25MHeroic_Boss_CCDuration;
extern float StatModifierRaid40M_Boss_Global;
extern float StatModifierRaid40M_Boss_Health;
extern float StatModifierRaid40M_Boss_Mana;
extern float StatModifierRaid40M_Boss_Armor;
extern float StatModifierRaid40M_Boss_CCDuration;
#endif
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_CREATURE_INFO_H
#define __AB_CREATURE_INFO_H
#include "AutoBalance.h"
#include "Creature.h"
#include "DataMap.h"
class AutoBalanceCreatureInfo : public DataMap::Base
{
public:
AutoBalanceCreatureInfo() {}
uint64_t mapConfigTime = 1; // The last map config time that this creature was updated
uint32 instancePlayerCount = 0; // The number of players this creature has been scaled for
uint8 selectedLevel = 0; // The level that this creature should be set to
float DamageMultiplier = 1.0f; // Per-player damage multiplier (no level scaling)
float ScaledDamageMultiplier = 1.0f; // Per-player and level scaling damage multiplier
float HealthMultiplier = 1.0f; // Per-player health multiplier (no level scaling)
float ScaledHealthMultiplier = 1.0f; // Per-player and level scaling health multiplier
float ManaMultiplier = 1.0f; // Per-player mana multiplier (no level scaling)
float ScaledManaMultiplier = 1.0f; // Per-player and level scaling mana multiplier
float ArmorMultiplier = 1.0f; // Per-player armor multiplier (no level scaling)
float ScaledArmorMultiplier = 1.0f; // Per-player and level scaling armor multiplier
float CCDurationMultiplier = 1.0f; // Per-player crowd control duration multiplier (level scaling doesn't affect this)
float XPModifier = 1.0f; // Per-player XP modifier (level scaling provided by normal XP distribution)
float MoneyModifier = 1.0f; // Per-player money modifier (no level scaling)
uint8 UnmodifiedLevel = 0; // Original level of the creature as determined by the game
bool isActive = false; // Whether or not the current creature is affecting map stats. May change as conditions change.
bool wasAliveNowDead = false; // Whether or not the creature was alive and is now dead
bool isInCreatureList = false; // Whether or not the creature is in the map's creature list
bool isBrandNew = false; // Whether or not the creature is brand new to the map (hasn't been added to the world yet)
bool neverLevelScale = false; // Whether or not the creature should never be level scaled (can still be player scaled)
uint32 initialMaxHealth = 0; // Stored max health value to be applied just before being added to the world
// creature->IsSummon() // Whether or not the creature is a summon
Creature* summoner = nullptr; // The creature that summoned this creature
std::string summonerName = ""; // The name of the creature that summoned this creature
uint8 summonerLevel = 0; // The level of the creature that summoned this creature
bool isCloneOfSummoner = false; // Whether or not the creature is a clone of its summoner
Relevance relevance = AUTOBALANCE_RELEVANCE_UNCHECKED; // Whether or not the creature is relevant for scaling
};
#endif
@@ -0,0 +1,176 @@
#include "ABGameObjectScript.h"
#include "ABConfig.h"
#include "ABMapInfo.h"
#include "ABUtils.h"
void AutoBalance_GameObjectScript::OnGameObjectModifyHealth(GameObject* target, Unit* source, int32& amount, SpellInfo const* spellInfo)
{
// uncomment to debug this hook
bool _debug_damage_and_healing = (source && target && (source->GetTypeId() == TYPEID_PLAYER || source->IsControlledByPlayer()));
if (_debug_damage_and_healing)
_Debug_Output("OnGameObjectModifyHealth", target, source, amount, "BEFORE:", spellInfo->SpellName[0], spellInfo->Id);
// modify the amount
amount = _Modify_GameObject_Damage_Healing(target, source, amount, spellInfo);
if (_debug_damage_and_healing)
_Debug_Output("OnGameObjectModifyHealth", target, source, amount, "AFTER:", spellInfo->SpellName[0], spellInfo->Id);
}
void AutoBalance_GameObjectScript::_Debug_Output(std::string function_name, GameObject* target, Unit* source, int32 amount, std::string prefix, std::string spell_name, uint32 spell_id)
{
if (target && source && amount)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::{}: {} {} {} {} ({} - {})",
function_name,
prefix,
source->GetName(),
amount,
target->GetName(),
spell_name,
spell_id
);
}
else if (target && source)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::{}: {} {} 0 {} ({} - {})",
function_name,
prefix,
source->GetName(),
target->GetName(),
spell_name,
spell_id
);
}
else if (target && amount)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::{}: {} ?? {} {} ({} - {})",
function_name,
prefix,
amount,
target->GetName(),
spell_name,
spell_id
);
}
else if (target)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::{}: {} ?? ?? {} ({} - {})",
function_name,
prefix,
target->GetName(),
spell_name,
spell_id
);
}
else
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::{}: {} W? T? F? ({} - {})",
function_name,
prefix,
spell_name,
spell_id
);
}
}
int32 AutoBalance_GameObjectScript::_Modify_GameObject_Damage_Healing(GameObject* target, Unit* source, int32 amount, SpellInfo const* spellInfo)
{
//
// Pre-flight Checks
//
// uncomment to debug this function
bool _debug_damage_and_healing = (source && target && (source->GetTypeId() == TYPEID_PLAYER || source->IsControlledByPlayer()));
// check that we're enabled globally, else return the original value
if (!EnableGlobal)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::_Modify_GameObject_Damage_Healing: EnableGlobal is false, returning original value of ({}).", amount);
return amount;
}
// make sure the target is in an instance, else return the original damage
if (!(target->GetMap()->IsDungeon()))
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::_Modify_GameObject_Damage_Healing: Target is not in an instance, returning original value of ({}).", amount);
return amount;
}
// make sure the target is in the world, else return the original value
if (!target->IsInWorld())
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::_Modify_GameObject_Damage_Healing: Target does not exist in the world, returning original value of ({}).", amount);
return amount;
}
// if the spell ID is in our "never modify" list, return the original value
if
(
spellInfo &&
spellInfo->Id &&
std::find
(
spellIdsToNeverModify.begin(),
spellIdsToNeverModify.end(),
spellInfo->Id
) != spellIdsToNeverModify.end()
)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Spell {}({}) is in the never modify list, returning original value of ({}).",
spellInfo->SpellName[0],
spellInfo->Id,
amount
);
return amount;
}
// get the map's info
AutoBalanceMapInfo* targetMapABInfo = GetMapInfo(target->GetMap());
// if the target's map is not enabled, return the original damage
if (!targetMapABInfo->enabled)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::_Modify_GameObject_Damage_Healing: Target's map is not enabled, returning original value of ({}).", amount);
return amount;
}
//
// Multiplier calculation
//
// calculate the new damage amount using the map's World Health Multiplier
int32 newAmount = _Calculate_Amount_For_GameObject(target, amount, targetMapABInfo->worldHealthMultiplier);
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_GameObjectScript::_Modify_GameObject_Damage_Healing: Returning modified damage: ({}) -> ({})", amount, newAmount);
return newAmount;
}
int32 AutoBalance_GameObjectScript::_Calculate_Amount_For_GameObject(GameObject* target, int32 amount, float multiplier)
{
// since it would be very complicated to reduce the real health of destructible game objects, instead we will
// adjust the damage to them as though their health were scaled. Damage will usually be dealt by vehicles and
// other non-player sources, so this effect shouldn't be as noticable as if we applied it to the player.
uint32 realMaxHealth = target->GetGOValue()->Building.MaxHealth;
uint32 scaledMaxHealth = realMaxHealth * multiplier;
float percentDamageOfScaledMaxHealth = (float)amount / (float)scaledMaxHealth;
uint32 scaledAmount = realMaxHealth * percentDamageOfScaledMaxHealth;
return scaledAmount;
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_GAME_OBJECT_SCRIPT_H
#define __AB_GAME_OBJECT_SCRIPT_H
#include "ScriptMgr.h"
#include "SpellInfo.h"
#include "Unit.h"
class AutoBalance_GameObjectScript : public AllGameObjectScript
{
public:
AutoBalance_GameObjectScript()
: AllGameObjectScript("AutoBalance_GameObjectScript")
{}
void OnGameObjectModifyHealth(GameObject* target, Unit* source, int32& amount, SpellInfo const* spellInfo) override;
private:
[[maybe_unused]] bool _debug_damage_and_healing = false; // defaults to false, overwritten in each function
void _Debug_Output(std::string function_name, GameObject* target, Unit* source, int32 amount, std::string prefix = "", std::string spell_name = "Unknown Spell", uint32 spell_id = 0);
int32 _Modify_GameObject_Damage_Healing(GameObject* target, Unit* source, int32 amount, SpellInfo const* spellInfo);
int32 _Calculate_Amount_For_GameObject(GameObject* target, int32 amount, float multiplier);
};
#endif
@@ -0,0 +1,45 @@
#include "ABGlobalScript.h"
#include "ABConfig.h"
#include "ABMapInfo.h"
#include "ABUtils.h"
void AutoBalance_GlobalScript::OnAfterUpdateEncounterState(Map* map, EncounterCreditType type, uint32 /*creditEntry*/, Unit* /*source*/, Difficulty /*difficulty_fixed*/, DungeonEncounterList const* /*encounters*/, uint32 /*dungeonCompleted*/, bool updated)
{
//if (!dungeonCompleted)
// return;
if (!rewardEnabled || !updated)
return;
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
if (mapABInfo->adjustedPlayerCount < MinPlayerReward)
return;
// skip if it's not a pre-wotlk dungeon/raid and if it's not scaled
if (!LevelScaling || mapABInfo->mapLevel <= 70 || mapABInfo->lfgMinLevel <= 70
// skip when not in dungeon or not kill credit
|| type != ENCOUNTER_CREDIT_KILL_CREATURE || !map->IsDungeon())
return;
Map::PlayerList const& playerList = map->GetPlayers();
if (playerList.IsEmpty())
return;
uint32 reward = map->ToInstanceMap()->GetMaxPlayers() > 5 ? rewardRaid : rewardDungeon;
if (!reward)
return;
//instanceStart=0, endTime;
uint8 difficulty = map->GetDifficulty();
for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr)
{
if (!itr->GetSource() || itr->GetSource()->IsGameMaster() || itr->GetSource()->GetLevel() < DEFAULT_MAX_LEVEL)
continue;
itr->GetSource()->AddItem(reward, 1 + difficulty); // difficulty boost
}
}
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_GLOBAL_SCRIPT_H
#define __AB_GLOBAL_SCRIPT_H
#include "ScriptMgr.h"
class AutoBalance_GlobalScript : public GlobalScript {
public:
AutoBalance_GlobalScript() : GlobalScript("AutoBalance_GlobalScript", {
GLOBALHOOK_ON_AFTER_UPDATE_ENCOUNTER_STATE
}) { }
void OnAfterUpdateEncounterState(Map* map, EncounterCreditType type, uint32 creditEntry, Unit* source, Difficulty difficulty_fixed, DungeonEncounterList const* encounters, uint32 dungeonCompleted, bool updated) override;
};
#endif /* __AB_GLOBAL_SCRIPT_H */
@@ -0,0 +1,22 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_INFLECTION_POINT_SETTINGS_H
#define __AB_INFLECTION_POINT_SETTINGS_H
#include "DataMap.h"
class AutoBalanceInflectionPointSettings : public DataMap::Base
{
public:
AutoBalanceInflectionPointSettings() {}
AutoBalanceInflectionPointSettings(float value, float curveFloor, float curveCeiling) :
value(value), curveFloor(curveFloor), curveCeiling(curveCeiling) {}
float value = 0.5;
float curveFloor = 0.0;
float curveCeiling = 1.0;
};
#endif
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_LEVEL_SCALING_DYNAMIC_LEVEL_SETTINGS_H
#define __AB_LEVEL_SCALING_DYNAMIC_LEVEL_SETTINGS_H
#include "DataMap.h"
class AutoBalanceLevelScalingDynamicLevelSettings : public DataMap::Base
{
public:
AutoBalanceLevelScalingDynamicLevelSettings() {}
AutoBalanceLevelScalingDynamicLevelSettings(int skipHigher, int skipLower, int ceiling, int floor) :
skipHigher(skipHigher), skipLower(skipLower), ceiling(ceiling), floor(floor) {}
int skipHigher = 0;
int skipLower = 0;
int ceiling = 1;
int floor = 1;
};
#endif
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_MAP_INFO_H
#define __AB_MAP_INFO_H
#include "Creature.h"
#include "DataMap.h"
#include "Player.h"
#include <vector>
class AutoBalanceMapInfo : public DataMap::Base
{
public:
AutoBalanceMapInfo() {}
std::vector<Creature*> allMapCreatures; // All creatures in the map, active and non-active
std::vector<Player*> allMapPlayers; // All players that are currently in the map
bool enabled = false; // Should AutoBalance make any changes to this map or its creatures?
uint64_t globalConfigTime = 1; // The last global config time that this map was updated
uint64_t mapConfigTime = 1; // The last map config time that this map was updated
uint8 playerCount = 0; // The actual number of non-GM players in the map
uint8 adjustedPlayerCount = 0; // The currently difficulty level expressed as number of players
uint8 minPlayers = 1; // Will be set by the config
uint8 mapLevel = 0; // Calculated from the avgCreatureLevel
uint8 lowestPlayerLevel = 0; // The lowest-level player in the map
uint8 highestPlayerLevel = 0; // The highest-level player in the map
uint8 lfgMinLevel = 0; // The minimum level for the map according to LFG
uint8 lfgTargetLevel = 0; // The target level for the map according to LFG
uint8 lfgMaxLevel = 0; // The maximum level for the map according to LFG
uint8 worldMultiplierTargetLevel = 0; // The level of the pseudo-creature that the world modifiers scale to
float worldDamageHealingMultiplier = 1.0f; // The damage/healing multiplier for the world (where source isn't an enemy creature)
float scaledWorldDamageHealingMultiplier = 1.0f; // The damage/healing multiplier for the world (where source isn't an enemy creature)
float worldHealthMultiplier = 1.0f; // The "health" multiplier for any destructible buildings in the map
bool combatLocked = false; // Whether or not the map is combat locked
bool combatLockTripped = false; // Set to true when combat locking was needed during this current combat (some tried to leave)
uint8 combatLockMinPlayers = 0; // The instance cannot be set to less than this number of players until combat ends
uint8 highestCreatureLevel = 0; // The highest-level creature in the map
uint8 lowestCreatureLevel = 0; // The lowest-level creature in the map
float avgCreatureLevel = 0; // The average level of all active creatures in the map (continuously updated)
uint32 activeCreatureCount = 0; // The number of creatures in the map that are included in the map's stats (not necessarily alive)
bool isLevelScalingEnabled = false; // Whether level scaling is enabled on this map
uint8 levelScalingSkipHigherLevels = 0; // Used to determine if this map should scale or not
uint8 levelScalingSkipLowerLevels = 0; // Used to determine if this map should scale or not
uint8 levelScalingDynamicCeiling = 0; // How many levels MORE than the highestPlayerLevel creature should be scaled to
uint8 levelScalingDynamicFloor = 0; // How many levels LESS than the highestPlayerLevel creature should be scaled to
uint8 prevMapLevel = 0; // Used to reduce calculations when they are not necessary
bool initialized = false; // Whether or not the map has been initialized
};
#endif
@@ -0,0 +1,11 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#include "ABModuleScript.h"
ABModuleScript::ABModuleScript(const char* name)
: ModuleScript(name)
{
ScriptRegistry<ABModuleScript>::AddScript(this);
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_MODULE_SCRIPT_H
#define __AB_MODULE_SCRIPT_H
#include "Creature.h"
#include "ScriptMgr.h"
/*
* Dedicated hooks for Autobalance Module
* Can be used to extend/customize this system
*/
class ABModuleScript : public ModuleScript
{
protected:
ABModuleScript(const char* name);
public:
virtual bool OnBeforeModifyAttributes(Creature* /*creature*/, uint32& /*instancePlayerCount*/) { return true; }
virtual bool OnAfterDefaultMultiplier(Creature* /*creature*/, float& /*defaultMultiplier*/) { return true; }
virtual bool OnBeforeUpdateStats (Creature* /*creature*/, uint32& /*scaledHealth*/, uint32& /*scaledMana*/, float& /*damageMultiplier*/, uint32& /*newBaseArmor*/) { return true; }
};
template class ScriptRegistry<ABModuleScript>;
#endif
@@ -0,0 +1,242 @@
#include <string>
#include "ABConfig.h"
#include "ABCreatureInfo.h"
#include "ABMapInfo.h"
#include "ABPlayerScript.h"
#include "ABUtils.h"
#include "Chat.h"
#include "Message.h"
void AutoBalance_PlayerScript::OnPlayerLogin(Player* Player)
{
if (EnableGlobal && Announcement)
ChatHandler(Player->GetSession()).SendSysMessage("This server is running the |cff4CFF00AutoBalance |rmodule.");
}
void AutoBalance_PlayerScript::OnPlayerLevelChanged(Player* player, uint8 oldlevel)
{
LOG_DEBUG("module.AutoBalance", "AutoBalance:: ------------------------------------------------");
LOG_DEBUG("module.AutoBalance", "AutoBalance_PlayerScript::OnLevelChanged: {} has leveled ({}->{})", player->GetName(), oldlevel, player->GetLevel());
if (!player || player->IsGameMaster())
return;
Map* map = player->GetMap();
if (!map || !map->IsDungeon())
return;
// update the map's player stats
UpdateMapPlayerStats(map);
// schedule all creatures for an update
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
mapABInfo->mapConfigTime = GetCurrentConfigTime();
}
void AutoBalance_PlayerScript::OnPlayerGiveXP(Player* player, uint32& amount, Unit* victim, uint8 /*xpSource*/)
{
Map* map = player->GetMap();
// If this isn't a dungeon, make no changes
if (!map->IsDungeon() || !map->GetInstanceId() || !victim)
return;
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
if (victim && RewardScalingXP && mapABInfo->enabled)
{
Map* map = player->GetMap();
AutoBalanceCreatureInfo* creatureABInfo = victim->CustomData.GetDefault<AutoBalanceCreatureInfo>("AutoBalanceCreatureInfo");
if (map->IsDungeon())
{
if (RewardScalingMethod == AUTOBALANCE_SCALING_DYNAMIC)
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_PlayerScript::OnGiveXP: Distributing XP from '{}' to '{}' in dynamic mode - {}->{}",
victim->GetName(), player->GetName(), amount, uint32(amount * creatureABInfo->XPModifier));
amount = uint32(amount * creatureABInfo->XPModifier);
}
else if (RewardScalingMethod == AUTOBALANCE_SCALING_FIXED)
{
// Ensure that the players always get the same XP, even when entering the dungeon alone
auto maxPlayerCount = map->ToInstanceMap()->GetMaxPlayers();
auto currentPlayerCount = mapABInfo->playerCount;
LOG_DEBUG("module.AutoBalance", "AutoBalance_PlayerScript::OnGiveXP: Distributing XP from '{}' to '{}' in fixed mode - {}->{}",
victim->GetName(), player->GetName(), amount, uint32(amount * creatureABInfo->XPModifier * ((float)currentPlayerCount / maxPlayerCount)));
amount = uint32(amount * creatureABInfo->XPModifier * ((float)currentPlayerCount / maxPlayerCount));
}
}
}
}
void AutoBalance_PlayerScript::OnPlayerBeforeLootMoney(Player* player, Loot* loot)
{
Map* map = player->GetMap();
// If this isn't a dungeon, make no changes
if (!map->IsDungeon())
return;
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
ObjectGuid sourceGuid = loot->sourceWorldObjectGUID;
if (mapABInfo->enabled && RewardScalingMoney)
{
// if the loot source is a creature, honor the modifiers for that creature
if (sourceGuid.IsCreature())
{
Creature* sourceCreature = ObjectAccessor::GetCreature(*player, sourceGuid);
AutoBalanceCreatureInfo* creatureABInfo = sourceCreature->CustomData.GetDefault<AutoBalanceCreatureInfo>("AutoBalanceCreatureInfo");
// Dynamic Mode
if (RewardScalingMethod == AUTOBALANCE_SCALING_DYNAMIC)
{
LOG_DEBUG("module.AutoBalance", "AutoBalance_PlayerScript::OnBeforeLootMoney: Distributing money from '{}' in dynamic mode - {}->{}",
sourceCreature->GetName(), loot->gold, uint32(loot->gold * creatureABInfo->MoneyModifier));
loot->gold = uint32(loot->gold * creatureABInfo->MoneyModifier);
}
// Fixed Mode
else if (RewardScalingMethod == AUTOBALANCE_SCALING_FIXED)
{
// Ensure that the players always get the same money, even when entering the dungeon alone
auto maxPlayerCount = map->ToInstanceMap()->GetMaxPlayers();
auto currentPlayerCount = mapABInfo->playerCount;
LOG_DEBUG("module.AutoBalance", "AutoBalance_PlayerScript::OnBeforeLootMoney: Distributing money from '{}' in fixed mode - {}->{}",
sourceCreature->GetName(), loot->gold, uint32(loot->gold * creatureABInfo->MoneyModifier * ((float)currentPlayerCount / maxPlayerCount)));
loot->gold = uint32(loot->gold * creatureABInfo->MoneyModifier * ((float)currentPlayerCount / maxPlayerCount));
}
}
// for all other loot sources, just distribute in Fixed mode as though the instance was full
else
{
auto maxPlayerCount = map->ToInstanceMap()->GetMaxPlayers();
auto currentPlayerCount = mapABInfo->playerCount;
LOG_DEBUG("module.AutoBalance", "AutoBalance_PlayerScript::OnBeforeLootMoney: Distributing money from a non-creature in fixed mode - {}->{}",
loot->gold, uint32(loot->gold * ((float)currentPlayerCount / maxPlayerCount)));
loot->gold = uint32(loot->gold * ((float)currentPlayerCount / maxPlayerCount));
}
}
}
void AutoBalance_PlayerScript::OnPlayerEnterCombat(Player* player, Unit* /*enemy*/)
{
// if the player or their map is gone, return
if (!player || !player->GetMap())
return;
Map* map = player->GetMap();
// If this isn't a dungeon, no work to do
if (!map || !map->IsDungeon())
return;
LOG_DEBUG("module.AutoBalance_CombatLocking", "AutoBalance_PlayerScript::OnPlayerEnterCombat: {} enters combat.", player->GetName());
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
// if this map isn't enabled, no work to do
if (!mapABInfo->enabled)
return;
// lock the current map
if (!mapABInfo->combatLocked)
{
mapABInfo->combatLocked = true;
mapABInfo->combatLockMinPlayers = mapABInfo->playerCount;
LOG_DEBUG("module.AutoBalance_CombatLocking", "AutoBalance_PlayerScript::OnPlayerEnterCombat: Map {} ({}{}) | Locking difficulty to no less than ({}) as {} enters combat.",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : "",
mapABInfo->combatLockMinPlayers,
player->GetName()
);
}
}
void AutoBalance_PlayerScript::OnPlayerLeaveCombat(Player* player)
{
// if the player or their map is gone, return
if (!player || !player->GetMap())
return;
Map* map = player->GetMap();
// If this isn't a dungeon, no work to do
if (!map || !map->IsDungeon())
return;
// this hook can get called even if the player isn't in combat
// I believe this happens whenever AC attempts to remove combat, but it doesn't check to see if the player is in combat first
// unfortunately, `player->IsInCombat()` doesn't work here
LOG_DEBUG("module.AutoBalance_CombatLocking", "AutoBalance_PlayerScript::OnPlayerLeaveCombat: {} leaves (or wasn't in) combat.", player->GetName());
AutoBalanceMapInfo* mapABInfo = GetMapInfo(map);
// if this map isn't enabled, no work to do
if (!mapABInfo->enabled)
return;
// check to see if any of the other players are in combat
bool anyPlayersInCombat = false;
for (auto player : mapABInfo->allMapPlayers)
{
if (player && player->IsInCombat())
{
anyPlayersInCombat = true;
LOG_DEBUG("module.AutoBalance_CombatLocking", "AutoBalance_PlayerScript::OnPlayerLeaveCombat: Map {} ({}{}) | Player {} (and potentially others) are still in combat.",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : "",
player->GetName()
);
break;
}
}
auto locale = player->GetSession()->GetSessionDbLocaleIndex();
// if no players are in combat, unlock the map
if (!anyPlayersInCombat && mapABInfo->combatLocked)
{
mapABInfo->combatLocked = false;
mapABInfo->combatLockMinPlayers = 0;
LOG_DEBUG("module.AutoBalance_CombatLocking", "AutoBalance_PlayerScript::OnPlayerLeaveCombat: Map {} ({}{}) | Unlocking difficulty as {} leaves combat.",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : "",
player->GetName()
);
// if the combat lock needed to be used, notify the players of it lifting
if (mapABInfo->combatLockTripped)
{
for (auto player : mapABInfo->allMapPlayers)
{
if (player && player->GetSession())
ChatHandler(player->GetSession()).PSendSysMessage(ABGetLocaleText(locale, "leaving_instance_combat_change").c_str());
}
}
// if the number of players changed while combat was in progress, schedule the map for an update
if (mapABInfo->combatLockTripped && mapABInfo->playerCount != mapABInfo->combatLockMinPlayers)
{
mapABInfo->mapConfigTime = 1;
LOG_DEBUG("module.AutoBalance_CombatLocking", "AutoBalance_PlayerScript::OnPlayerLeaveCombat: Map {} ({}{}) | Reset map config time to ({}).",
map->GetMapName(),
map->GetId(),
map->GetInstanceId() ? "-" + std::to_string(map->GetInstanceId()) : "",
mapABInfo->mapConfigTime
);
mapABInfo->combatLockTripped = false;
}
}
}
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_PLAYER_SCRIPT_H
#define __AB_PLAYER_SCRIPT_H
#include "Player.h"
#include "ScriptMgr.h"
#include "Unit.h"
class AutoBalance_PlayerScript : public PlayerScript
{
public:
AutoBalance_PlayerScript()
: PlayerScript("AutoBalance_PlayerScript")
{
}
void OnPlayerLogin(Player* Player) override;
virtual void OnPlayerLevelChanged(Player* player, uint8 oldlevel) override;
void OnPlayerGiveXP(Player* player, uint32& amount, Unit* victim, uint8 xpSource) override;
void OnPlayerBeforeLootMoney(Player* player, Loot* loot) override;
virtual void OnPlayerEnterCombat(Player* player, Unit* enemy) override;
virtual void OnPlayerLeaveCombat(Player* player) override;
};
#endif /* __AB_PLAYER_SCRIPT_H */
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#include "ABModuleScript.h"
#include "ABScriptMgr.h"
#include "ScriptMgr.h"
#include "ScriptMgrMacros.h"
ABScriptMgr* ABScriptMgr::instance()
{
static ABScriptMgr instance;
return &instance;
}
bool ABScriptMgr::OnBeforeModifyAttributes(Creature* creature, uint32& instancePlayerCount)
{
auto ret = IsValidBoolScript<ABModuleScript>([&](ABModuleScript* script)
{
return !script->OnBeforeModifyAttributes(creature, instancePlayerCount);
});
if (ret && *ret)
return false;
return true;
}
bool ABScriptMgr::OnAfterDefaultMultiplier(Creature* creature, float& defaultMultiplier)
{
auto ret = IsValidBoolScript<ABModuleScript>([&](ABModuleScript* script)
{
return !script->OnAfterDefaultMultiplier(creature, defaultMultiplier);
});
if (ret && *ret)
return false;
return true;
}
bool ABScriptMgr::OnBeforeUpdateStats(Creature* creature, uint32& scaledHealth, uint32& scaledMana, float& damageMultiplier, uint32& newBaseArmor)
{
auto ret = IsValidBoolScript<ABModuleScript>([&](ABModuleScript* script)
{
return !script->OnBeforeUpdateStats(creature, scaledHealth, scaledMana, damageMultiplier, newBaseArmor);
});
if (ret && *ret)
return false;
return true;
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_SCRIPT_MGR_H
#define __AB_SCRIPT_MGR_H
#include "Creature.h"
#include "ScriptMgr.h"
// Manages registration, loading, and execution of scripts.
class ABScriptMgr
{
public: /* Initialization */
static ABScriptMgr* instance();
// Called at the start of ModifyCreatureAttributes method.
// It can be used to add some condition to skip autobalancing system for example.
bool OnBeforeModifyAttributes(Creature* creature, uint32 & instancePlayerCount);
// Called right after default multiplier has been set, you can use it to change.
// Current scaling formula based on number of players or just skip modifications
bool OnAfterDefaultMultiplier(Creature* creature, float &defaultMultiplier);
// Called before change creature values, to tune some values or skip modifications.
bool OnBeforeUpdateStats (Creature* creature, uint32 &scaledHealth, uint32 &scaledMana, float &damageMultiplier, uint32 &newBaseArmor);
};
#define sABScriptMgr ABScriptMgr::instance()
#endif
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_MODULE_STAT_MODIFIERS_H
#define __AB_MODULE_STAT_MODIFIERS_H
#include "DataMap.h"
class AutoBalanceStatModifiers : public DataMap::Base
{
public:
AutoBalanceStatModifiers() {}
AutoBalanceStatModifiers(float global, float health, float mana, float armor, float damage, float ccduration) :
global(global), health(health), mana(mana), armor(armor), damage(damage), ccduration(ccduration) {}
float global = 1.0;
float health = 1.0;
float mana = 1.0;
float armor = 1.0;
float damage = 1.0;
float ccduration = 1.0;
};
#endif
@@ -0,0 +1,557 @@
#include "ABUnitScript.h"
#include "ABConfig.h"
#include "ABCreatureInfo.h"
#include "ABMapInfo.h"
#include "ABUtils.h"
void AutoBalance_UnitScript::ModifyPeriodicDamageAurasTick(Unit* target, Unit* source, uint32& amount, SpellInfo const* spellInfo)
{
// if the spell is negative (damage), we need to flip the sign
// if the spell is positive (healing or other) we keep it the same
int32 adjustedAmount = !spellInfo->IsPositive() ? amount * -1 : amount;
// only debug if the source or target is a player
bool _debug_damage_and_healing = ((source && (source->GetTypeId() == TYPEID_PLAYER || source->IsControlledByPlayer())) || (target && target->GetTypeId() == TYPEID_PLAYER));
_debug_damage_and_healing = (source && source->GetMap()->GetInstanceId());
if (_debug_damage_and_healing)
_Debug_Output("ModifyPeriodicDamageAurasTick", target, source, adjustedAmount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_BEFORE, spellInfo->SpellName[0], spellInfo->Id);
// set amount to the absolute value of the function call
// the provided amount doesn't indicate whether it's a positive or negative value
adjustedAmount = _Modify_Damage_Healing(target, source, adjustedAmount, spellInfo);
amount = abs(adjustedAmount);
if (_debug_damage_and_healing)
_Debug_Output("ModifyPeriodicDamageAurasTick", target, source, adjustedAmount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_AFTER, spellInfo->SpellName[0], spellInfo->Id);
}
void AutoBalance_UnitScript::ModifySpellDamageTaken(Unit* target, Unit* source, int32& amount, SpellInfo const* spellInfo)
{
// if the spell is negative (damage), we need to flip the sign to negative
// if the spell is positive (healing or other) we keep it the same (positive)
int32 adjustedAmount = !spellInfo->IsPositive() ? amount * -1 : amount;
// only debug if the source or target is a player
bool _debug_damage_and_healing = ((source && (source->GetTypeId() == TYPEID_PLAYER || source->IsControlledByPlayer())) || (target && target->GetTypeId() == TYPEID_PLAYER));
_debug_damage_and_healing = (source && source->GetMap()->GetInstanceId());
if (_debug_damage_and_healing)
_Debug_Output("ModifySpellDamageTaken", target, source, adjustedAmount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_BEFORE, spellInfo->SpellName[0], spellInfo->Id);
// set amount to the absolute value of the function call
// the provided amount doesn't indicate whether it's a positive or negative value
adjustedAmount = _Modify_Damage_Healing(target, source, adjustedAmount, spellInfo);
amount = abs(adjustedAmount);
if (_debug_damage_and_healing)
_Debug_Output("ModifySpellDamageTaken", target, source, adjustedAmount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_AFTER, spellInfo->SpellName[0], spellInfo->Id);
}
void AutoBalance_UnitScript::ModifyMeleeDamage(Unit* target, Unit* source, uint32& amount)
{
// melee damage is always negative, so we need to flip the sign to negative
int32 adjustedAmount = amount * -1;
// only debug if the source or target is a player
bool _debug_damage_and_healing = ((source && (source->GetTypeId() == TYPEID_PLAYER || source->IsControlledByPlayer())) || (target && target->GetTypeId() == TYPEID_PLAYER));
_debug_damage_and_healing = (source && source->GetMap()->GetInstanceId());
if (_debug_damage_and_healing)
_Debug_Output("ModifyMeleeDamage", target, source, adjustedAmount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_BEFORE, "Melee");
// set amount to the absolute value of the function call
adjustedAmount = _Modify_Damage_Healing(target, source, adjustedAmount);
amount = abs(adjustedAmount);
if (_debug_damage_and_healing)
_Debug_Output("ModifyMeleeDamage", target, source, adjustedAmount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_AFTER, "Melee");
}
void AutoBalance_UnitScript::ModifyHealReceived(Unit* target, Unit* source, uint32& amount, SpellInfo const* spellInfo)
{
// healing is always positive, no need for any sign flip
// only debug if the source or target is a player
bool _debug_damage_and_healing = ((source && (source->GetTypeId() == TYPEID_PLAYER || source->IsControlledByPlayer())) || (target && target->GetTypeId() == TYPEID_PLAYER));
_debug_damage_and_healing = (source && source->GetMap()->GetInstanceId());
if (_debug_damage_and_healing)
_Debug_Output("ModifyHealReceived", target, source, amount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_BEFORE, spellInfo->SpellName[0], spellInfo->Id);
amount = _Modify_Damage_Healing(target, source, amount, spellInfo);
if (_debug_damage_and_healing)
_Debug_Output("ModifyHealReceived", target, source, amount, AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_AFTER, spellInfo->SpellName[0], spellInfo->Id);
}
void AutoBalance_UnitScript::OnAuraApply(Unit* unit, Aura* aura)
{
// only debug if the source or target is a player
bool _debug_damage_and_healing = (unit && unit->GetTypeId() == TYPEID_PLAYER);
_debug_damage_and_healing = (unit && unit->GetMap()->GetInstanceId());
// Only if this aura has a duration
if (aura && (aura->GetDuration() > 0 || aura->GetMaxDuration() > 0))
{
uint32 auraDuration = _Modifier_CCDuration(unit, aura->GetCaster(), aura);
// only update if we decided to change it
if (auraDuration != (float)aura->GetDuration())
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::OnAuraApply(): Spell '{}' had it's duration adjusted ({}->{}).",
aura->GetSpellInfo()->SpellName[0],
aura->GetMaxDuration() / 1000,
auraDuration / 1000
);
aura->SetMaxDuration(auraDuration);
aura->SetDuration(auraDuration);
}
}
}
void AutoBalance_UnitScript::_Debug_Output(std::string function_name, Unit* target, Unit* source, int32 amount, Damage_Healing_Debug_Phase phase, std::string spell_name, uint32 spell_id)
{
if (phase == AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_BEFORE)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance:: ------------------------------------------------");
}
if (target && source && amount)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::{}: {}: {}{} {} {}{} with {}{} for ({})",
function_name,
phase ? "AFTER" : "BEFORE",
source->GetName(),
source->GetEntry() ? " (" + std::to_string(source->GetEntry()) + ")" : "",
amount > 0 ? "heals" : "damages",
target->GetName(),
target->GetEntry() ? " (" + std::to_string(target->GetEntry()) + ")" : "",
spell_name,
spell_id ? " (" + std::to_string(spell_id) + ")" : "",
amount
);
}
else if (target && source)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::{}: {}: {}{} damages {}{} with {}{} for (0)",
function_name,
phase ? "AFTER" : "BEFORE",
source->GetName(),
source->GetEntry() ? " (" + std::to_string(source->GetEntry()) + ")" : "",
target->GetName(),
target->GetEntry() ? " (" + std::to_string(target->GetEntry()) + ")" : "",
spell_name,
spell_id ? " (" + std::to_string(spell_id) + ")" : ""
);
}
else if (target && amount)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::{}: {}: ?? {} {}{} with {}{} for ({})",
function_name,
phase ? "AFTER" : "BEFORE",
amount > 0 ? "heals" : "damages",
target->GetName(),
target->GetEntry() ? " (" + std::to_string(target->GetEntry()) + ")" : "",
spell_name,
spell_id ? " (" + std::to_string(spell_id) + ")" : "",
amount
);
}
else if (target)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::{}: {}: ?? affects {}{} with {}{}",
function_name,
phase ? "AFTER" : "BEFORE",
target->GetName(),
target->GetEntry() ? " (" + std::to_string(target->GetEntry()) + ")" : "",
spell_name,
spell_id ? " (" + std::to_string(spell_id) + ")" : ""
);
}
else
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::{}: {}: W? T? F? with {}{}",
function_name,
phase ? "AFTER" : "BEFORE",
spell_name,
spell_id ? " (" + std::to_string(spell_id) + ")" : ""
);
}
}
int32 AutoBalance_UnitScript::_Modify_Damage_Healing(Unit* target, Unit* source, int32 amount, SpellInfo const* spellInfo)
{
//
// Pre-flight Checks
//
// only debug if the source or target is a player
bool _debug_damage_and_healing = ((source && (source->GetTypeId() == TYPEID_PLAYER || source->IsControlledByPlayer())) || (target && target->GetTypeId() == TYPEID_PLAYER));
_debug_damage_and_healing = (source && source->GetMap()->GetInstanceId());
// check that we're enabled globally, else return the original value
if (!EnableGlobal)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: EnableGlobal is false, returning original value of ({}).", amount);
return amount;
}
// if the source is gone (logged off? despawned?), use the same target and source.
// hacky, but better than crashing or having the damage go to 1.0x
if (!source)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is null, using target as source.");
source = target;
}
// make sure the source and target are in an instance, else return the original damage
if (!(source->GetMap()->IsDungeon() && target->GetMap()->IsDungeon()))
{
//if (_debug_damage_and_healing)
// LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Not in an instance, returning original value of ({}).", amount);
return amount;
}
// make sure that the source is in the world, else return the original value
if (!source->IsInWorld())
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source does not exist in the world, returning original value of ({}).", amount);
return amount;
}
// if the spell ID is in our "never modify" list, return the original value
if
(
spellInfo &&
spellInfo->Id &&
std::find
(
spellIdsToNeverModify.begin(),
spellIdsToNeverModify.end(),
spellInfo->Id
) != spellIdsToNeverModify.end()
)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Spell {}({}) is in the never modify list, returning original value of ({}).",
spellInfo->SpellName[0],
spellInfo->Id,
amount
);
return amount;
}
// get the maps' info
AutoBalanceMapInfo* sourceMapABInfo = GetMapInfo(source->GetMap());
AutoBalanceMapInfo* targetMapABInfo = GetMapInfo(target->GetMap());
// if either the target or the source's maps are not enabled, return the original damage
if (!sourceMapABInfo->enabled || !targetMapABInfo->enabled)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source or Target's map is not enabled, returning original value of ({}).", amount);
return amount;
}
//
// Source and Target Checking
//
// if the source is a player and they are healing themselves, return the original value
if (source->GetTypeId() == TYPEID_PLAYER && source->GetGUID() == target->GetGUID() && amount >= 0)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a player that is self-healing, returning original value of ({}).", amount);
return amount;
}
// if the source is a player and they are damaging themselves, log to debug but continue
else if (source->GetTypeId() == TYPEID_PLAYER && source->GetGUID() == target->GetGUID() && amount < 0)
{
// if the spell used is in our list of spells to ignore, return the original value
if
(
spellInfo &&
spellInfo->Id &&
std::find
(
spellIdsThatSpendPlayerHealth.begin(),
spellIdsThatSpendPlayerHealth.end(),
spellInfo->Id
) != spellIdsThatSpendPlayerHealth.end()
)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a player that is self-damaging with a spell that is ignored, returning original value of ({}).", amount);
return amount;
}
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a player that is self-damaging, continuing.");
}
// if the source is a player and they are damaging unit that is friendly, log to debug but continue
else if (source->GetTypeId() == TYPEID_PLAYER && target->IsFriendlyTo(source) && amount < 0)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a player that is damaging a friendly unit, continuing.");
}
// if the source is a player under any other condition, return the original value
else if (source->GetTypeId() == TYPEID_PLAYER)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is an enemy player, returning original value of ({}).", amount);
return amount;
}
// if the creature is attacking itself with an aura with effect type SPELL_AURA_SHARE_DAMAGE_PCT, return the orginal damage
else if
(
source->GetTypeId() == TYPEID_UNIT &&
source->GetTypeId() != TYPEID_PLAYER &&
source->GetGUID() == target->GetGUID() &&
_isAuraWithEffectType(spellInfo, SPELL_AURA_SHARE_DAMAGE_PCT)
)
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a creature that is self-damaging with an aura that shares damage, returning original value of ({}).", amount);
return amount;
}
// if the source is under the control of the player, return the original damage
// noteably, this should NOT include mind control targets
if ((source->IsHunterPet() || source->IsPet() || source->IsSummon()) && source->IsControlledByPlayer())
{
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a player-controlled pet or summon, returning original value of ({}).", amount);
return amount;
}
//
// Multiplier calculation
//
float damageMultiplier = 1.0f;
// if the source is a player AND the target is that same player AND the value is damage (negative), use the map's multiplier
if (source->GetTypeId() == TYPEID_PLAYER && source->GetGUID() == target->GetGUID() && amount < 0)
{
// if this aura damages based on a percent of the player's max health, use the un-level-scaled multiplier
if (_isAuraWithEffectType(spellInfo, SPELL_AURA_PERIODIC_DAMAGE_PERCENT))
{
damageMultiplier = sourceMapABInfo->worldDamageHealingMultiplier;
if (_debug_damage_and_healing)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Spell damage based on percent of max health. Ignore level scaling.");
LOG_DEBUG("module.AutoBalance_DamageHealingCC",
"AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a player and the target is that same player, using the map's (level-scaling ignored) multiplier: ({})",
damageMultiplier
);
}
}
else
{
damageMultiplier = sourceMapABInfo->scaledWorldDamageHealingMultiplier;
if (_debug_damage_and_healing)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC",
"AutoBalance_UnitScript::_Modify_Damage_Healing: Source is a player and the target is that same player, using the map's multiplier: ({})",
damageMultiplier
);
}
}
}
// if the target is a player AND the value is healing (positive), use the map's damage multiplier
// (player to player healing was already eliminated in the Source and Target Checking section)
else if (target->GetTypeId() == TYPEID_PLAYER && amount >= 0)
{
damageMultiplier = targetMapABInfo->scaledWorldDamageHealingMultiplier;
if (_debug_damage_and_healing)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC",
"AutoBalance_UnitScript::_Modify_Damage_Healing: A non-player is healing a player, using the map's multiplier: ({})",
damageMultiplier
);
}
}
// if the target is a player AND the source is not a creature, use the map's multiplier
else if (target->GetTypeId() == TYPEID_PLAYER && source->GetTypeId() != TYPEID_UNIT && amount < 0)
{
// if this aura damages based on a percent of the player's max health, use the un-level-scaled multiplier
if (_isAuraWithEffectType(spellInfo, SPELL_AURA_PERIODIC_DAMAGE_PERCENT))
{
damageMultiplier = targetMapABInfo->worldDamageHealingMultiplier;
if (_debug_damage_and_healing)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Spell damage based on percent of max health. Ignore level scaling.");
LOG_DEBUG("module.AutoBalance_DamageHealingCC",
"AutoBalance_UnitScript::_Modify_Damage_Healing: Target is a player and the source is not a creature, using the map's (level-scaling-ignored) multiplier: ({})",
damageMultiplier
);
}
}
else
{
damageMultiplier = targetMapABInfo->scaledWorldDamageHealingMultiplier;
if (_debug_damage_and_healing)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC",
"AutoBalance_UnitScript::_Modify_Damage_Healing: Target is a player and the source is not a creature, using the map's multiplier: ({})",
damageMultiplier
);
}
}
}
// otherwise, use the source creature's damage multiplier
else
{
// if this aura damages based on a percent of the player's max health, use the un-level-scaled multiplier
if (_isAuraWithEffectType(spellInfo, SPELL_AURA_PERIODIC_DAMAGE_PERCENT))
{
damageMultiplier = source->CustomData.GetDefault<AutoBalanceCreatureInfo>("AutoBalanceCreatureInfo")->DamageMultiplier;
if (_debug_damage_and_healing)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Spell damage based on percent of max health. Ignore level scaling.");
LOG_DEBUG("module.AutoBalance_DamageHealingCC",
"AutoBalance_UnitScript::_Modify_Damage_Healing: Using the source creature's (level-scaling ignored) damage multiplier: ({})",
damageMultiplier
);
}
}
// non percent-based, used the normal multiplier
else
{
damageMultiplier = source->CustomData.GetDefault<AutoBalanceCreatureInfo>("AutoBalanceCreatureInfo")->ScaledDamageMultiplier;
if (_debug_damage_and_healing)
{
LOG_DEBUG("module.AutoBalance_DamageHealingCC",
"AutoBalance_UnitScript::_Modify_Damage_Healing: Using the source creature's damage multiplier: ({})",
damageMultiplier
);
}
}
}
// we are good to go, return the original damage times the multiplier
if (_debug_damage_and_healing)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_Modify_Damage_Healing: Returning modified {}: ({}) * ({}) = ({})",
amount <= 0 ? "damage" : "healing",
amount,
damageMultiplier,
amount * damageMultiplier
);
return amount * damageMultiplier;
}
uint32 AutoBalance_UnitScript::_Modifier_CCDuration(Unit* target, Unit* caster, Aura* aura)
{
// store the original duration of the aura
float originalDuration = (float)aura->GetDuration();
// check that we're enabled globally, else return the original duration
if (!EnableGlobal)
return originalDuration;
// ensure that both the target and the caster are defined
if (!target || !caster)
return originalDuration;
// if the aura wasn't cast just now, don't change it
if (aura->GetDuration() != aura->GetMaxDuration())
return originalDuration;
// if the target isn't a player or the caster is a player, return the original duration
if (!target->IsPlayer() || caster->IsPlayer())
return originalDuration;
// make sure we're in an instance, else return the original duration
if (!(target->GetMap()->IsDungeon() && caster->GetMap()->IsDungeon()))
return originalDuration;
// get the current creature's CC duration multiplier
float ccDurationMultiplier = caster->CustomData.GetDefault<AutoBalanceCreatureInfo>("AutoBalanceCreatureInfo")->CCDurationMultiplier;
// if it's the default of 1.0, return the original damage
if (ccDurationMultiplier == 1)
return originalDuration;
// if the aura was cast by a pet or summon, return the original duration
if ((caster->IsHunterPet() || caster->IsPet() || caster->IsSummon()) && caster->IsControlledByPlayer())
return originalDuration;
// only if this aura is a CC
if (
aura->HasEffectType(SPELL_AURA_MOD_CHARM) ||
aura->HasEffectType(SPELL_AURA_MOD_CONFUSE) ||
aura->HasEffectType(SPELL_AURA_MOD_DISARM) ||
aura->HasEffectType(SPELL_AURA_MOD_FEAR) ||
aura->HasEffectType(SPELL_AURA_MOD_PACIFY) ||
aura->HasEffectType(SPELL_AURA_MOD_POSSESS) ||
aura->HasEffectType(SPELL_AURA_MOD_SILENCE) ||
aura->HasEffectType(SPELL_AURA_MOD_STUN) ||
aura->HasEffectType(SPELL_AURA_MOD_SPEED_SLOW_ALL)
)
{
return originalDuration * ccDurationMultiplier;
}
else
return originalDuration;
}
bool AutoBalance_UnitScript::_isAuraWithEffectType(SpellInfo const* spellInfo, AuraType auraType, bool log)
{
// if the spell is not defined, return false
if (!spellInfo)
{
if (log)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_isAuraWithEffectType: SpellInfo is null, returning false.");
return false;
}
// if the spell doesn't have any effects, return false
if (!spellInfo->GetEffects().size())
{
if (log)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_isAuraWithEffectType: SpellInfo has no effects, returning false.");
return false;
}
// iterate through the spell effects
for (SpellEffectInfo effect : spellInfo->GetEffects())
{
// if the effect is not an aura, continue to next effect
if (!effect.IsAura())
{
if (log)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_isAuraWithEffectType: SpellInfo has an effect that is not an aura, continuing to next effect.");
continue;
}
if (effect.ApplyAuraName == auraType)
{
// if the effect is an aura of the target type, return true
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_isAuraWithEffectType: SpellInfo has an aura of the target type, returning true.");
return true;
}
}
// if no aura effect of type auraType was found, return false
if (log)
LOG_DEBUG("module.AutoBalance_DamageHealingCC", "AutoBalance_UnitScript::_isAuraWithEffectType: SpellInfo has no aura of the target type, returning false.");
return false;
}
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_UNIT_SCRIPT_H
#define __AB_UNIT_SCRIPT_H
#include "AutoBalance.h"
#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellInfo.h"
class AutoBalance_UnitScript : public UnitScript
{
public:
AutoBalance_UnitScript()
: UnitScript("AutoBalance_UnitScript", true, {
UNITHOOK_MODIFY_PERIODIC_DAMAGE_AURAS_TICK,
UNITHOOK_MODIFY_SPELL_DAMAGE_TAKEN,
UNITHOOK_MODIFY_MELEE_DAMAGE,
UNITHOOK_MODIFY_HEAL_RECEIVED,
UNITHOOK_ON_AURA_APPLY
})
{
}
void ModifyPeriodicDamageAurasTick(Unit* target, Unit* source, uint32& amount, SpellInfo const* spellInfo) override;
void ModifySpellDamageTaken(Unit* target, Unit* source, int32& amount, SpellInfo const* spellInfo) override;
void ModifyMeleeDamage(Unit* target, Unit* source, uint32& amount) override;
void ModifyHealReceived(Unit* target, Unit* source, uint32& amount, SpellInfo const* spellInfo) override;
void OnAuraApply(Unit* unit, Aura* aura) override;
private:
[[maybe_unused]] bool _debug_damage_and_healing = false; // defaults to false, overwritten in each function
void _Debug_Output(std::string function_name, Unit* target, Unit* source, int32 amount, Damage_Healing_Debug_Phase phase, std::string spell_name = "Unknown Spell", uint32 spell_id = 0);
int32 _Modify_Damage_Healing(Unit* target, Unit* source, int32 amount, SpellInfo const* spellInfo = nullptr);
uint32 _Modifier_CCDuration(Unit* target, Unit* caster, Aura* aura);
bool _isAuraWithEffectType(SpellInfo const* spellInfo, AuraType auraType, bool log = false);
};
#endif /* __AB_UNIT_SCRIPT_H */
File diff suppressed because it is too large Load Diff
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_UTILS_H
#define __AB_UTILS_H
#include "ABInflectionPointSettings.h"
#include "ABLevelScalingDynamicLevelSettings.h"
#include "ABMapInfo.h"
#include "ABStatModifiers.h"
#include "AutoBalance.h"
#include "Creature.h"
#include "Map.h"
#include "SharedDefines.h"
#include <list>
#include <map>
#include <string>
void AddCreatureToMapCreatureList(Creature* creature, bool addToCreatureList = true, bool forceRecalculation = false);
void RemoveCreatureFromMapData(Creature* creature);
uint64_t GetCurrentConfigTime();
uint32 getBaseExpansionValueForLevel(const uint32 baseValues[3], uint8 targetLevel);
float getBaseExpansionValueForLevel(const float baseValues[3], uint8 targetLevel);
float getDefaultMultiplier(Map* map, AutoBalanceInflectionPointSettings inflectionPointSettings);
int GetForcedNumPlayers(int creatureId);
World_Multipliers getWorldMultiplier(Map* map, BaseValueType baseValueType);
AutoBalanceInflectionPointSettings getInflectionPointSettings(InstanceMap* instanceMap, bool isBoss = false);
void getStatModifiersDebug(Map* map, Creature* creature, std::string message);
AutoBalanceStatModifiers getStatModifiers(Map* map, Creature* creature = nullptr);
bool hasBossOverride(uint32 dungeonId);
bool hasDungeonOverride(uint32 dungeonId);
bool hasDynamicLevelOverride(uint32 dungeonId);
bool hasLevelScalingDistanceCheckOverride(uint32 dungeonId);
bool hasStatModifierBossOverride(uint32 dungeonId);
bool hasStatModifierCreatureOverride(uint32 creatureId);
bool hasStatModifierOverride(uint32 dungeonId);
bool isBossOrBossSummon(Creature* creature, bool log = false);
bool isCreatureRelevant(Creature* creature);
bool isDungeonInDisabledDungeonIds(uint32 dungeonId);
bool isDungeonInMinPlayerMap(uint32 dungeonId, bool isHeroic);
void LoadForcedCreatureIdsFromString(std::string creatureIds, int forcedPlayerCount);
std::list<uint32> LoadDisabledDungeons(std::string dungeonIdString);
std::map <uint32, uint32> LoadDistanceCheckOverrides(std::string dungeonIdString);
std::map <uint8 , AutoBalanceLevelScalingDynamicLevelSettings> LoadDynamicLevelOverrides(std::string dungeonIdString);
std::map <uint32, AutoBalanceInflectionPointSettings> LoadInflectionPointOverrides(std::string dungeonIdString);
void LoadMapSettings(Map* map);
std::map <uint32, uint8> LoadMinPlayersPerDungeonId(std::string minPlayersString);
std::map <uint32, AutoBalanceStatModifiers> LoadStatModifierOverrides(std::string dungeonIdString);
bool ShouldMapBeEnabled (Map* map);
void UpdateMapPlayerStats (Map* map);
void AddPlayerToMap(Map* map, Player* player);
bool RemovePlayerFromMap(Map* map, Player* player);
bool UpdateMapDataIfNeeded(Map* map, bool force = false);
AutoBalanceMapInfo* GetMapInfo(Map* map);
#endif
@@ -0,0 +1,509 @@
#include "ABWorldScript.h"
#include "ABConfig.h"
#include "ABUtils.h"
#include "Configuration/Config.h"
#include "Log.h"
void AutoBalance_WorldScript::OnBeforeConfigLoad(bool /*reload*/)
{
SetInitialWorldSettings();
globalConfigTime = GetCurrentConfigTime();
LOG_INFO("module.AutoBalance", "AutoBalance::OnBeforeConfigLoad: Config loaded. Global config time set to ({}).", globalConfigTime);
}
void AutoBalance_WorldScript::SetInitialWorldSettings()
{
forcedCreatureIds.clear();
disabledDungeonIds.clear();
dungeonOverrides.clear();
bossOverrides.clear();
statModifierOverrides.clear();
statModifierBossOverrides.clear();
statModifierCreatureOverrides.clear();
levelScalingDynamicLevelOverrides.clear();
levelScalingDistanceCheckOverrides.clear();
LoadForcedCreatureIdsFromString(sConfigMgr->GetOption<std::string>("AutoBalance.ForcedID40", ""), 40);
LoadForcedCreatureIdsFromString(sConfigMgr->GetOption<std::string>("AutoBalance.ForcedID25", ""), 25);
LoadForcedCreatureIdsFromString(sConfigMgr->GetOption<std::string>("AutoBalance.ForcedID10", ""), 10);
LoadForcedCreatureIdsFromString(sConfigMgr->GetOption<std::string>("AutoBalance.ForcedID5" , ""), 5);
LoadForcedCreatureIdsFromString(sConfigMgr->GetOption<std::string>("AutoBalance.ForcedID2" , ""), 2);
LoadForcedCreatureIdsFromString(sConfigMgr->GetOption<std::string>("AutoBalance.DisabledID", ""), 0);
//
// Disabled Dungeon IDs
//
disabledDungeonIds = LoadDisabledDungeons(sConfigMgr->GetOption<std::string>("AutoBalance.Disable.PerInstance", ""));
//
// Min Players
//
minPlayersNormal = sConfigMgr->GetOption<int>("AutoBalance.MinPlayers", 1);
minPlayersHeroic = sConfigMgr->GetOption<int>("AutoBalance.MinPlayers.Heroic", 1);
minPlayersRaid = sConfigMgr->GetOption<int>("AutoBalance.MinPlayers.Raid", minPlayersNormal);
minPlayersRaidHeroic = sConfigMgr->GetOption<int>("AutoBalance.MinPlayers.RaidHeroic", minPlayersHeroic);
if (sConfigMgr->GetOption<float>("AutoBalance.PerDungeonPlayerCounts", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.PerDungeonPlayerCounts` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
minPlayersPerDungeonIdMap = LoadMinPlayersPerDungeonId(
sConfigMgr->GetOption<std::string>("AutoBalance.MinPlayers.PerInstance",
sConfigMgr->GetOption<std::string>("AutoBalance.PerDungeonPlayerCounts", "", false), false)); // `AutoBalance.PerDungeonPlayerCounts` for backwards compatibility
minPlayersPerHeroicDungeonIdMap = LoadMinPlayersPerDungeonId(
sConfigMgr->GetOption<std::string>("AutoBalance.MinPlayers.Heroic.PerInstance",
sConfigMgr->GetOption<std::string>("AutoBalance.PerDungeonPlayerCounts", "", false), false)); // `AutoBalance.PerDungeonPlayerCounts` for backwards compatibility
//
// Overrides
//
if (sConfigMgr->GetOption<float>("AutoBalance.PerDungeonScaling", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.PerDungeonScaling` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
dungeonOverrides = LoadInflectionPointOverrides(
sConfigMgr->GetOption<std::string>("AutoBalance.InflectionPoint.PerInstance",
sConfigMgr->GetOption<std::string>("AutoBalance.PerDungeonScaling", "", false), false)); // `AutoBalance.PerDungeonScaling` for backwards compatibility
if (sConfigMgr->GetOption<float>("AutoBalance.PerDungeonBossScaling", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.PerDungeonBossScaling` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
bossOverrides = LoadInflectionPointOverrides(
sConfigMgr->GetOption<std::string>("AutoBalance.InflectionPoint.Boss.PerInstance",
sConfigMgr->GetOption<std::string>("AutoBalance.PerDungeonBossScaling", "", false), false)); // `AutoBalance.PerDungeonBossScaling` for backwards compatibility
statModifierOverrides = LoadStatModifierOverrides(
sConfigMgr->GetOption<std::string>("AutoBalance.StatModifier.PerInstance", "", false));
statModifierBossOverrides = LoadStatModifierOverrides(
sConfigMgr->GetOption<std::string>("AutoBalance.StatModifier.Boss.PerInstance", "", false));
statModifierCreatureOverrides = LoadStatModifierOverrides(
sConfigMgr->GetOption<std::string>("AutoBalance.StatModifier.PerCreature", "", false));
levelScalingDynamicLevelOverrides = LoadDynamicLevelOverrides(
sConfigMgr->GetOption<std::string>("AutoBalance.LevelScaling.DynamicLevel.PerInstance", "", false));
levelScalingDistanceCheckOverrides = LoadDistanceCheckOverrides(
sConfigMgr->GetOption<std::string>("AutoBalance.LevelScaling.DynamicLevel.DistanceCheck.PerInstance", "", false));
//
// AutoBalance.Enable.*
// Deprecated setting warning
//
if (sConfigMgr->GetOption<int>("AutoBalance.enable", -1, false) != -1)
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.enable` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
EnableGlobal = sConfigMgr->GetOption<bool>("AutoBalance.Enable.Global" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false)); // `AutoBalance.enable` for backwards compatibility
Enable5M = sConfigMgr->GetOption<bool>("AutoBalance.Enable.5M" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable10M = sConfigMgr->GetOption<bool>("AutoBalance.Enable.10M" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable15M = sConfigMgr->GetOption<bool>("AutoBalance.Enable.15M" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable20M = sConfigMgr->GetOption<bool>("AutoBalance.Enable.20M" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable25M = sConfigMgr->GetOption<bool>("AutoBalance.Enable.25M" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable40M = sConfigMgr->GetOption<bool>("AutoBalance.Enable.40M" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
EnableOtherNormal = sConfigMgr->GetOption<bool>("AutoBalance.Enable.OtherNormal", sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable5MHeroic = sConfigMgr->GetOption<bool>("AutoBalance.Enable.5MHeroic" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable10MHeroic = sConfigMgr->GetOption<bool>("AutoBalance.Enable.10MHeroic" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
Enable25MHeroic = sConfigMgr->GetOption<bool>("AutoBalance.Enable.25MHeroic" , sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
EnableOtherHeroic = sConfigMgr->GetOption<bool>("AutoBalance.Enable.OtherHeroic", sConfigMgr->GetOption<bool>("AutoBalance.enable", 1, false));
//
// Deprecated setting warning
//
if (sConfigMgr->GetOption<int>("AutoBalance.DungeonsOnly", -1, false) != -1)
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.DungeonsOnly` defined in `AutoBalance.conf`. This variable has been removed and has no effect. Please see `AutoBalance.conf.dist` for more details.");
if (sConfigMgr->GetOption<int>("AutoBalance.levelUseDbValuesWhenExists", -1, false) != -1)
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.levelUseDbValuesWhenExists` defined in `AutoBalance.conf`. This variable has been removed and has no effect. Please see `AutoBalance.conf.dist` for more details.");
//
// Misc Settings
// TODO: Organize and standardize variable names
//
PlayerChangeNotify = sConfigMgr->GetOption<bool> ("AutoBalance.PlayerChangeNotify", 1);
rewardEnabled = sConfigMgr->GetOption<bool> ("AutoBalance.reward.enable", 1);
PlayerCountDifficultyOffset = sConfigMgr->GetOption<uint32>("AutoBalance.playerCountDifficultyOffset", 0);
rewardRaid = sConfigMgr->GetOption<uint32>("AutoBalance.reward.raidToken", 49426);
rewardDungeon = sConfigMgr->GetOption<uint32>("AutoBalance.reward.dungeonToken", 47241);
MinPlayerReward = sConfigMgr->GetOption<float> ("AutoBalance.reward.MinPlayerReward", 1);
//
// InflectionPoint*
// warn the console if deprecated values are detected
//
if (sConfigMgr->GetOption<float>("AutoBalance.BossInflectionMult", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.BossInflectionMult` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
InflectionPoint = sConfigMgr->GetOption<float>("AutoBalance.InflectionPoint", 0.5f, false);
InflectionPointCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPoint.CurveFloor", 0.0f, false);
InflectionPointCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPoint.CurveCeiling", 1.0f, false);
InflectionPointBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPoint.BossModifier", sConfigMgr->GetOption<float>("AutoBalance.BossInflectionMult", 1.0f, false), false); // `AutoBalance.BossInflectionMult` for backwards compatibility
InflectionPointHeroic = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointHeroic", 0.5f, false);
InflectionPointHeroicCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointHeroic.CurveFloor", 0.0f, false);
InflectionPointHeroicCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointHeroic.CurveCeiling", 1.0f, false);
InflectionPointHeroicBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointHeroic.BossModifier", sConfigMgr->GetOption<float>("AutoBalance.BossInflectionMult", 1.0f, false), false); // `AutoBalance.BossInflectionMult` for backwards compatibility
InflectionPointRaid = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid", 0.5f, false);
InflectionPointRaidCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid.CurveFloor", 0.0f, false);
InflectionPointRaidCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid.CurveCeiling", 1.0f, false);
InflectionPointRaidBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid.BossModifier", sConfigMgr->GetOption<float>("AutoBalance.BossInflectionMult", 1.0f, false), false); // `AutoBalance.BossInflectionMult` for backwards compatibility
InflectionPointRaidHeroic = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaidHeroic", 0.5f, false);
InflectionPointRaidHeroicCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaidHeroic.CurveFloor", 0.0f, false);
InflectionPointRaidHeroicCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaidHeroic.CurveCeiling", 1.0f, false);
InflectionPointRaidHeroicBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaidHeroic.BossModifier", sConfigMgr->GetOption<float>("AutoBalance.BossInflectionMult", 1.0f, false), false); // `AutoBalance.BossInflectionMult` for backwards compatibility
InflectionPointRaid10M = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10M", InflectionPointRaid, false);
InflectionPointRaid10MCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10M.CurveFloor", InflectionPointRaidCurveFloor, false);
InflectionPointRaid10MCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10M.CurveCeiling", InflectionPointRaidCurveCeiling, false);
InflectionPointRaid10MBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10M.BossModifier", InflectionPointRaidBoss, false);
InflectionPointRaid10MHeroic = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10MHeroic", InflectionPointRaidHeroic, false);
InflectionPointRaid10MHeroicCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10MHeroic.CurveFloor", InflectionPointRaidHeroicCurveFloor, false);
InflectionPointRaid10MHeroicCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10MHeroic.CurveCeiling", InflectionPointRaidHeroicCurveCeiling, false);
InflectionPointRaid10MHeroicBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid10MHeroic.BossModifier", InflectionPointRaidHeroicBoss, false);
InflectionPointRaid15M = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid15M", InflectionPointRaid, false);
InflectionPointRaid15MCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid15M.CurveFloor", InflectionPointRaidCurveFloor, false);
InflectionPointRaid15MCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid15M.CurveCeiling", InflectionPointRaidCurveCeiling, false);
InflectionPointRaid15MBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid15M.BossModifier", InflectionPointRaidBoss, false);
InflectionPointRaid20M = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid20M", InflectionPointRaid, false);
InflectionPointRaid20MCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid20M.CurveFloor", InflectionPointRaidCurveFloor, false);
InflectionPointRaid20MCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid20M.CurveCeiling", InflectionPointRaidCurveCeiling, false);
InflectionPointRaid20MBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid20M.BossModifier", InflectionPointRaidBoss, false);
InflectionPointRaid25M = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25M", InflectionPointRaid, false);
InflectionPointRaid25MCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25M.CurveFloor", InflectionPointRaidCurveFloor, false);
InflectionPointRaid25MCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25M.CurveCeiling", InflectionPointRaidCurveCeiling, false);
InflectionPointRaid25MBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25M.BossModifier", InflectionPointRaidBoss, false);
InflectionPointRaid25MHeroic = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25MHeroic", InflectionPointRaidHeroic, false);
InflectionPointRaid25MHeroicCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25MHeroic.CurveFloor", InflectionPointRaidHeroicCurveFloor, false);
InflectionPointRaid25MHeroicCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25MHeroic.CurveCeiling", InflectionPointRaidHeroicCurveCeiling, false);
InflectionPointRaid25MHeroicBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid25MHeroic.BossModifier", InflectionPointRaidHeroicBoss, false);
InflectionPointRaid40M = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid40M", InflectionPointRaid, false);
InflectionPointRaid40MCurveFloor = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid40M.CurveFloor", InflectionPointRaidCurveFloor, false);
InflectionPointRaid40MCurveCeiling = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid40M.CurveCeiling", InflectionPointRaidCurveCeiling, false);
InflectionPointRaid40MBoss = sConfigMgr->GetOption<float>("AutoBalance.InflectionPointRaid40M.BossModifier", InflectionPointRaidBoss, false);
//
// StatModifier*
// warn the console if deprecated values are detected
//
if (sConfigMgr->GetOption<float>("AutoBalance.rate.global", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.rate.global` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
if (sConfigMgr->GetOption<float>("AutoBalance.rate.health", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.rate.health` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
if (sConfigMgr->GetOption<float>("AutoBalance.rate.mana", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.rate.mana` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
if (sConfigMgr->GetOption<float>("AutoBalance.rate.armor", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.rate.armor` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
if (sConfigMgr->GetOption<float>("AutoBalance.rate.damage", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.rate.damage` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
//
// 5-player dungeons
//
StatModifier_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifier_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifier_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifier_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifier_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifier_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.CCDuration", -1.0f, false);
StatModifier_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Boss.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifier_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Boss.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifier_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Boss.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifier_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Boss.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifier_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Boss.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifier_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifier.Boss.CCDuration", -1.0f, false);
//
// 5-player heroic dungeons
//
StatModifierHeroic_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifierHeroic_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifierHeroic_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifierHeroic_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifierHeroic_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifierHeroic_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.CCDuration", -1.0f, false);
StatModifierHeroic_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Boss.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifierHeroic_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Boss.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifierHeroic_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Boss.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifierHeroic_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Boss.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifierHeroic_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Boss.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifierHeroic_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierHeroic.Boss.CCDuration", -1.0f, false);
//
// Default for all raids
//
StatModifierRaid_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifierRaid_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifierRaid_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifierRaid_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifierRaid_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifierRaid_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.CCDuration", -1.0f, false);
StatModifierRaid_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Boss.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifierRaid_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Boss.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifierRaid_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Boss.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifierRaid_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Boss.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifierRaid_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Boss.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifierRaid_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid.Boss.CCDuration", -1.0f, false);
//
// Default for all heroic raids
//
StatModifierRaidHeroic_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifierRaidHeroic_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifierRaidHeroic_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifierRaidHeroic_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifierRaidHeroic_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifierRaidHeroic_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.CCDuration", -1.0f, false);
StatModifierRaidHeroic_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Boss.Global", sConfigMgr->GetOption<float>("AutoBalance.rate.global", 1.0f, false), false); // `AutoBalance.rate.global` for backwards compatibility
StatModifierRaidHeroic_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Boss.Health", sConfigMgr->GetOption<float>("AutoBalance.rate.health", 1.0f, false), false); // `AutoBalance.rate.health` for backwards compatibility
StatModifierRaidHeroic_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Boss.Mana", sConfigMgr->GetOption<float>("AutoBalance.rate.mana", 1.0f, false), false); // `AutoBalance.rate.mana` for backwards compatibility
StatModifierRaidHeroic_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Boss.Armor", sConfigMgr->GetOption<float>("AutoBalance.rate.armor", 1.0f, false), false); // `AutoBalance.rate.armor` for backwards compatibility
StatModifierRaidHeroic_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Boss.Damage", sConfigMgr->GetOption<float>("AutoBalance.rate.damage", 1.0f, false), false); // `AutoBalance.rate.damage` for backwards compatibility
StatModifierRaidHeroic_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaidHeroic.Boss.CCDuration", -1.0f, false);
//
// 10-player raids
//
StatModifierRaid10M_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Global", StatModifierRaid_Global, false);
StatModifierRaid10M_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Health", StatModifierRaid_Health, false);
StatModifierRaid10M_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Mana", StatModifierRaid_Mana, false);
StatModifierRaid10M_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Armor", StatModifierRaid_Armor, false);
StatModifierRaid10M_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Damage", StatModifierRaid_Damage, false);
StatModifierRaid10M_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.CCDuration", StatModifierRaid_CCDuration, false);
StatModifierRaid10M_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Boss.Global", StatModifierRaid_Boss_Global, false);
StatModifierRaid10M_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Boss.Health", StatModifierRaid_Boss_Health, false);
StatModifierRaid10M_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Boss.Mana", StatModifierRaid_Boss_Mana, false);
StatModifierRaid10M_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Boss.Armor", StatModifierRaid_Boss_Armor, false);
StatModifierRaid10M_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Boss.Damage", StatModifierRaid_Boss_Damage, false);
StatModifierRaid10M_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10M.Boss.CCDuration", StatModifierRaid_Boss_CCDuration, false);
//
// 10-player heroic raids
//
StatModifierRaid10MHeroic_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Global", StatModifierRaidHeroic_Global, false);
StatModifierRaid10MHeroic_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Health", StatModifierRaidHeroic_Health, false);
StatModifierRaid10MHeroic_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Mana", StatModifierRaidHeroic_Mana, false);
StatModifierRaid10MHeroic_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Armor", StatModifierRaidHeroic_Armor, false);
StatModifierRaid10MHeroic_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Damage", StatModifierRaidHeroic_Damage, false);
StatModifierRaid10MHeroic_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.CCDuration", StatModifierRaidHeroic_CCDuration, false);
StatModifierRaid10MHeroic_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Boss.Global", StatModifierRaidHeroic_Boss_Global, false);
StatModifierRaid10MHeroic_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Boss.Health", StatModifierRaidHeroic_Boss_Health, false);
StatModifierRaid10MHeroic_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Boss.Mana", StatModifierRaidHeroic_Boss_Mana, false);
StatModifierRaid10MHeroic_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Boss.Armor", StatModifierRaidHeroic_Boss_Armor, false);
StatModifierRaid10MHeroic_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Boss.Damage", StatModifierRaidHeroic_Boss_Damage, false);
StatModifierRaid10MHeroic_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid10MHeroic.Boss.CCDuration", StatModifierRaidHeroic_Boss_CCDuration, false);
//
// 15-player raids
//
StatModifierRaid15M_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Global", StatModifierRaid_Global, false);
StatModifierRaid15M_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Health", StatModifierRaid_Health, false);
StatModifierRaid15M_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Mana", StatModifierRaid_Mana, false);
StatModifierRaid15M_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Armor", StatModifierRaid_Armor, false);
StatModifierRaid15M_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Damage", StatModifierRaid_Damage, false);
StatModifierRaid15M_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.CCDuration", StatModifierRaid_CCDuration, false);
StatModifierRaid15M_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Boss.Global", StatModifierRaid_Boss_Global, false);
StatModifierRaid15M_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Boss.Health", StatModifierRaid_Boss_Health, false);
StatModifierRaid15M_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Boss.Mana", StatModifierRaid_Boss_Mana, false);
StatModifierRaid15M_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Boss.Armor", StatModifierRaid_Boss_Armor, false);
StatModifierRaid15M_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Boss.Damage", StatModifierRaid_Boss_Damage, false);
StatModifierRaid15M_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid15M.Boss.CCDuration", StatModifierRaid_Boss_CCDuration, false);
//
// 20-player raids
//
StatModifierRaid20M_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Global", StatModifierRaid_Global, false);
StatModifierRaid20M_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Health", StatModifierRaid_Health, false);
StatModifierRaid20M_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Mana", StatModifierRaid_Mana, false);
StatModifierRaid20M_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Armor", StatModifierRaid_Armor, false);
StatModifierRaid20M_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Damage", StatModifierRaid_Damage, false);
StatModifierRaid20M_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.CCDuration", StatModifierRaid_CCDuration, false);
StatModifierRaid20M_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Boss.Global", StatModifierRaid_Boss_Global, false);
StatModifierRaid20M_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Boss.Health", StatModifierRaid_Boss_Health, false);
StatModifierRaid20M_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Boss.Mana", StatModifierRaid_Boss_Mana, false);
StatModifierRaid20M_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Boss.Armor", StatModifierRaid_Boss_Armor, false);
StatModifierRaid20M_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Boss.Damage", StatModifierRaid_Boss_Damage, false);
StatModifierRaid20M_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid20M.Boss.CCDuration", StatModifierRaid_Boss_CCDuration, false);
//
// 25-player raids
//
StatModifierRaid25M_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Global", StatModifierRaid_Global, false);
StatModifierRaid25M_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Health", StatModifierRaid_Health, false);
StatModifierRaid25M_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Mana", StatModifierRaid_Mana, false);
StatModifierRaid25M_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Armor", StatModifierRaid_Armor, false);
StatModifierRaid25M_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Damage", StatModifierRaid_Damage, false);
StatModifierRaid25M_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.CCDuration", StatModifierRaid_CCDuration, false);
StatModifierRaid25M_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Boss.Global", StatModifierRaid_Boss_Global, false);
StatModifierRaid25M_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Boss.Health", StatModifierRaid_Boss_Health, false);
StatModifierRaid25M_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Boss.Mana", StatModifierRaid_Boss_Mana, false);
StatModifierRaid25M_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Boss.Armor", StatModifierRaid_Boss_Armor, false);
StatModifierRaid25M_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Boss.Damage", StatModifierRaid_Boss_Damage, false);
StatModifierRaid25M_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25M.Boss.CCDuration", StatModifierRaid_Boss_CCDuration, false);
//
// 25-player heroic raids
//
StatModifierRaid25MHeroic_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Global", StatModifierRaidHeroic_Global, false);
StatModifierRaid25MHeroic_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Health", StatModifierRaidHeroic_Health, false);
StatModifierRaid25MHeroic_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Mana", StatModifierRaidHeroic_Mana, false);
StatModifierRaid25MHeroic_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Armor", StatModifierRaidHeroic_Armor, false);
StatModifierRaid25MHeroic_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Damage", StatModifierRaidHeroic_Damage, false);
StatModifierRaid25MHeroic_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.CCDuration", StatModifierRaidHeroic_CCDuration, false);
StatModifierRaid25MHeroic_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Boss.Global", StatModifierRaidHeroic_Boss_Global, false);
StatModifierRaid25MHeroic_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Boss.Health", StatModifierRaidHeroic_Boss_Health, false);
StatModifierRaid25MHeroic_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Boss.Mana", StatModifierRaidHeroic_Boss_Mana, false);
StatModifierRaid25MHeroic_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Boss.Armor", StatModifierRaidHeroic_Boss_Armor, false);
StatModifierRaid25MHeroic_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Boss.Damage", StatModifierRaidHeroic_Boss_Damage, false);
StatModifierRaid25MHeroic_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid25MHeroic.Boss.CCDuration", StatModifierRaidHeroic_Boss_CCDuration, false);
//
// 40-player raids
//
StatModifierRaid40M_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Global", StatModifierRaid_Global, false);
StatModifierRaid40M_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Health", StatModifierRaid_Health, false);
StatModifierRaid40M_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Mana", StatModifierRaid_Mana, false);
StatModifierRaid40M_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Armor", StatModifierRaid_Armor, false);
StatModifierRaid40M_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Damage", StatModifierRaid_Damage, false);
StatModifierRaid40M_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.CCDuration", StatModifierRaid_CCDuration, false);
StatModifierRaid40M_Boss_Global = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Boss.Global", StatModifierRaid_Boss_Global, false);
StatModifierRaid40M_Boss_Health = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Boss.Health", StatModifierRaid_Boss_Health, false);
StatModifierRaid40M_Boss_Mana = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Boss.Mana", StatModifierRaid_Boss_Mana, false);
StatModifierRaid40M_Boss_Armor = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Boss.Armor", StatModifierRaid_Boss_Armor, false);
StatModifierRaid40M_Boss_Damage = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Boss.Damage", StatModifierRaid_Boss_Damage, false);
StatModifierRaid40M_Boss_CCDuration = sConfigMgr->GetOption<float>("AutoBalance.StatModifierRaid40M.Boss.CCDuration", StatModifierRaid_Boss_CCDuration, false);
//
// Modifier Min/Max
//
MinHPModifier = sConfigMgr->GetOption<float>("AutoBalance.MinHPModifier", 0.1f);
MinManaModifier = sConfigMgr->GetOption<float>("AutoBalance.MinManaModifier", 0.01f);
MinDamageModifier = sConfigMgr->GetOption<float>("AutoBalance.MinDamageModifier", 0.01f);
MinCCDurationModifier = sConfigMgr->GetOption<float>("AutoBalance.MinCCDurationModifier", 0.25f);
MaxCCDurationModifier = sConfigMgr->GetOption<float>("AutoBalance.MaxCCDurationModifier", 1.0f);
//
// LevelScaling.*
//
LevelScaling = sConfigMgr->GetOption<bool>("AutoBalance.LevelScaling", true);
std::string LevelScalingMethodString = sConfigMgr->GetOption<std::string>("AutoBalance.LevelScaling.Method", "dynamic", false);
if (LevelScalingMethodString == "fixed")
LevelScalingMethod = AUTOBALANCE_SCALING_FIXED;
else if (LevelScalingMethodString == "dynamic")
LevelScalingMethod = AUTOBALANCE_SCALING_DYNAMIC;
else
{
LOG_ERROR("server.loading", "mod-autobalance: invalid value `{}` for `AutoBalance.LevelScaling.Method` defined in `AutoBalance.conf`. Defaulting to a value of `dynamic`.", LevelScalingMethodString);
LevelScalingMethod = AUTOBALANCE_SCALING_DYNAMIC;
}
if (sConfigMgr->GetOption<float>("AutoBalance.LevelHigherOffset", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.LevelHigherOffset` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
LevelScalingSkipHigherLevels = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.SkipHigherLevels", sConfigMgr->GetOption<uint32>("AutoBalance.LevelHigherOffset", 3, false), true);
if (sConfigMgr->GetOption<float>("AutoBalance.LevelLowerOffset", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.LevelLowerOffset` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
LevelScalingSkipLowerLevels = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.SkipLowerLevels", sConfigMgr->GetOption<uint32>("AutoBalance.LevelLowerOffset", 5, false), true);
LevelScalingDynamicLevelCeilingDungeons = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Ceiling.Dungeons", 1);
LevelScalingDynamicLevelFloorDungeons = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Floor.Dungeons", 5);
LevelScalingDynamicLevelCeilingHeroicDungeons = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Ceiling.HeroicDungeons", 2);
LevelScalingDynamicLevelFloorHeroicDungeons = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Floor.HeroicDungeons", 5);
LevelScalingDynamicLevelCeilingRaids = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Ceiling.Raids", 3);
LevelScalingDynamicLevelFloorRaids = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Floor.Raids", 5);
LevelScalingDynamicLevelCeilingHeroicRaids = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Ceiling.HeroicRaids", 3);
LevelScalingDynamicLevelFloorHeroicRaids = sConfigMgr->GetOption<uint8>("AutoBalance.LevelScaling.DynamicLevel.Floor.HeroicRaids", 5);
if (sConfigMgr->GetOption<float>("AutoBalance.LevelEndGameBoost", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.LevelEndGameBoost` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
LevelScalingEndGameBoost = sConfigMgr->GetOption<bool>("AutoBalance.LevelScaling.EndGameBoost", sConfigMgr->GetOption<bool>("AutoBalance.LevelEndGameBoost", 1, false), true);
if (LevelScalingEndGameBoost)
{
LOG_WARN("server.loading", "mod-autobalance: `AutoBalance.LevelScaling.EndGameBoost` is enabled in the configuration, but is not currently implemented. No effect.");
LevelScalingEndGameBoost = 0;
}
//
// RewardScaling.*
// warn the console if deprecated values are detected
//
if (sConfigMgr->GetOption<float>("AutoBalance.DungeonScaleDownXP", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.DungeonScaleDownXP` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
if (sConfigMgr->GetOption<float>("AutoBalance.DungeonScaleDownMoney", false, false))
LOG_WARN("server.loading", "mod-autobalance: deprecated value `AutoBalance.DungeonScaleDownMoney` defined in `AutoBalance.conf`. This variable will be removed in a future release. Please see `AutoBalance.conf.dist` for more details.");
std::string RewardScalingMethodString = sConfigMgr->GetOption<std::string>("AutoBalance.RewardScaling.Method", "dynamic", false);
if (RewardScalingMethodString == "fixed")
RewardScalingMethod = AUTOBALANCE_SCALING_FIXED;
else if (RewardScalingMethodString == "dynamic")
RewardScalingMethod = AUTOBALANCE_SCALING_DYNAMIC;
else
{
LOG_ERROR("server.loading", "mod-autobalance: invalid value `{}` for `AutoBalance.RewardScaling.Method` defined in `AutoBalance.conf`. Defaulting to a value of `dynamic`.", RewardScalingMethodString);
RewardScalingMethod = AUTOBALANCE_SCALING_DYNAMIC;
}
RewardScalingXP = sConfigMgr->GetOption<bool>("AutoBalance.RewardScaling.XP", sConfigMgr->GetOption<bool>("AutoBalance.DungeonScaleDownXP", true, false));
RewardScalingXPModifier = sConfigMgr->GetOption<float>("AutoBalance.RewardScaling.XP.Modifier", 1.0f, false);
RewardScalingMoney = sConfigMgr->GetOption<bool>("AutoBalance.RewardScaling.Money", sConfigMgr->GetOption<bool>("AutoBalance.DungeonScaleDownMoney", true, false));
RewardScalingMoneyModifier = sConfigMgr->GetOption<float>("AutoBalance.RewardScaling.Money.Modifier", 1.0f, false);
//
// Announcement
//
Announcement = sConfigMgr->GetOption<bool>("AutoBalanceAnnounce.enable", true);
}
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
*/
#ifndef __AB_WORLD_SCRIPT_H
#define __AB_WORLD_SCRIPT_H
#include "WorldScript.h"
class AutoBalance_WorldScript : public WorldScript
{
public:
AutoBalance_WorldScript()
: WorldScript("AutoBalance_WorldScript", {
WORLDHOOK_ON_BEFORE_CONFIG_LOAD
})
{
}
void OnBeforeConfigLoad(bool /*reload*/) override;
void SetInitialWorldSettings();
};
#endif
@@ -0,0 +1,6 @@
void AddAutoBalanceScripts();
void Addmod_autobalanceScripts()
{
AddAutoBalanceScripts();
}
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2018 AzerothCore <http://www.azerothcore.org>
* Copyright (C) 2012 CVMagic <http://www.trinitycore.org/f/topic/6551-vas-autobalance/>
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* Copyright (C) 1985-2010 KalCorp <http://vasserver.dyndns.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Script Name: AutoBalance
* Original Authors: KalCorp and Vaughner
* Maintainer(s): AzerothCore
* Original Script Name: AutoBalance
* Description: This script is intended to scale based on number of players,
* instance mobs & world bosses' level, health, mana, and damage.
*/
#include "AutoBalance.h"
#include "ABAllCreatureScript.h"
#include "ABAllMapScript.h"
#include "ABCommandScript.h"
#include "ABConfig.h"
#include "ABCreatureInfo.h"
#include "ABGameObjectScript.h"
#include "ABGlobalScript.h"
#include "ABInflectionPointSettings.h"
#include "ABLevelScalingDynamicLevelSettings.h"
#include "ABMapInfo.h"
#include "ABModuleScript.h"
#include "ABPlayerScript.h"
#include "ABScriptMgr.h"
#include "ABStatModifiers.h"
#include "ABUnitScript.h"
#include "ABUtils.h"
#include "ABWorldScript.h"
#include "Configuration/Config.h"
#include "Chat.h"
#include "Creature.h"
#include "Group.h"
#include "Language.h"
#include "Log.h"
#include "Map.h"
#include "MapMgr.h"
#include "Message.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptMgrMacros.h"
#include "SharedDefines.h"
#include "Unit.h"
#include "World.h"
#include <chrono>
#include <vector>
#if AC_COMPILER == AC_COMPILER_GNU
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
void AddAutoBalanceScripts()
{
new AutoBalance_WorldScript();
new AutoBalance_PlayerScript();
new AutoBalance_UnitScript();
new AutoBalance_GameObjectScript();
new AutoBalance_AllCreatureScript();
new AutoBalance_AllMapScript();
new AutoBalance_CommandScript();
new AutoBalance_GlobalScript();
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef MOD_AUTOBALANCE_H
#define MOD_AUTOBALANCE_H
enum ScalingMethod
{
AUTOBALANCE_SCALING_FIXED,
AUTOBALANCE_SCALING_DYNAMIC
};
enum BaseValueType
{
AUTOBALANCE_HEALTH,
AUTOBALANCE_DAMAGE_HEALING
};
enum Relevance
{
AUTOBALANCE_RELEVANCE_FALSE,
AUTOBALANCE_RELEVANCE_TRUE,
AUTOBALANCE_RELEVANCE_UNCHECKED
};
enum Damage_Healing_Debug_Phase
{
AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_BEFORE,
AUTOBALANCE_DAMAGE_HEALING_DEBUG_PHASE_AFTER
};
struct World_Multipliers
{
float scaled = 1.0f;
float unscaled = 1.0f;
};
#endif
+569
View File
@@ -0,0 +1,569 @@
#include "Message.h"
#include "DatabaseEnv.h"
#include "ItemTemplate.h"
#include <iostream>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
const std::unordered_map<LocaleConstant, std::string> AB_WELCOME_TO_PLAYER = {
{LOCALE_enUS, "|cffc3dbff [AutoBalance]|r|cffFF8000 Welcome to {} ({}-player {}). There are {} player(s) in this instance. Difficulty set to {} player(s).|r"},
{LOCALE_koKR, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} ({}-player {})에 오신 것을 환영합니다. 이 인스턴스에는 {}명의 플레이어가 있습니다. 난이도가 {}명으로 설정되었습니다.|r"},
{LOCALE_frFR, "|cffc3dbff [AutoBalance]|r|cffFF8000 Bienvenue dans {} ({} {}). Il y a {} joueur(s) dans cette instance. La difficulté est réglée sur {} joueur(s).|r"},
{LOCALE_deDE, "|cffc3dbff [AutoBalance]|r|cffFF8000 Willkommen in {} ({} Spieler {}). Es gibt {} Spieler in dieser Instanz. Schwierigkeit auf {} Spieler eingestellt.|r"},
{LOCALE_zhCN, "|cffc3dbff [AutoBalance]|r|cffFF8000 欢迎来到 {}{}人 {})。此副本中有 {} 名玩家。难度设置为 {} 名玩家。|r"},
{LOCALE_zhTW, "|cffc3dbff [AutoBalance]|r|cffFF8000 歡迎來到 {}{}人 {})。此副本中有 {} 名玩家。難度設定為 {} 名玩家。|r"},
{LOCALE_esES, "|cffc3dbff [AutoBalance]|r|cffFF8000 Bienvenido a {} ({} jugador {}). Hay {} jugador(es) en esta instancia. La dificultad se establece en {} jugador(es).|r"},
{LOCALE_esMX, "|cffc3dbff [AutoBalance]|r|cffFF8000 Bienvenido a {} ({} jugador {}). Hay {} jugador(es) en esta instancia. La dificultad se establece en {} jugador(es).|r"},
{LOCALE_ruRU, "|cffc3dbff [AutoBalance]|r|cffFF8000 Добро пожаловать в {} ({} игрок {}). В этом экземпляре {} игроков. Сложность установлена на {} игроков.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_WELCOME_TO_GM = {
{LOCALE_enUS, "|cffc3dbff [AutoBalance]|r|cffFF8000 Your GM flag is turned on. AutoBalance will ignore you. Please turn GM off and exit/re-enter the instance if you'd like to be considering for AutoBalancing.|r"},
{LOCALE_koKR, "|cffc3dbff [AutoBalance]|r|cffFF8000 GM 플래그가 켜져 있습니다. AutoBalance는 당신을 무시합니다. AutoBalancing을 고려하려면 GM을 끄고 인스턴스를 나가고 다시 들어가십시오.|r"},
{LOCALE_frFR, "|cffc3dbff [AutoBalance]|r|cffFF8000 Votre drapeau GM est activé. AutoBalance vous ignorera. Veuillez désactiver GM et sortir/revenir dans l'instance si vous souhaitez être pris en compte pour l'AutoBalancing.|r"},
{LOCALE_deDE, "|cffc3dbff [AutoBalance]|r|cffFF8000 Ihre GM-Flagge ist eingeschaltet. AutoBalance wird Sie ignorieren. Bitte schalten Sie GM aus und verlassen Sie das Instanz, wenn Sie für das AutoBalancing berücksichtigt werden möchten.|r"},
{LOCALE_zhCN, "|cffc3dbff [AutoBalance]|r|cffFF8000 您的GM模式已打开。AutoBalance将忽略。如果您希望考虑自动平衡,请关闭GM并退出/重新进入副本。|r"},
{LOCALE_zhTW, "|cffc3dbff [AutoBalance]|r|cffFF8000 您的GM模式已打開。AutoBalance將忽略。如果您希望考慮自動平衡,請關閉GM並退出/重新進入副本。|r"},
{LOCALE_esES, "|cffc3dbff [AutoBalance]|r|cffFF8000 Su bandera de GM está encendida. AutoBalance te ignorará. Por favor, apague GM y salga/vuelva a entrar en la instancia si desea ser considerado para el AutoBalance.|r"},
{LOCALE_esMX, "|cffc3dbff [AutoBalance]|r|cffFF8000 Su bandera de GM está encendida. AutoBalance te ignorará. Por favor, apague GM y salga/vuelva a entrar en la instancia si desea ser considerado para el AutoBalance.|r"},
{LOCALE_ruRU, "|cffc3dbff [AutoBalance]|r|cffFF8000 Ваш флаг GM включен. AutoBalance будет игнорировать вас. Пожалуйста, отключите GM и выйдите/войдите в экземпляр, если хотите, чтобы вас учитывали при автобалансировке.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ANNOUNCE_NON_GM_ENTERING_INSTANCE = {
{LOCALE_enUS, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} enters the instance. There are {} player(s) in this instance. Difficulty set to {} player(s).|r"},
{LOCALE_koKR, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}이(가) 인스턴스에 들어왔습니다. 이 인스턴스에는 {}명의 플레이어가 있습니다. 난이도가 {}명으로 설정되었습니다.|r"},
{LOCALE_frFR, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} entre dans l'instance. Il y a {} joueur(s) dans cette instance. La difficulté est réglée sur {} joueur(s).|r"},
{LOCALE_deDE, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} betritt die Instanz. Es gibt {} Spieler in dieser Instanz. Schwierigkeit auf {} Spieler eingestellt.|r"},
{LOCALE_zhCN, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}进入了副本。此副本中有 {} 名玩家。难度设置为 {} 名玩家。|r"},
{LOCALE_zhTW, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}進入了副本。此副本中有 {} 名玩家。難度設定為 {} 名玩家。|r"},
{LOCALE_esES, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} entra en la instancia. Hay {} jugador(es) en esta instancia. La dificultad se establece en {} jugador(es).|r"},
{LOCALE_esMX, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} entra en la instancia. Hay {} jugador(es) en esta instancia. La dificultad se establece en {} jugador(es).|r"},
{LOCALE_ruRU, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} входит в экземпляр. В этом экземпляре {} игроков. Сложность установлена на {} игроков.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_LEAVING_INSTANCE_COMBAT = {
{LOCALE_enUS, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} left the instance while combat was in progress. Difficulty locked to no less than {} players until combat ends.|r"},
{LOCALE_koKR, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}이(가) 전투 중에 인스턴스를 떠났습니다. 전투가 끝날 때까지 난이도가 {}명 미만으로 잠겨 있습니다.|r"},
{LOCALE_frFR, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} a quitté l'instance alors que le combat était en cours. La difficulté est verrouillée à pas moins de {} joueur(s) jusqu'à la fin du combat.|r"},
{LOCALE_deDE, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} hat die Instanz verlassen, während der Kampf im Gange war. Die Schwierigkeit ist gesperrt, bis der Kampf endet, auf nicht weniger als {} Spieler.|r"},
{LOCALE_zhCN, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}在战斗进行中离开了副本。直到战斗结束,难度锁定为不少于 {} 名玩家。|r"},
{LOCALE_zhTW, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}在戰鬥進行中離開了副本。直到戰鬥結束,難度鎖定為不少於 {} 名玩家。|r"},
{LOCALE_esES, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} salió de la instancia mientras el combate estaba en progreso. La dificultad está bloqueada a no menos de {} jugador(es) hasta que termine el combate.|r"}
};
const std::unordered_map<LocaleConstant, std::string> AB_LEAVING_INSTANCE = {
{LOCALE_enUS, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} left the instance. There are {} player(s) in this instance. Difficulty set to {} player(s).|r"},
{LOCALE_koKR, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}이(가) 인스턴스를 떠났습니다. 이 인스턴스에는 {}명의 플레이어가 있습니다. 난이도가 {}명으로 설정되었습니다.|r"},
{LOCALE_frFR, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} a quitté l'instance. Il y a {} joueur(s) dans cette instance. La difficulté est réglée sur {} joueur(s).|r"},
{LOCALE_deDE, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} hat die Instanz verlassen. Es gibt {} Spieler in dieser Instanz. Schwierigkeit auf {} Spieler eingestellt.|r"},
{LOCALE_zhCN, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}离开了副本。此副本中有 {} 名玩家。难度设置为 {} 名玩家。|r"},
{LOCALE_zhTW, "|cffc3dbff [AutoBalance]|r|cffFF8000 {}離開了副本。此副本中有 {} 名玩家。難度設定為 {} 名玩家。|r"},
{LOCALE_esES, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} salió de la instancia. Hay {} jugador(es) en esta instancia. La dificultad se establece en {} jugador(es).|r"},
{LOCALE_esMX, "|cffc3dbff [AutoBalance]|r|cffFF8000 {} salió de la instancia. Hay {} jugador(es) en esta instancia. La dificultad se establece en {}"}
};
const std::unordered_map<LocaleConstant, std::string> AB_SET_OFFSET_COMMAND_DESCRIPTION = {
{LOCALE_enUS, "Set the player difficulty offset for this instance. Usage: .ab offset <number>.|r"},
{LOCALE_koKR, "이 인스턴스의 플레이어 난이도 오프셋을 설정합니다. 사용법: .ab offset <숫자>.|r"},
{LOCALE_frFR, "Définissez le décalage de difficulté du joueur pour cette instance. Utilisation : .ab offset <nombre>.|r"},
{LOCALE_deDE, "Legen Sie den Spieler-Schwierigkeits-Offset für diese Instanz fest. Verwendung: .ab offset <Nummer>.|r"},
{LOCALE_zhCN, "设置此副本的玩家难度。用法:.ab offset <数字>。|r"},
{LOCALE_zhTW, "設定此副本的玩家難度。用法:.ab offset <數字>。|r"},
{LOCALE_esES, "Establece el desplazamiento de dificultad del jugador para esta instancia. Uso: .ab offset <número>.|r"},
{LOCALE_esMX, "Establece el desplazamiento de dificultad del jugador para esta instancia. Uso: .ab offset <número>.|r"},
{LOCALE_ruRU, "Устанавливает смещение сложности игрока для этого экземп"}
};
const std::unordered_map<LocaleConstant, std::string> AB_SET_OFFSET_COMMAND_SUCCESS = {
{LOCALE_enUS, "Changing Player Difficulty Offset to {}.|r"},
{LOCALE_koKR, "플레이어 난이도 오프셋을 {}(으)로 변경합니다.|r"},
{LOCALE_frFR, "Modification du décalage de difficulté du joueur à {}.|r"},
{LOCALE_deDE, "Spieler-Schwierigkeits-Offset auf {} ändern.|r"},
{LOCALE_zhCN, "将玩家难度更改为 {}。|r"},
{LOCALE_zhTW, "將玩家難度更改為 {}。|r"},
{LOCALE_esES, "Cambiando el desplazamiento de dificultad del jugador a {}.|r"},
{LOCALE_esMX, "Cambiando el desplazamiento de dificultad del jugador a {}.|r"},
{LOCALE_ruRU, "Изменение смещения сложности игрока на {}.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_SET_OFFSET_COMMAND_ERROR = {
{LOCALE_enUS, "Error changing Player Difficulty Offset! Please try again.|r"},
{LOCALE_koKR, "플레이어 난이도 오프셋 변경 중 오류가 발생했습니다! 다시 시도하십시오.|r"},
{LOCALE_frFR, "Erreur lors de la modification du décalage de difficulté du joueur ! Veuillez réessayer.|r"},
{LOCALE_deDE, "Fehler beim Ändern des Spieler-Schwierigkeits-Offsets! Bitte versuchen Sie es erneut.|r"},
{LOCALE_zhCN, "更改玩家难度时出错!请重试。|r"},
{LOCALE_zhTW, "更改玩家難度時出錯!請重試。|r"},
{LOCALE_esES, "¡Error al cambiar el desplazamiento de dificultad del jugador! Por favor, inténtelo de nuevo.|r"},
{LOCALE_esMX, "¡Error al cambiar el desplazamiento de dificultad del jugador! Por favor, inténtelo de nuevo.|r"},
{LOCALE_ruRU, "Ошибка при изменении смещения сложности игрока! Пожалуйста, попробуйте еще раз.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_GET_OFFSET_COMMAND_SUCCESS = {
{LOCALE_enUS, "Current Player Difficulty Offset = {}.|r"},
{LOCALE_koKR, "현재 플레이어 난이도 오프셋 = {}.|r"},
{LOCALE_frFR, "Décalage de difficulté actuel du joueur = {}.|r"},
{LOCALE_deDE, "Aktueller Spieler-Schwierigkeits-Offset = {}.|r"},
{LOCALE_zhCN, "当前玩家难度偏移 = {}。|r"},
{LOCALE_zhTW, "當前玩家難度偏移 = {}。|r"},
{LOCALE_esES, "Desplazamiento de dificultad actual del jugador = {}.|r"},
{LOCALE_esMX, "Desplazamiento de dificultad actual del jugador = {}.|r"},
{LOCALE_ruRU, "Текущее смещение сложности игрока = {}.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ADJUSTED_PLAYER_COUNT_COMBAT_LOCKED = {
{LOCALE_enUS, "Adjusted Player Count: {} (Combat Locked)|r"},
{LOCALE_koKR, "조정된 플레이어 수: {} (전투 잠금됨)|r"},
{LOCALE_frFR, "Nombre de joueurs ajusté : {} (verrouillé en combat)|r"},
{LOCALE_deDE, "Angepasste Spieleranzahl: {} (Kampf gesperrt)|r"},
{LOCALE_zhCN, "调整后的玩家数量:{}(战斗锁定)|r"},
{LOCALE_zhTW, "調整後的玩家數量:{}(戰鬥鎖定)|r"},
{LOCALE_esES, "Cantidad de jugadores ajustada: {} (bloqueada en combate)|r"},
{LOCALE_esMX, "Cantidad de jugadores ajustada: {} (bloqueada en combate)|r"},
{LOCALE_ruRU, "Количество игроков, отрегулированное: {} (заблокировано в бою)|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ADJUSTED_PLAYER_COUNT_MAP_MINIMUM = {
{LOCALE_enUS, "Adjusted Player Count: {} (Map Minimum)|r"},
{LOCALE_koKR, "조정된 플레이어 수: {} (지도 최소)|r"},
{LOCALE_frFR, "Nombre de joueurs ajusté : {} (minimum de la carte)|r"},
{LOCALE_deDE, "Angepasste Spieleranzahl: {} (Kartenminimum)|r"},
{LOCALE_zhCN, "调整后的玩家数量:{}(地图最小)|r"},
{LOCALE_zhTW, "調整後的玩家數量:{}(地圖最小)|r"},
{LOCALE_esES, "Cantidad de jugadores ajustada: {} (mínimo del mapa)|r"},
{LOCALE_esMX, "Cantidad de jugadores ajustada: {} (mínimo del mapa)|r"},
{LOCALE_ruRU, "Количество игроков, отрегулированное: {} (минимальное для карты)|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ADJUSTED_PLAYER_COUNT_MAP_MINIMUM_DIFFICULTY_OFFSET = {
{LOCALE_enUS, "Adjusted Player Count: {} (Map Minimum + Difficulty Offset of {})|r"},
{LOCALE_koKR, "조정된 플레이어 수: {} (지도 최소 + {}의 난이도 오프셋)|r"},
{LOCALE_frFR, "Nombre de joueurs ajusté : {} (minimum de la carte + décalage de difficulté de {})|r"},
{LOCALE_deDE, "Angepasste Spieleranzahl: {} (Kartenminimum + Schwierigkeits-Offset von {})|r"},
{LOCALE_zhCN, "调整后的玩家数量:{}(地图最小 + {}的难度修正)|r"},
{LOCALE_zhTW, "調整後的玩家數量:{}(地圖最小 + {}的難度修正)|r"},
{LOCALE_esES, "Cantidad de jugadores ajustada: {} (mínimo del mapa + desplazamiento de dificultad de {})|r"},
{LOCALE_esMX, "Cantidad de jugadores ajustada: {} (mínimo del mapa + desplazamiento de dificultad de {})|r"},
{LOCALE_ruRU, "Количество игроков, отрегулированное: {} (минимальное для карты"}
};
const std::unordered_map<LocaleConstant, std::string> AB_ADJUSTED_PLAYER_COUNT_DIFFICULTY_OFFSET = {
{LOCALE_enUS, "Adjusted Player Count: {} (Difficulty Offset of {})|r"},
{LOCALE_koKR, "조정된 플레이어 수: {} ({}의 난이도 오프셋)|r"},
{LOCALE_frFR, "Nombre de joueurs ajusté : {} (décalage de difficulté de {})|r"},
{LOCALE_deDE, "Angepasste Spieleranzahl: {} (Schwierigkeits-Offset von {})|r"},
{LOCALE_zhCN, "调整后的玩家数量:{}({}的难度修正)|r"},
{LOCALE_zhTW, "調整後的玩家數量:{}({}的難度修正)|r"},
{LOCALE_esES, "Cantidad de jugadores ajustada: {} (desplazamiento de dificultad de {})|r"},
{LOCALE_esMX, "Cantidad de jugadores ajustada: {} (desplazamiento de dificultad de {})|r"},
{LOCALE_ruRU, "Количество игроков, отрегулированное: {} (смещение сложности {})|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ADJUSTED_PLAYER_COUNT = {
{LOCALE_enUS, "Adjusted Player Count: {}|r"},
{LOCALE_koKR, "조정된 플레이어 수: {}|r"},
{LOCALE_frFR, "Nombre de joueurs ajusté : {}|r"},
{LOCALE_deDE, "Angepasste Spieleranzahl: {}|r"},
{LOCALE_zhCN, "调整后的玩家数量:{}|r"},
{LOCALE_zhTW, "調整後的玩家數量:{}|r"},
{LOCALE_esES, "Cantidad de jugadores ajustada: {}|r"},
{LOCALE_esMX, "Cantidad de jugadores ajustada: {}|r"},
{LOCALE_ruRU, "Количество игроков, отрегулированное: {}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_LFG_RANGE = {
{LOCALE_enUS, "LFG Range: Lvl {} - {} (Target: Lvl {})|r"},
{LOCALE_koKR, "LFG 범위: 레벨 {} - {} (대상: 레벨 {})|r"},
{LOCALE_frFR, "Plage LFG : Niveau {} - {} (Cible : Niveau {})|r"},
{LOCALE_deDE, "LFG-Bereich: Stufe {} - {} (Ziel: Stufe {})|r"},
{LOCALE_zhCN, "LFG范围:等级 {} - {}(目标:等级 {})|r"},
{LOCALE_zhTW, "LFG範圍:等級 {} - {}(目標:等級 {})|r"},
{LOCALE_esES, "Rango de LFG: Nivel {} - {} (Objetivo: Nivel {})|r"},
{LOCALE_esMX, "Rango de LFG: Nivel {} - {} (Objetivo: Nivel {})|r"},
{LOCALE_ruRU, "Диапазон поиска группы: Ур. {} - {} (Цель: Ур. {})|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_MAP_LEVEL = {
{LOCALE_enUS, "Map Level: {}{}|r"},
{LOCALE_koKR, "지도 레벨: {}{}|r"},
{LOCALE_frFR, "Niveau de la carte : {}{}|r"},
{LOCALE_deDE, "Kartenlevel: {}{}|r"},
{LOCALE_zhCN, "地图等级:{}{}|r"},
{LOCALE_zhTW, "地圖等級:{}{}|r"},
{LOCALE_esES, "Nivel del mapa: {}{}|r"},
{LOCALE_esMX, "Nivel del mapa: {}{}|r"},
{LOCALE_ruRU, "Уровень карты: {}{}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_LEVEL_SCALING_ENABLED = {
{LOCALE_enUS, " (Level Scaling Enabled)|r"},
{LOCALE_koKR, " (레벨 스케일링 활성화됨)|r"},
{LOCALE_frFR, " (Mise à l'échelle des niveaux activée)|r"},
{LOCALE_deDE, " (Stufenanpassung aktiviert)|r"},
{LOCALE_zhCN, " (启用等级自动平衡)|r"},
{LOCALE_zhTW, " (啟用等級縮放平衡)|r"},
{LOCALE_esES, " (Escalado de nivel activado)|r"},
{LOCALE_esMX, " (Escalado de nivel activado)|r"},
{LOCALE_ruRU, " (Масштабирование уровней включено)|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_LEVEL_SCALING_DISABLED = {
{LOCALE_enUS, " (Level Scaling Disabled)|r"},
{LOCALE_koKR, " (레벨 스케일링 비활성화됨)|r"},
{LOCALE_frFR, " (Mise à l'échelle des niveaux désactivée)|r"},
{LOCALE_deDE, " (Stufenanpassung deaktiviert)|r"},
{LOCALE_zhCN, " (禁用等级自动平衡)|r"},
{LOCALE_zhTW, " (停用等級縮放平衡)|r"},
{LOCALE_esES, " (Escalado de nivel desactivado)|r"},
{LOCALE_esMX, " (Escalado de nivel desactivado)|r"},
{LOCALE_ruRU, " (Масштабирование уровней отключено)|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_WORLD_HEALTH_MULTIPLIER = {
{LOCALE_enUS, "World health multiplier: {:.3f}|r"},
{LOCALE_koKR, "월드 체력 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de santé mondiale : {:.3f}|r"},
{LOCALE_deDE, "Weltgesundheitsmultiplikator: {:.3f}|r"},
{LOCALE_zhCN, "全局生命值倍率:{:.3f}|r"},
{LOCALE_zhTW, "全局生命值倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de salud mundial: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de salud mundial: {:.3f}|r"},
{LOCALE_ruRU, "Множитель здоровья мира: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_WORLD_HOSTILE_DAMAGE_HEALING_MULTIPLIER_TO = {
{LOCALE_enUS, "World hostile damage and healing multiplier: {:.3f} -> {:.3f}|r"},
{LOCALE_koKR, "월드 적 대미지 및 치유 배율: {:.3f} -> {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de dégâts et de soins hostiles mondiaux : {:.3f} -> {:.3f}|r"},
{LOCALE_deDE, "Weltweiter feindlicher Schadens- und Heilungs-Multiplikator: {:.3f} -> {:.3f}|r"},
{LOCALE_zhCN, "全局伤害和治疗倍率:{:.3f} -> {:.3f}|r"},
{LOCALE_zhTW, "全局敵對傷害和治療倍增器:{:.3f} -> {:.3f}|r"},
{LOCALE_esES, "Multiplicador de daño y curación hostil mundial: {:.3f} -> {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de daño y curación hostil mundial: {:.3f} -> {:.3f}|r"},
{LOCALE_ruRU, "Множитель урона и лечения мира: {:.3f} -> {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_WORLD_HOSTILE_DAMAGE_HEALING_MULTIPLIER = {
{LOCALE_enUS, "World hostile damage and healing multiplier: {:.3f}|r"},
{LOCALE_koKR, "월드 적 대미지 및 치유 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de dégâts et de soins hostiles mondiaux : {:.3f}|r"},
{LOCALE_deDE, "Weltweiter feindlicher Schadens- und Heilungs-Multiplikator: {:.3f}|r"},
{LOCALE_zhCN, "全局伤害和治疗倍率:{:.3f}|r"},
{LOCALE_zhTW, "全局敵對傷害和治療倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de daño y curación hostil mundial: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de daño y curación hostil mundial: {:.3f}|r"},
{LOCALE_ruRU, "Множитель урона и лечения мира: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ORIGINAL_CREATURE_LEVEL_RANGE = {
{LOCALE_enUS, "Original Creature Level Range: {} - {} (Avg: {:.2f})|r"},
{LOCALE_koKR, "원래 크리쳐 레벨 범위: {} - {} (평균: {:.2f})|r"},
{LOCALE_frFR, "Plage de niveaux de créatures d'origine : {} - {} (Moyenne : {:.2f})|r"},
{LOCALE_deDE, "Originaler Kreaturenlevelbereich: {} - {} (Durchschnitt: {:.2f})|r"},
{LOCALE_zhCN, "原始生物等级范围:{} - {}(平均:{:2.f}|r"},
{LOCALE_zhTW, "原始生物等級範圍:{} - {}(平均:{:2.f}|r"},
{LOCALE_esES, "Rango de niveles de criaturas originales: {} - {} (Promedio: {:.2f})|r"},
{LOCALE_esMX, "Rango de niveles de criaturas originales: {} - {} (Promedio: {:.2f})|r"},
{LOCALE_ruRU, "Исходный диапазон уровней существ: {} - {} (Среднее: {:.2f})|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ACTIVE_TOTAL_CREATURES_IN_MAP = {
{LOCALE_enUS, "Active | Total Creatures in map: {} | {}|r"},
{LOCALE_koKR, "활성 | 지도 내 총 크리쳐: {} | {}|r"},
{LOCALE_frFR, "Actif | Créatures totales dans la carte : {} | {}|r"},
{LOCALE_deDE, "Aktiv | Gesamte Kreaturen in der Karte: {} | {}|r"},
{LOCALE_zhCN, "Active | 地图中的总生物: {} | {}|r"},
{LOCALE_zhTW, "Active | 地圖中的總生物: {} | {}|r"},
{LOCALE_esES, "Activo | Criaturas totales en el mapa: {} | {}|r"},
{LOCALE_esMX, "Activo | Criaturas totales en el mapa: {} | {}|r"},
{LOCALE_ruRU, "Активные | Всего существ на карте: {} | {}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_COMMAND_ONLY_IN_INSTANCE = {
{LOCALE_enUS, "This command can only be used in a dungeon or raid.|r"},
{LOCALE_koKR, "이 명령은 던전이나 공격대에서만 사용할 수 있습니다.|r"},
{LOCALE_frFR, "Cette commande ne peut être utilisée que dans un donjon ou un raid.|r"},
{LOCALE_deDE, "Dieser Befehl kann nur in einem Dungeon oder Schlachtzug verwendet werden.|r"},
{LOCALE_zhCN, "此命令只能在地下城或团队副本中使用。|r"},
{LOCALE_zhTW, "此命令只能在地城或團隊副本中使用。|r"},
{LOCALE_esES, "Este comando solo se puede usar en una mazmorra o banda.|r"},
{LOCALE_esMX, "Este comando solo se puede usar en una mazmorra o banda.|r"},
{LOCALE_ruRU, "Эту команду можно использовать только в подземелье или рейде.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_TARGET_NO_IN_INSTANCE = {
{LOCALE_enUS, "That target is not in an instance.|r"},
{LOCALE_koKR, "그 대상은 인스턴스에 있지 않습니다.|r"},
{LOCALE_frFR, "Cette cible n'est pas dans une instance.|r"},
{LOCALE_deDE, "Dieses Ziel befindet sich nicht in einer Instanz.|r"},
{LOCALE_zhCN, "该目标不在副本中。|r"},
{LOCALE_zhTW, "該目標不在副本中。|r"},
{LOCALE_esES, "Ese objetivo no está en una instancia.|r"},
{LOCALE_esMX, "Ese objetivo no está en una instancia.|r"},
{LOCALE_ruRU, "Эта цель не находится в подземелье.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ACTIVE_FOR_MAP_STATS = {
{LOCALE_enUS, "Active for Map Stats|r"},
{LOCALE_koKR, "지도 통계용 활성|r"},
{LOCALE_frFR, "Actif pour les statistiques de la carte|r"},
{LOCALE_deDE, "Aktiv für Kartenstatistiken|r"},
{LOCALE_zhCN, "地图平衡激活|r"},
{LOCALE_zhTW, "地圖平衡激活|r"},
{LOCALE_esES, "Activo para estadísticas del mapa|r"},
{LOCALE_esMX, "Activo para estadísticas del mapa|r"},
{LOCALE_ruRU, "Активно для статистики карты|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_IGNORED_FOR_MAP_STATS = {
{LOCALE_enUS, "Ignored for Map Stats|r"},
{LOCALE_koKR, "지도 통계용 무시됨|r"},
{LOCALE_frFR, "Ignoré pour les statistiques de la carte|r"},
{LOCALE_deDE, "Ignoriert für Kartenstatistiken|r"},
{LOCALE_zhCN, "地图平衡已忽略|r"},
{LOCALE_zhTW, "地圖平衡已忽略|r"},
{LOCALE_esES, "Ignorado para estadísticas del mapa|r"},
{LOCALE_esMX, "Ignorado para estadísticas del mapa|r"},
{LOCALE_ruRU, "Игнорируется для статистики карты|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_CREATURE_DIFFICULTY_LEVEL = {
{LOCALE_enUS, "Creature difficulty level: {} player(s)|r"},
{LOCALE_koKR, "생물 난이도 레벨: {} 플레이어|r"},
{LOCALE_frFR, "Niveau de difficulté de la créature : {} joueur(s)|r"},
{LOCALE_deDE, "Kreaturschwierigkeitsstufe: {} Spieler|r"},
{LOCALE_zhCN, "生物难度等级:{} 玩家|r"},
{LOCALE_zhTW, "生物難度等級:{} 玩家|r"},
{LOCALE_esES, "Nivel de dificultad de la criatura: {} jugador(es)|r"},
{LOCALE_esMX, "Nivel de dificultad de la criatura: {} jugador(es)|r"},
{LOCALE_ruRU, "Уровень сложности существа: {} игрок(ов)|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_CLONE_OF_SUMMON = {
{LOCALE_enUS, "Clone of {} ({})|r"},
{LOCALE_koKR, "{}의 복제 ({})|r"},
{LOCALE_frFR, "Clone de {} ({})|r"},
{LOCALE_deDE, "Klon von {} ({})|r"},
{LOCALE_zhCN, "{}的克隆({}|r"},
{LOCALE_zhTW, "{}的克隆({}|r"},
{LOCALE_esES, "Clon de {} ({})|r"},
{LOCALE_esMX, "Clon de {} ({})|r"},
{LOCALE_ruRU, "Клон {} ({})|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_SUMMON_OF_SUMMON = {
{LOCALE_enUS, "Summon of {} ({})|r"},
{LOCALE_koKR, "{}의 소환 ({})|r"},
{LOCALE_frFR, "Invocation de {} ({})|r"},
{LOCALE_deDE, "Beschwörung von {} ({})|r"},
{LOCALE_zhCN, "{}的召唤({}|r"},
{LOCALE_zhTW, "{}的召喚({}|r"},
{LOCALE_esES, "Invocación de {} ({})|r"},
{LOCALE_esMX, "Invocación de {} ({})|r"},
{LOCALE_ruRU, "Призыв {} ({})|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_SUMMON_WITHOUT_SUMMONER = {
{LOCALE_enUS, "Summon without a summoner.|r"},
{LOCALE_koKR, "소환사 없는 소환.|r"},
{LOCALE_frFR, "Invocation sans invocateur.|r"},
{LOCALE_deDE, "Beschwörung ohne Beschwörer.|r"},
{LOCALE_zhCN, "没有召唤者的召唤物。|r"},
{LOCALE_zhTW, "沒有召喚者的召喚物。|r"},
{LOCALE_esES, "Invocación sin invocador.|r"},
{LOCALE_esMX, "Invocación sin invocador.|r"},
{LOCALE_ruRU, "Призыв без призывателя.|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_HEALTH_MULTIPLIER_TO = {
{LOCALE_enUS, "Health multiplier: {:.3f} -> {:.3f}|r"},
{LOCALE_koKR, "체력 배율: {:.3f} -> {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de santé : {:.3f} -> {:.3f}|r"},
{LOCALE_deDE, "Gesundheitsmultiplikator: {:.3f} -> {:.3f}|r"},
{LOCALE_zhCN, "生命值倍率:{:.3f} -> {:.3f}|r"},
{LOCALE_zhTW, "生命值倍增器:{:.3f} -> {:.3f}|r"},
{LOCALE_esES, "Multiplicador de salud: {:.3f} -> {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de salud: {:.3f} -> {:.3f}|r"},
{LOCALE_ruRU, "Множитель здоровья: {:.3f} -> {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_MANA_MULTIPLIER_TO = {
{LOCALE_enUS, "Mana multiplier: {:.3f} -> {:.3f}|r"},
{LOCALE_koKR, "마나 배율: {:.3f} -> {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de mana : {:.3f} -> {:.3f}|r"},
{LOCALE_deDE, "Manamultiplikator: {:.3f} -> {:.3f}|r"},
{LOCALE_zhCN, "法力值倍率:{:.3f} -> {:.3f}|r"},
{LOCALE_zhTW, "法力值倍增器:{:.3f} -> {:.3f}|r"},
{LOCALE_esES, "Multiplicador de maná: {:.3f} -> {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de maná: {:.3f} -> {:.3f}|r"},
{LOCALE_ruRU, "Множитель маны: {:.3f} -> {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ARMOR_MULTIPLIER_TO = {
{LOCALE_enUS, "Armor multiplier: {:.3f} -> {:.3f}|r"},
{LOCALE_koKR, "방어구 배율: {:.3f} -> {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur d'armure : {:.3f} -> {:.3f}|r"},
{LOCALE_deDE, "Rüstungsmultiplikator: {:.3f} -> {:.3f}|r"},
{LOCALE_zhCN, "护甲倍率:{:.3f} -> {:.3f}|r"},
{LOCALE_zhTW, "護甲倍增器:{:.3f} -> {:.3f}|r"},
{LOCALE_esES, "Multiplicador de armadura: {:.3f} -> {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de armadura: {:.3f} -> {:.3f}|r"},
{LOCALE_ruRU, "Множитель брони: {:.3f} -> {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_DAMAGE_MULTIPLIER_TO = {
{LOCALE_enUS, "Damage multiplier: {:.3f} -> {:.3f}|r"},
{LOCALE_koKR, "피해 배율: {:.3f} -> {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de dégâts : {:.3f} -> {:.3f}|r"},
{LOCALE_deDE, "Schadensmultiplikator: {:.3f} -> {:.3f}|r"},
{LOCALE_zhCN, "伤害倍率:{:.3f} -> {:.3f}|r"},
{LOCALE_zhTW, "傷害倍增器:{:.3f} -> {:.3f}|r"},
{LOCALE_esES, "Multiplicador de daño: {:.3f} -> {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de daño: {:.3f} -> {:.3f}|r"},
{LOCALE_ruRU, "Множитель урона: {:.3f} -> {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_HEALTH_MULTIPLIER = {
{LOCALE_enUS, "Health multiplier: {:.3f}|r"},
{LOCALE_koKR, "체력 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de santé : {:.3f}|r"},
{LOCALE_deDE, "Gesundheitsmultiplikator: {:.3f}|r"},
{LOCALE_zhCN, "生命值倍率:{:.3f}|r"},
{LOCALE_zhTW, "生命值倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de salud: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de salud: {:.3f}|r"},
{LOCALE_ruRU, "Множитель здоровья: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_MANA_MULTIPLIER = {
{LOCALE_enUS, "Mana multiplier: {:.3f}|r"},
{LOCALE_koKR, "마나 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de mana : {:.3f}|r"},
{LOCALE_deDE, "Manamultiplikator: {:.3f}|r"},
{LOCALE_zhCN, "法力值倍率:{:.3f}|r"},
{LOCALE_zhTW, "法力值倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de maná: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de maná: {:.3f}|r"},
{LOCALE_ruRU, "Множитель маны: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_ARMOR_MULTIPLIER = {
{LOCALE_enUS, "Armor multiplier: {:.3f}|r"},
{LOCALE_koKR, "방어구 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur d'armure : {:.3f}|r"},
{LOCALE_deDE, "Rüstungsmultiplikator: {:.3f}|r"},
{LOCALE_zhCN, "护甲倍率:{:.3f}|r"},
{LOCALE_zhTW, "護甲倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de armadura: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de armadura: {:.3f}|r"},
{LOCALE_ruRU, "Множитель брони: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_DAMAGE_MULTIPLIER = {
{LOCALE_enUS, "Damage multiplier: {:.3f}|r"},
{LOCALE_koKR, "피해 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de dégâts : {:.3f}|r"},
{LOCALE_deDE, "Schadensmultiplikator: {:.3f}|r"},
{LOCALE_zhCN, "伤害倍率:{:.3f}|r"},
{LOCALE_zhTW, "傷害倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de daño: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de daño: {:.3f}|r"},
{LOCALE_ruRU, "Множитель урона: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_CC_DURATION_MULTIPLIER = {
{LOCALE_enUS, "CC Duration multiplier: {:.3f}|r"},
{LOCALE_koKR, "CC 지속시간 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur de durée de la CC : {:.3f}|r"},
{LOCALE_deDE, "CC-Dauer-Multiplikator: {:.3f}|r"},
{LOCALE_zhCN, "控制持续时间倍率:{:.3f}|r"},
{LOCALE_zhTW, "控制持續時間倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de duración de CC: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de duración de CC: {:.3f}|r"},
{LOCALE_ruRU, "Множитель длительности контроля: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_XP_MONEY_MULTIPLIER = {
{LOCALE_enUS, "XP multiplier: {:.3f} Money multiplier: {:.3f}|r"},
{LOCALE_koKR, "경험치 배율: {:.3f} 돈 배율: {:.3f}|r"},
{LOCALE_frFR, "Multiplicateur d'XP : {:.3f} Multiplicateur d'argent : {:.3f}|r"},
{LOCALE_deDE, "XP-Multiplikator: {:.3f} Geldmultiplikator: {:.3f}|r"},
{LOCALE_zhCN, "经验值倍率:{:.3f} 金钱倍率:{:.3f}|r"},
{LOCALE_zhTW, "經驗值倍增器:{:.3f} 金錢倍增器:{:.3f}|r"},
{LOCALE_esES, "Multiplicador de XP: {:.3f} Multiplicador de dinero: {:.3f}|r"},
{LOCALE_esMX, "Multiplicador de XP: {:.3f} Multiplicador de dinero: {:.3f}|r"},
{LOCALE_ruRU, "Множитель опыта: {:.3f} Множитель денег: {:.3f}|r"},
};
const std::unordered_map<LocaleConstant, std::string> AB_LEAVING_INSTANCE_COMBAT_CHANGE = {
{LOCALE_enUS, "|cffc3dbff [AutoBalance]|r|cffFF8000 Combat has ended. Difficulty is no longer locked.|r"},
{LOCALE_koKR, "|cffc3dbff [AutoBalance]|r|cffFF8000 전투가 종료되었습니다. 난이도가 더 이상 잠겨 있지 않습니다.|r"},
{LOCALE_frFR, "|cffc3dbff [AutoBalance]|r|cffFF8000 Le combat est terminé. La difficulté n'est plus verrouillée.|r"},
{LOCALE_deDE, "|cffc3dbff [AutoBalance]|r|cffFF8000 Der Kampf ist vorbei. Die Schwierigkeit ist nicht mehr gesperrt.|r"},
{LOCALE_zhCN, "|cffc3dbff [AutoBalance]|r|cffFF8000 战斗结束了。难度不再被锁定。|r"},
{LOCALE_zhTW, "|cffc3dbff [AutoBalance]|r|cffFF8000 戰鬥已結束。難度不再被鎖定。|r"},
{LOCALE_esES, "|cffc3dbff [AutoBalance]|r|cffFF8000 El combate ha terminado. La dificultad ya no está bloqueada.|r"},
{LOCALE_esMX, "|cffc3dbff [AutoBalance]|r|cffFF8000 El combate ha terminado. La dificultad ya no está bloqueada.|r"},
{LOCALE_ruRU, "|cffc3dbff [AutoBalance]|r|cffFF8000 Бой окончен. Сложность больше не заблокирована.|r"},
};
std::unordered_map<std::string, const std::unordered_map<LocaleConstant, std::string>*> abTextMaps = {
{"welcome_to_player", &AB_WELCOME_TO_PLAYER},
{"welcome_to_gm", &AB_WELCOME_TO_GM},
{"announce_non_gm_entering_instance", &AB_ANNOUNCE_NON_GM_ENTERING_INSTANCE},
{"leaving_instance_combat", &AB_LEAVING_INSTANCE_COMBAT},
{"leaving_instance", &AB_LEAVING_INSTANCE},
{"set_offset_command_description", &AB_SET_OFFSET_COMMAND_DESCRIPTION},
{"set_offset_command_success", &AB_SET_OFFSET_COMMAND_SUCCESS},
{"set_offset_command_error", &AB_SET_OFFSET_COMMAND_ERROR},
{"get_offset_command_success", &AB_GET_OFFSET_COMMAND_SUCCESS},
{"adjusted_player_count_combat_locked", &AB_ADJUSTED_PLAYER_COUNT_COMBAT_LOCKED},
{"adjusted_player_count_map_minimum", &AB_ADJUSTED_PLAYER_COUNT_MAP_MINIMUM},
{"adjusted_player_count_map_minimum_difficulty_offset", &AB_ADJUSTED_PLAYER_COUNT_MAP_MINIMUM_DIFFICULTY_OFFSET},
{"adjusted_player_count_difficulty_offset", &AB_ADJUSTED_PLAYER_COUNT_DIFFICULTY_OFFSET},
{"adjusted_player_count", &AB_ADJUSTED_PLAYER_COUNT},
{"lfg_range", &AB_LFG_RANGE},
{"map_level", &AB_MAP_LEVEL},
{"level_scaling_enabled", &AB_LEVEL_SCALING_ENABLED},
{"level_scaling_disabled", &AB_LEVEL_SCALING_DISABLED},
{"world_health_multiplier", &AB_WORLD_HEALTH_MULTIPLIER},
{"world_hostile_damage_healing_multiplier_to", &AB_WORLD_HOSTILE_DAMAGE_HEALING_MULTIPLIER_TO},
{"world_hostile_damage_healing_multiplier", &AB_WORLD_HOSTILE_DAMAGE_HEALING_MULTIPLIER},
{"original_creature_level_range", &AB_ORIGINAL_CREATURE_LEVEL_RANGE},
{"active_total_creatures_in_map", &AB_ACTIVE_TOTAL_CREATURES_IN_MAP},
{"ab_command_only_in_instance", &AB_COMMAND_ONLY_IN_INSTANCE},
{"target_no_in_instance", &AB_TARGET_NO_IN_INSTANCE},
{"active_for_map_stats", &AB_ACTIVE_FOR_MAP_STATS},
{"ignored_for_map_stats", &AB_IGNORED_FOR_MAP_STATS},
{"creature_difficulty_level", &AB_CREATURE_DIFFICULTY_LEVEL},
{"clone_of_summon", &AB_CLONE_OF_SUMMON},
{"summon_of_summon", &AB_SUMMON_OF_SUMMON},
{"summon_without_summoner", &AB_SUMMON_WITHOUT_SUMMONER},
{"health_multiplier_to", &AB_HEALTH_MULTIPLIER_TO},
{"mana_multiplier_to", &AB_MANA_MULTIPLIER_TO},
{"armor_multiplier_to", &AB_ARMOR_MULTIPLIER_TO},
{"damage_multiplier_to", &AB_DAMAGE_MULTIPLIER_TO},
{"health_multiplier", &AB_HEALTH_MULTIPLIER},
{"mana_multiplier", &AB_MANA_MULTIPLIER},
{"armor_multiplier", &AB_ARMOR_MULTIPLIER},
{"damage_multiplier", &AB_DAMAGE_MULTIPLIER},
{"cc_duration_multiplier", &AB_CC_DURATION_MULTIPLIER},
{"xp_money_multiplier", &AB_XP_MONEY_MULTIPLIER},
{"leaving_instance_combat_change", &AB_LEAVING_INSTANCE_COMBAT_CHANGE},
};
std::string ABGetLocaleText(LocaleConstant locale, const std::string& titleType) {
auto textMapIt = abTextMaps.find(titleType);
if (textMapIt != abTextMaps.end())
{
const std::unordered_map<LocaleConstant, std::string>* textMap = textMapIt->second;
auto it = textMap->find(locale);
if (it != textMap->end())
return it->second;
}
return "";
}
+12
View File
@@ -0,0 +1,12 @@
// Message.h
#ifndef AB_MESSAGE_H
#define AB_MESSAGE_H
#include "Common.h"
#include "ItemTemplate.h"
#include <string>
std::string ABGetLocaleText(LocaleConstant locale, const std::string& titleType);
#endif // AB_MESSAGE_H