/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 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 Affero 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 .
*/
/** \file
\ingroup world
*/
#include "World.h"
#include "AccountMgr.h"
#include "AchievementMgr.h"
#include "AddonMgr.h"
#include "ArenaTeamMgr.h"
#include "AsyncAuctionListing.h"
#include "AuctionHouseMgr.h"
#include "BattlefieldMgr.h"
#include "BattlegroundMgr.h"
#include "CalendarMgr.h"
#include "Channel.h"
#include "ChannelMgr.h"
#include "CharacterDatabaseCleaner.h"
#include "Chat.h"
#include "ChatPackets.h"
#include "Common.h"
#include "ConditionMgr.h"
#include "Config.h"
#include "CreatureAIRegistry.h"
#include "CreatureGroups.h"
#include "CreatureTextMgr.h"
#include "DBCStores.h"
#include "DatabaseEnv.h"
#include "DisableMgr.h"
#include "DynamicVisibility.h"
#include "GameEventMgr.h"
#include "GameGraveyard.h"
#include "GameTime.h"
#include "GitRevision.h"
#include "GridNotifiersImpl.h"
#include "GroupMgr.h"
#include "GuildMgr.h"
#include "IPLocation.h"
#include "InstanceSaveMgr.h"
#include "ItemEnchantmentMgr.h"
#include "LFGMgr.h"
#include "Language.h"
#include "Log.h"
#include "LootItemStorage.h"
#include "LootMgr.h"
#include "MMapFactory.h"
#include "MapMgr.h"
#include "Metric.h"
#include "M2Stores.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "OutdoorPvPMgr.h"
#include "PetitionMgr.h"
#include "Player.h"
#include "PlayerDump.h"
#include "PoolMgr.h"
#include "Realm.h"
#include "ScriptMgr.h"
#include "ServerMotd.h"
#include "SkillDiscovery.h"
#include "SkillExtraItems.h"
#include "SmartAI.h"
#include "SpellMgr.h"
#include "TaskScheduler.h"
#include "TicketMgr.h"
#include "Transport.h"
#include "TransportMgr.h"
#include "UpdateTime.h"
#include "Util.h"
#include "VMapFactory.h"
#include "VMapMgr2.h"
#include "Vehicle.h"
#include "Warden.h"
#include "WardenCheckMgr.h"
#include "WaypointMovementGenerator.h"
#include "WeatherMgr.h"
#include "WhoListCacheMgr.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include
#include
namespace
{
TaskScheduler playersSaveScheduler;
}
std::atomic_long World::m_stopEvent = false;
uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
uint32 World::m_worldLoopCounter = 0;
float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
Realm realm;
/// World constructor
World::World()
{
m_playerLimit = 0;
m_allowedSecurityLevel = SEC_PLAYER;
m_allowMovement = true;
m_ShutdownMask = 0;
m_ShutdownTimer = 0;
m_maxActiveSessionCount = 0;
m_maxQueuedSessionCount = 0;
m_PlayerCount = 0;
m_MaxPlayerCount = 0;
m_NextDailyQuestReset = 0s;
m_NextWeeklyQuestReset = 0s;
m_NextMonthlyQuestReset = 0s;
m_NextRandomBGReset = 0s;
m_NextCalendarOldEventsDeletionTime = 0s;
m_NextGuildReset = 0s;
m_defaultDbcLocale = LOCALE_enUS;
mail_expire_check_timer = 0s;
m_isClosed = false;
m_CleaningFlags = 0;
memset(rate_values, 0, sizeof(rate_values));
memset(m_int_configs, 0, sizeof(m_int_configs));
memset(m_bool_configs, 0, sizeof(m_bool_configs));
memset(m_float_configs, 0, sizeof(m_float_configs));
}
/// World destructor
World::~World()
{
///- Empty the kicked session set
while (!m_sessions.empty())
{
// not remove from queue, prevent loading new sessions
delete m_sessions.begin()->second;
m_sessions.erase(m_sessions.begin());
}
while (!m_offlineSessions.empty())
{
delete m_offlineSessions.begin()->second;
m_offlineSessions.erase(m_offlineSessions.begin());
}
CliCommandHolder* command = nullptr;
while (cliCmdQueue.next(command))
delete command;
VMAP::VMapFactory::clear();
MMAP::MMapFactory::clear();
//TODO free addSessQueue
}
std::unique_ptr& getWorldInstance()
{
static std::unique_ptr instance = std::make_unique();
return instance;
}
/// Find a player in a specified zone
Player* World::FindPlayerInZone(uint32 zone)
{
///- circle through active sessions and return the first player found in the zone
SessionMap::const_iterator itr;
for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
{
if (!itr->second)
continue;
Player* player = itr->second->GetPlayer();
if (!player)
continue;
if (player->IsInWorld() && player->GetZoneId() == zone)
return player;
}
return nullptr;
}
bool World::IsClosed() const
{
return m_isClosed;
}
void World::SetClosed(bool val)
{
m_isClosed = val;
// Invert the value, for simplicity for scripters.
sScriptMgr->OnOpenStateChange(!val);
}
/// Find a session by its id
WorldSession* World::FindSession(uint32 id) const
{
SessionMap::const_iterator itr = m_sessions.find(id);
if (itr != m_sessions.end())
return itr->second; // also can return nullptr for kicked session
else
return nullptr;
}
WorldSession* World::FindOfflineSession(uint32 id) const
{
SessionMap::const_iterator itr = m_offlineSessions.find(id);
if (itr != m_offlineSessions.end())
return itr->second;
else
return nullptr;
}
WorldSession* World::FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const
{
if (m_offlineSessions.empty())
return nullptr;
for (SessionMap::const_iterator itr = m_offlineSessions.begin(); itr != m_offlineSessions.end(); ++itr)
if (itr->second->GetGuidLow() == guidLow)
return itr->second;
return nullptr;
}
/// Remove a given session
bool World::KickSession(uint32 id)
{
///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation
SessionMap::const_iterator itr = m_sessions.find(id);
if (itr != m_sessions.end() && itr->second)
{
if (itr->second->PlayerLoading())
return false;
itr->second->KickPlayer("KickSession", false);
}
return true;
}
void World::AddSession(WorldSession* s)
{
addSessQueue.add(s);
}
void World::AddSession_(WorldSession* s)
{
ASSERT (s);
// kick existing session with same account (if any)
// if character on old session is being loaded, then return
if (!KickSession(s->GetAccountId()))
{
s->KickPlayer("kick existing session with same account");
delete s; // session not added yet in session list, so not listed in queue
return;
}
SessionMap::const_iterator old = m_sessions.find(s->GetAccountId());
if (old != m_sessions.end())
{
WorldSession* oldSession = old->second;
if (!RemoveQueuedPlayer(oldSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
m_disconnects[s->GetAccountId()] = GameTime::GetGameTime().count();
// pussywizard:
if (oldSession->HandleSocketClosed())
{
// there should be no offline session if current one is logged onto a character
SessionMap::iterator iter;
if ((iter = m_offlineSessions.find(oldSession->GetAccountId())) != m_offlineSessions.end())
{
WorldSession* tmp = iter->second;
m_offlineSessions.erase(iter);
tmp->SetShouldSetOfflineInDB(false);
delete tmp;
}
oldSession->SetOfflineTime(GameTime::GetGameTime().count());
m_offlineSessions[oldSession->GetAccountId()] = oldSession;
}
else
{
oldSession->SetShouldSetOfflineInDB(false); // pussywizard: don't set offline in db because new session for that acc is already created
delete oldSession;
}
}
m_sessions[s->GetAccountId()] = s;
uint32 Sessions = GetActiveAndQueuedSessionCount();
uint32 pLimit = GetPlayerAmountLimit();
// don't count this session when checking player limit
--Sessions;
if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !s->CanSkipQueue() && !HasRecentlyDisconnected(s))
{
AddQueuedPlayer (s);
UpdateMaxSessionCounters();
return;
}
s->SendAuthResponse(AUTH_OK, true);
FinalizePlayerWorldSession(s);
UpdateMaxSessionCounters();
}
bool World::HasRecentlyDisconnected(WorldSession* session)
{
if (!session)
return false;
if (uint32 tolerance = getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
{
for (DisconnectMap::iterator i = m_disconnects.begin(); i != m_disconnects.end();)
{
if ((GameTime::GetGameTime().count() - i->second) < tolerance)
{
if (i->first == session->GetAccountId())
return true;
++i;
}
else
m_disconnects.erase(i++);
}
}
return false;
}
int32 World::GetQueuePos(WorldSession* sess)
{
uint32 position = 1;
for (Queue::const_iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position)
if ((*iter) == sess)
return position;
return 0;
}
void World::AddQueuedPlayer(WorldSession* sess)
{
sess->SetInQueue(true);
m_QueuedPlayer.push_back(sess);
// The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
sess->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(sess));
}
bool World::RemoveQueuedPlayer(WorldSession* sess)
{
uint32 sessions = GetActiveSessionCount();
uint32 position = 1;
Queue::iterator iter = m_QueuedPlayer.begin();
// search to remove and count skipped positions
bool found = false;
for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
{
if (*iter == sess)
{
sess->SetInQueue(false);
sess->ResetTimeOutTime(false);
iter = m_QueuedPlayer.erase(iter);
found = true;
break;
}
}
// if session not queued then it was an active session
if (!found)
{
ASSERT(sessions > 0);
--sessions;
}
// accept first in queue
if ((!GetPlayerAmountLimit() || sessions < GetPlayerAmountLimit()) && !m_QueuedPlayer.empty())
{
WorldSession* pop_sess = m_QueuedPlayer.front();
pop_sess->SetInQueue(false);
pop_sess->ResetTimeOutTime(false);
pop_sess->SendAuthWaitQueue(0);
pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK);
FinalizePlayerWorldSession(pop_sess);
m_QueuedPlayer.pop_front();
// update iter to point first queued socket or end() if queue is empty now
iter = m_QueuedPlayer.begin();
position = 1;
}
// update queue position from iter to end()
for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
(*iter)->SendAuthWaitQueue(position);
return found;
}
/// Initialize config values
void World::LoadConfigSettings(bool reload)
{
if (reload)
{
if (!sConfigMgr->Reload())
{
LOG_ERROR("server.loading", "World settings reload fail: can't read settings.");
return;
}
sLog->LoadFromConfig();
sMetric->LoadFromConfigs();
}
// Set realm id and enable db logging
sLog->SetRealmId(realm.Id.Realm);
sScriptMgr->OnBeforeConfigLoad(reload);
// load update time related configs
sWorldUpdateTime.LoadFromConfig();
///- Read the player limit and the Message of the day from the config file
if (!reload)
{
SetPlayerAmountLimit(sConfigMgr->GetOption("PlayerLimit", 1000));
}
Motd::SetMotd(sConfigMgr->GetOption("Motd", "Welcome to an AzerothCore server"));
///- Read ticket system setting from the config file
m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetOption("AllowTickets", true);
m_bool_configs[CONFIG_DELETE_CHARACTER_TICKET_TRACE] = sConfigMgr->GetOption("DeletedCharacterTicketTrace", false);
///- Get string for new logins (newly created characters)
SetNewCharString(sConfigMgr->GetOption("PlayerStart.String", ""));
///- Send server info on login?
m_int_configs[CONFIG_ENABLE_SINFO_LOGIN] = sConfigMgr->GetOption("Server.LoginInfo", 0);
///- Read all rates from the config file
rate_values[RATE_HEALTH] = sConfigMgr->GetOption("Rate.Health", 1);
if (rate_values[RATE_HEALTH] < 0)
{
LOG_ERROR("server.loading", "Rate.Health ({}) must be > 0. Using 1 instead.", rate_values[RATE_HEALTH]);
rate_values[RATE_HEALTH] = 1;
}
rate_values[RATE_POWER_MANA] = sConfigMgr->GetOption("Rate.Mana", 1);
if (rate_values[RATE_POWER_MANA] < 0)
{
LOG_ERROR("server.loading", "Rate.Mana ({}) must be > 0. Using 1 instead.", rate_values[RATE_POWER_MANA]);
rate_values[RATE_POWER_MANA] = 1;
}
rate_values[RATE_POWER_RAGE_INCOME] = sConfigMgr->GetOption("Rate.Rage.Income", 1);
rate_values[RATE_POWER_RAGE_LOSS] = sConfigMgr->GetOption("Rate.Rage.Loss", 1);
if (rate_values[RATE_POWER_RAGE_LOSS] < 0)
{
LOG_ERROR("server.loading", "Rate.Rage.Loss ({}) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RAGE_LOSS]);
rate_values[RATE_POWER_RAGE_LOSS] = 1;
}
rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfigMgr->GetOption("Rate.RunicPower.Income", 1);
rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfigMgr->GetOption("Rate.RunicPower.Loss", 1);
if (rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0)
{
LOG_ERROR("server.loading", "Rate.RunicPower.Loss ({}) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RUNICPOWER_LOSS]);
rate_values[RATE_POWER_RUNICPOWER_LOSS] = 1;
}
rate_values[RATE_POWER_FOCUS] = sConfigMgr->GetOption("Rate.Focus", 1.0f);
rate_values[RATE_POWER_ENERGY] = sConfigMgr->GetOption("Rate.Energy", 1.0f);
rate_values[RATE_SKILL_DISCOVERY] = sConfigMgr->GetOption("Rate.Skill.Discovery", 1.0f);
rate_values[RATE_DROP_ITEM_POOR] = sConfigMgr->GetOption("Rate.Drop.Item.Poor", 1.0f);
rate_values[RATE_DROP_ITEM_NORMAL] = sConfigMgr->GetOption("Rate.Drop.Item.Normal", 1.0f);
rate_values[RATE_DROP_ITEM_UNCOMMON] = sConfigMgr->GetOption("Rate.Drop.Item.Uncommon", 1.0f);
rate_values[RATE_DROP_ITEM_RARE] = sConfigMgr->GetOption("Rate.Drop.Item.Rare", 1.0f);
rate_values[RATE_DROP_ITEM_EPIC] = sConfigMgr->GetOption("Rate.Drop.Item.Epic", 1.0f);
rate_values[RATE_DROP_ITEM_LEGENDARY] = sConfigMgr->GetOption("Rate.Drop.Item.Legendary", 1.0f);
rate_values[RATE_DROP_ITEM_ARTIFACT] = sConfigMgr->GetOption("Rate.Drop.Item.Artifact", 1.0f);
rate_values[RATE_DROP_ITEM_REFERENCED] = sConfigMgr->GetOption("Rate.Drop.Item.Referenced", 1.0f);
rate_values[RATE_DROP_ITEM_REFERENCED_AMOUNT] = sConfigMgr->GetOption("Rate.Drop.Item.ReferencedAmount", 1.0f);
rate_values[RATE_DROP_MONEY] = sConfigMgr->GetOption("Rate.Drop.Money", 1.0f);
rate_values[RATE_REWARD_BONUS_MONEY] = sConfigMgr->GetOption("Rate.RewardBonusMoney", 1.0f);
rate_values[RATE_XP_KILL] = sConfigMgr->GetOption("Rate.XP.Kill", 1.0f);
rate_values[RATE_XP_BG_KILL_AV] = sConfigMgr->GetOption("Rate.XP.BattlegroundKillAV", 1.0f);
rate_values[RATE_XP_BG_KILL_WSG] = sConfigMgr->GetOption("Rate.XP.BattlegroundKillWSG", 1.0f);
rate_values[RATE_XP_BG_KILL_AB] = sConfigMgr->GetOption("Rate.XP.BattlegroundKillAB", 1.0f);
rate_values[RATE_XP_BG_KILL_EOTS] = sConfigMgr->GetOption("Rate.XP.BattlegroundKillEOTS", 1.0f);
rate_values[RATE_XP_BG_KILL_SOTA] = sConfigMgr->GetOption("Rate.XP.BattlegroundKillSOTA", 1.0f);
rate_values[RATE_XP_BG_KILL_IC] = sConfigMgr->GetOption("Rate.XP.BattlegroundKillIC", 1.0f);
rate_values[RATE_XP_QUEST] = sConfigMgr->GetOption("Rate.XP.Quest", 1.0f);
rate_values[RATE_XP_QUEST_DF] = sConfigMgr->GetOption("Rate.XP.Quest.DF", 1.0f);
rate_values[RATE_XP_EXPLORE] = sConfigMgr->GetOption("Rate.XP.Explore", 1.0f);
rate_values[RATE_XP_PET] = sConfigMgr->GetOption("Rate.XP.Pet", 1.0f);
rate_values[RATE_XP_PET_NEXT_LEVEL] = sConfigMgr->GetOption("Rate.Pet.LevelXP", 0.05f);
rate_values[RATE_REPAIRCOST] = sConfigMgr->GetOption("Rate.RepairCost", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_POOR] = sConfigMgr->GetOption("Rate.SellValue.Item.Poor", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_NORMAL] = sConfigMgr->GetOption("Rate.SellValue.Item.Normal", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_UNCOMMON] = sConfigMgr->GetOption("Rate.SellValue.Item.Uncommon", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_RARE] = sConfigMgr->GetOption("Rate.SellValue.Item.Rare", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_EPIC] = sConfigMgr->GetOption("Rate.SellValue.Item.Epic", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_LEGENDARY] = sConfigMgr->GetOption("Rate.SellValue.Item.Legendary", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_ARTIFACT] = sConfigMgr->GetOption("Rate.SellValue.Item.Artifact", 1.0f);
rate_values[RATE_SELLVALUE_ITEM_HEIRLOOM] = sConfigMgr->GetOption("Rate.SellValue.Item.Heirloom", 1.0f);
rate_values[ RATE_BUYVALUE_ITEM_POOR] = sConfigMgr->GetOption("Rate.BuyValue.Item.Poor", 1.0f);
rate_values[ RATE_BUYVALUE_ITEM_NORMAL] = sConfigMgr->GetOption("Rate.BuyValue.Item.Normal", 1.0f);
rate_values[ RATE_BUYVALUE_ITEM_UNCOMMON] = sConfigMgr->GetOption("Rate.BuyValue.Item.Uncommon", 1.0f);
rate_values[ RATE_BUYVALUE_ITEM_RARE] = sConfigMgr->GetOption("Rate.BuyValue.Item.Rare", 1.0f);
rate_values[ RATE_BUYVALUE_ITEM_EPIC] = sConfigMgr->GetOption("Rate.BuyValue.Item.Epic", 1.0f);
rate_values[ RATE_BUYVALUE_ITEM_LEGENDARY] = sConfigMgr->GetOption("Rate.BuyValue.Item.Legendary", 1.0f);
rate_values[RATE_BUYVALUE_ITEM_ARTIFACT] = sConfigMgr->GetOption("Rate.BuyValue.Item.Artifact", 1.0f);
rate_values[RATE_BUYVALUE_ITEM_HEIRLOOM] = sConfigMgr->GetOption("Rate.BuyValue.Item.Heirloom", 1.0f);
if (rate_values[RATE_REPAIRCOST] < 0.0f)
{
LOG_ERROR("server.loading", "Rate.RepairCost ({}) must be >=0. Using 0.0 instead.", rate_values[RATE_REPAIRCOST]);
rate_values[RATE_REPAIRCOST] = 0.0f;
}
rate_values[RATE_REPUTATION_GAIN] = sConfigMgr->GetOption("Rate.Reputation.Gain", 1.0f);
rate_values[RATE_REPUTATION_LOWLEVEL_KILL] = sConfigMgr->GetOption("Rate.Reputation.LowLevel.Kill", 1.0f);
rate_values[RATE_REPUTATION_LOWLEVEL_QUEST] = sConfigMgr->GetOption("Rate.Reputation.LowLevel.Quest", 1.0f);
rate_values[RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS] = sConfigMgr->GetOption("Rate.Reputation.RecruitAFriendBonus", 0.1f);
rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfigMgr->GetOption("Rate.Creature.Normal.Damage", 1.0f);
rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.Elite.Damage", 1.0f);
rate_values[RATE_CREATURE_ELITE_RAREELITE_DAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.RAREELITE.Damage", 1.0f);
rate_values[RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.WORLDBOSS.Damage", 1.0f);
rate_values[RATE_CREATURE_ELITE_RARE_DAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.RARE.Damage", 1.0f);
rate_values[RATE_CREATURE_NORMAL_HP] = sConfigMgr->GetOption("Rate.Creature.Normal.HP", 1.0f);
rate_values[RATE_CREATURE_ELITE_ELITE_HP] = sConfigMgr->GetOption("Rate.Creature.Elite.Elite.HP", 1.0f);
rate_values[RATE_CREATURE_ELITE_RAREELITE_HP] = sConfigMgr->GetOption("Rate.Creature.Elite.RAREELITE.HP", 1.0f);
rate_values[RATE_CREATURE_ELITE_WORLDBOSS_HP] = sConfigMgr->GetOption("Rate.Creature.Elite.WORLDBOSS.HP", 1.0f);
rate_values[RATE_CREATURE_ELITE_RARE_HP] = sConfigMgr->GetOption("Rate.Creature.Elite.RARE.HP", 1.0f);
rate_values[RATE_CREATURE_NORMAL_SPELLDAMAGE] = sConfigMgr->GetOption("Rate.Creature.Normal.SpellDamage", 1.0f);
rate_values[RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.Elite.SpellDamage", 1.0f);
rate_values[RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.RAREELITE.SpellDamage", 1.0f);
rate_values[RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.WORLDBOSS.SpellDamage", 1.0f);
rate_values[RATE_CREATURE_ELITE_RARE_SPELLDAMAGE] = sConfigMgr->GetOption("Rate.Creature.Elite.RARE.SpellDamage", 1.0f);
rate_values[RATE_CREATURE_AGGRO] = sConfigMgr->GetOption("Rate.Creature.Aggro", 1.0f);
rate_values[RATE_REST_INGAME] = sConfigMgr->GetOption("Rate.Rest.InGame", 1.0f);
rate_values[RATE_REST_OFFLINE_IN_TAVERN_OR_CITY] = sConfigMgr->GetOption("Rate.Rest.Offline.InTavernOrCity", 1.0f);
rate_values[RATE_REST_OFFLINE_IN_WILDERNESS] = sConfigMgr->GetOption("Rate.Rest.Offline.InWilderness", 1.0f);
rate_values[RATE_DAMAGE_FALL] = sConfigMgr->GetOption("Rate.Damage.Fall", 1.0f);
rate_values[RATE_AUCTION_TIME] = sConfigMgr->GetOption("Rate.Auction.Time", 1.0f);
rate_values[RATE_AUCTION_DEPOSIT] = sConfigMgr->GetOption("Rate.Auction.Deposit", 1.0f);
rate_values[RATE_AUCTION_CUT] = sConfigMgr->GetOption("Rate.Auction.Cut", 1.0f);
rate_values[RATE_HONOR] = sConfigMgr->GetOption("Rate.Honor", 1.0f);
rate_values[RATE_ARENA_POINTS] = sConfigMgr->GetOption("Rate.ArenaPoints", 1.0f);
rate_values[RATE_INSTANCE_RESET_TIME] = sConfigMgr->GetOption("Rate.InstanceResetTime", 1.0f);
rate_values[RATE_MISS_CHANCE_MULTIPLIER_TARGET_CREATURE] = sConfigMgr->GetOption("Rate.MissChanceMultiplier.TargetCreature", 11.0f);
rate_values[RATE_MISS_CHANCE_MULTIPLIER_TARGET_PLAYER] = sConfigMgr->GetOption("Rate.MissChanceMultiplier.TargetPlayer", 7.0f);
m_bool_configs[CONFIG_MISS_CHANCE_MULTIPLIER_ONLY_FOR_PLAYERS] = sConfigMgr->GetOption("Rate.MissChanceMultiplier.OnlyAffectsPlayer", false);
rate_values[RATE_TALENT] = sConfigMgr->GetOption("Rate.Talent", 1.0f);
if (rate_values[RATE_TALENT] < 0.0f)
{
LOG_ERROR("server.loading", "Rate.Talent ({}) must be > 0. Using 1 instead.", rate_values[RATE_TALENT]);
rate_values[RATE_TALENT] = 1.0f;
}
rate_values[RATE_MOVESPEED] = sConfigMgr->GetOption("Rate.MoveSpeed", 1.0f);
if (rate_values[RATE_MOVESPEED] < 0)
{
LOG_ERROR("server.loading", "Rate.MoveSpeed ({}) must be > 0. Using 1 instead.", rate_values[RATE_MOVESPEED]);
rate_values[RATE_MOVESPEED] = 1.0f;
}
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) playerBaseMoveSpeed[i] = baseMoveSpeed[i] * rate_values[RATE_MOVESPEED];
rate_values[RATE_CORPSE_DECAY_LOOTED] = sConfigMgr->GetOption("Rate.Corpse.Decay.Looted", 0.5f);
rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = sConfigMgr->GetOption("TargetPosRecalculateRange", 1.5f);
if (rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] < CONTACT_DISTANCE)
{
LOG_ERROR("server.loading", "TargetPosRecalculateRange ({}) must be >= {}. Using {} instead.", rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], CONTACT_DISTANCE, CONTACT_DISTANCE);
rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = CONTACT_DISTANCE;
}
else if (rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] > NOMINAL_MELEE_RANGE)
{
LOG_ERROR("server.loading", "TargetPosRecalculateRange ({}) must be <= {}. Using {} instead.",
rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], NOMINAL_MELEE_RANGE, NOMINAL_MELEE_RANGE);
rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = NOMINAL_MELEE_RANGE;
}
rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = sConfigMgr->GetOption("DurabilityLoss.OnDeath", 10.0f);
if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] < 0.0f)
{
LOG_ERROR("server.loading", "DurabilityLoss.OnDeath ({}) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
}
if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] > 100.0f)
{
LOG_ERROR("server.loading", "DurabilityLoss.OnDeath ({}) must be <= 100. Using 100.0 instead.", rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = rate_values[RATE_DURABILITY_LOSS_ON_DEATH] / 100.0f;
rate_values[RATE_DURABILITY_LOSS_DAMAGE] = sConfigMgr->GetOption("DurabilityLossChance.Damage", 0.5f);
if (rate_values[RATE_DURABILITY_LOSS_DAMAGE] < 0.0f)
{
LOG_ERROR("server.loading", "DurabilityLossChance.Damage ({}) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_DAMAGE]);
rate_values[RATE_DURABILITY_LOSS_DAMAGE] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_ABSORB] = sConfigMgr->GetOption("DurabilityLossChance.Absorb", 0.5f);
if (rate_values[RATE_DURABILITY_LOSS_ABSORB] < 0.0f)
{
LOG_ERROR("server.loading", "DurabilityLossChance.Absorb ({}) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_ABSORB]);
rate_values[RATE_DURABILITY_LOSS_ABSORB] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_PARRY] = sConfigMgr->GetOption("DurabilityLossChance.Parry", 0.05f);
if (rate_values[RATE_DURABILITY_LOSS_PARRY] < 0.0f)
{
LOG_ERROR("server.loading", "DurabilityLossChance.Parry ({}) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_PARRY]);
rate_values[RATE_DURABILITY_LOSS_PARRY] = 0.0f;
}
rate_values[RATE_DURABILITY_LOSS_BLOCK] = sConfigMgr->GetOption("DurabilityLossChance.Block", 0.05f);
if (rate_values[RATE_DURABILITY_LOSS_BLOCK] < 0.0f)
{
LOG_ERROR("server.loading", "DurabilityLossChance.Block ({}) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_BLOCK]);
rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f;
}
///- Read other configuration items from the config file
m_bool_configs[CONFIG_DURABILITY_LOSS_IN_PVP] = sConfigMgr->GetOption("DurabilityLoss.InPvP", false);
m_int_configs[CONFIG_COMPRESSION] = sConfigMgr->GetOption("Compression", 1);
if (m_int_configs[CONFIG_COMPRESSION] < 1 || m_int_configs[CONFIG_COMPRESSION] > 9)
{
LOG_ERROR("server.loading", "Compression level ({}) must be in range 1..9. Using default compression level (1).", m_int_configs[CONFIG_COMPRESSION]);
m_int_configs[CONFIG_COMPRESSION] = 1;
}
m_bool_configs[CONFIG_ADDON_CHANNEL] = sConfigMgr->GetOption("AddonChannel", true);
m_bool_configs[CONFIG_CLEAN_CHARACTER_DB] = sConfigMgr->GetOption("CleanCharacterDB", false);
m_int_configs[CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS] = sConfigMgr->GetOption("PersistentCharacterCleanFlags", 0);
m_int_configs[CONFIG_CHAT_CHANNEL_LEVEL_REQ] = sConfigMgr->GetOption("ChatLevelReq.Channel", 1);
m_int_configs[CONFIG_CHAT_WHISPER_LEVEL_REQ] = sConfigMgr->GetOption("ChatLevelReq.Whisper", 1);
m_int_configs[CONFIG_CHAT_SAY_LEVEL_REQ] = sConfigMgr->GetOption("ChatLevelReq.Say", 1);
m_int_configs[CONFIG_PARTY_LEVEL_REQ] = sConfigMgr->GetOption("PartyLevelReq", 1);
m_int_configs[CONFIG_TRADE_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Trade", 1);
m_int_configs[CONFIG_TICKET_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Ticket", 1);
m_int_configs[CONFIG_AUCTION_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Auction", 1);
m_int_configs[CONFIG_MAIL_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Mail", 1);
m_bool_configs[CONFIG_ALLOW_PLAYER_COMMANDS] = sConfigMgr->GetOption("AllowPlayerCommands", 1);
m_bool_configs[CONFIG_PRESERVE_CUSTOM_CHANNELS] = sConfigMgr->GetOption("PreserveCustomChannels", false);
m_int_configs[CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION] = sConfigMgr->GetOption("PreserveCustomChannelDuration", 14);
m_int_configs[CONFIG_INTERVAL_SAVE] = sConfigMgr->GetOption("PlayerSaveInterval", 15 * MINUTE * IN_MILLISECONDS);
m_int_configs[CONFIG_INTERVAL_DISCONNECT_TOLERANCE] = sConfigMgr->GetOption("DisconnectToleranceInterval", 0);
m_bool_configs[CONFIG_STATS_SAVE_ONLY_ON_LOGOUT] = sConfigMgr->GetOption("PlayerSave.Stats.SaveOnlyOnLogout", true);
m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = sConfigMgr->GetOption("PlayerSave.Stats.MinLevel", 0);
if (m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] > MAX_LEVEL || int32(m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]) < 0)
{
LOG_ERROR("server.loading", "PlayerSave.Stats.MinLevel ({}) must be in range 0..80. Using default, do not save character stats (0).", m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]);
m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
}
m_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption("MapUpdateInterval", 100);
if (m_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
{
LOG_ERROR("server.loading", "MapUpdateInterval ({}) must be greater {}. Use this minimal value.", m_int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
m_int_configs[CONFIG_INTERVAL_MAPUPDATE] = MIN_MAP_UPDATE_DELAY;
}
if (reload)
sMapMgr->SetMapUpdateInterval(m_int_configs[CONFIG_INTERVAL_MAPUPDATE]);
m_int_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfigMgr->GetOption("ChangeWeatherInterval", 10 * MINUTE * IN_MILLISECONDS);
if (reload)
{
uint32 val = sConfigMgr->GetOption("WorldServerPort", 8085);
if (val != m_int_configs[CONFIG_PORT_WORLD])
LOG_ERROR("server.loading", "WorldServerPort option can't be changed at worldserver.conf reload, using current value ({}).", m_int_configs[CONFIG_PORT_WORLD]);
}
else
m_int_configs[CONFIG_PORT_WORLD] = sConfigMgr->GetOption("WorldServerPort", 8085);
m_bool_configs[CONFIG_CLOSE_IDLE_CONNECTIONS] = sConfigMgr->GetOption("CloseIdleConnections", true);
m_int_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfigMgr->GetOption("SocketTimeOutTime", 900000);
m_int_configs[CONFIG_SOCKET_TIMEOUTTIME_ACTIVE] = sConfigMgr->GetOption("SocketTimeOutTimeActive", 60000);
m_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfigMgr->GetOption("SessionAddDelay", 10000);
m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetOption("MaxGroupXPDistance", 74.0f);
m_float_configs[CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE] = sConfigMgr->GetOption("MaxRecruitAFriendBonusDistance", 100.0f);
/// \todo Add MonsterSight in worldserver.conf or put it as define
m_float_configs[CONFIG_SIGHT_MONSTER] = sConfigMgr->GetOption("MonsterSight", 50);
if (reload)
{
uint32 val = sConfigMgr->GetOption("GameType", 0);
if (val != m_int_configs[CONFIG_GAME_TYPE])
LOG_ERROR("server.loading", "GameType option can't be changed at worldserver.conf reload, using current value ({}).", m_int_configs[CONFIG_GAME_TYPE]);
}
else
m_int_configs[CONFIG_GAME_TYPE] = sConfigMgr->GetOption("GameType", 0);
if (reload)
{
uint32 val = sConfigMgr->GetOption("RealmZone", REALM_ZONE_DEVELOPMENT);
if (val != m_int_configs[CONFIG_REALM_ZONE])
LOG_ERROR("server.loading", "RealmZone option can't be changed at worldserver.conf reload, using current value ({}).", m_int_configs[CONFIG_REALM_ZONE]);
}
else
m_int_configs[CONFIG_REALM_ZONE] = sConfigMgr->GetOption("RealmZone", REALM_ZONE_DEVELOPMENT);
m_int_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfigMgr->GetOption ("StrictPlayerNames", 0);
m_int_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfigMgr->GetOption ("StrictCharterNames", 0);
m_int_configs[CONFIG_STRICT_CHANNEL_NAMES] = sConfigMgr->GetOption ("StrictChannelNames", 0);
m_int_configs[CONFIG_STRICT_PET_NAMES] = sConfigMgr->GetOption ("StrictPetNames", 0);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfigMgr->GetOption("AllowTwoSide.Accounts", true);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Calendar", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Chat", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Channel", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Group", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Guild", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Auction", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Mail", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfigMgr->GetOption("AllowTwoSide.WhoList", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfigMgr->GetOption("AllowTwoSide.AddFriend", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfigMgr->GetOption("AllowTwoSide.Trade", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Emote", false);
m_int_configs[CONFIG_MIN_PLAYER_NAME] = sConfigMgr->GetOption ("MinPlayerName", 2);
if (m_int_configs[CONFIG_MIN_PLAYER_NAME] < 1 || m_int_configs[CONFIG_MIN_PLAYER_NAME] > MAX_PLAYER_NAME)
{
LOG_ERROR("server.loading", "MinPlayerName ({}) must be in range 1..{}. Set to 2.", m_int_configs[CONFIG_MIN_PLAYER_NAME], MAX_PLAYER_NAME);
m_int_configs[CONFIG_MIN_PLAYER_NAME] = 2;
}
m_int_configs[CONFIG_MIN_CHARTER_NAME] = sConfigMgr->GetOption ("MinCharterName", 2);
if (m_int_configs[CONFIG_MIN_CHARTER_NAME] < 1 || m_int_configs[CONFIG_MIN_CHARTER_NAME] > MAX_CHARTER_NAME)
{
LOG_ERROR("server.loading", "MinCharterName ({}) must be in range 1..{}. Set to 2.", m_int_configs[CONFIG_MIN_CHARTER_NAME], MAX_CHARTER_NAME);
m_int_configs[CONFIG_MIN_CHARTER_NAME] = 2;
}
m_int_configs[CONFIG_MIN_PET_NAME] = sConfigMgr->GetOption ("MinPetName", 2);
if (m_int_configs[CONFIG_MIN_PET_NAME] < 1 || m_int_configs[CONFIG_MIN_PET_NAME] > MAX_PET_NAME)
{
LOG_ERROR("server.loading", "MinPetName ({}) must be in range 1..{}. Set to 2.", m_int_configs[CONFIG_MIN_PET_NAME], MAX_PET_NAME);
m_int_configs[CONFIG_MIN_PET_NAME] = 2;
}
m_int_configs[CONFIG_CHARTER_COST_GUILD] = sConfigMgr->GetOption("Guild.CharterCost", 1000);
m_int_configs[CONFIG_CHARTER_COST_ARENA_2v2] = sConfigMgr->GetOption("ArenaTeam.CharterCost.2v2", 800000);
m_int_configs[CONFIG_CHARTER_COST_ARENA_3v3] = sConfigMgr->GetOption("ArenaTeam.CharterCost.3v3", 1200000);
m_int_configs[CONFIG_CHARTER_COST_ARENA_5v5] = sConfigMgr->GetOption("ArenaTeam.CharterCost.5v5", 2000000);
m_int_configs[CONFIG_MAX_WHO_LIST_RETURN] = sConfigMgr->GetOption("MaxWhoListReturns", 49);
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED] = sConfigMgr->GetOption("CharacterCreating.Disabled", 0);
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfigMgr->GetOption("CharacterCreating.Disabled.RaceMask", 0);
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfigMgr->GetOption("CharacterCreating.Disabled.ClassMask", 0);
m_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfigMgr->GetOption("CharactersPerRealm", 10);
if (m_int_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_int_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
{
LOG_ERROR("server.loading", "CharactersPerRealm ({}) must be in range 1..10. Set to 10.", m_int_configs[CONFIG_CHARACTERS_PER_REALM]);
m_int_configs[CONFIG_CHARACTERS_PER_REALM] = 10;
}
// must be after CONFIG_CHARACTERS_PER_REALM
m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfigMgr->GetOption("CharactersPerAccount", 50);
if (m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] < m_int_configs[CONFIG_CHARACTERS_PER_REALM])
{
LOG_ERROR("server.loading", "CharactersPerAccount ({}) can't be less than CharactersPerRealm ({}).", m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT], m_int_configs[CONFIG_CHARACTERS_PER_REALM]);
m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_int_configs[CONFIG_CHARACTERS_PER_REALM];
}
m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfigMgr->GetOption("HeroicCharactersPerRealm", 1);
if (int32(m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]) < 0 || m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10)
{
LOG_ERROR("server.loading", "HeroicCharactersPerRealm ({}) must be in range 0..10. Set to 1.", m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]);
m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1;
}
m_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER] = sConfigMgr->GetOption("CharacterCreating.MinLevelForHeroicCharacter", 55);
m_int_configs[CONFIG_SKIP_CINEMATICS] = sConfigMgr->GetOption("SkipCinematics", 0);
if (int32(m_int_configs[CONFIG_SKIP_CINEMATICS]) < 0 || m_int_configs[CONFIG_SKIP_CINEMATICS] > 2)
{
LOG_ERROR("server.loading", "SkipCinematics ({}) must be in range 0..2. Set to 0.", m_int_configs[CONFIG_SKIP_CINEMATICS]);
m_int_configs[CONFIG_SKIP_CINEMATICS] = 0;
}
if (reload)
{
uint32 val = sConfigMgr->GetOption("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
if (val != m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
LOG_ERROR("server.loading", "MaxPlayerLevel option can't be changed at config reload, using current value ({}).", m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
}
else
m_int_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfigMgr->GetOption("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
if (m_int_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL || m_int_configs[CONFIG_MAX_PLAYER_LEVEL] < 1)
{
LOG_ERROR("server.loading", "MaxPlayerLevel ({}) must be in range 1..{}. Set to {}.", m_int_configs[CONFIG_MAX_PLAYER_LEVEL], MAX_LEVEL, MAX_LEVEL);
m_int_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL;
}
m_int_configs[CONFIG_MIN_DUALSPEC_LEVEL] = sConfigMgr->GetOption("MinDualSpecLevel", 40);
m_int_configs[CONFIG_START_PLAYER_LEVEL] = sConfigMgr->GetOption("StartPlayerLevel", 1);
if (m_int_configs[CONFIG_START_PLAYER_LEVEL] < 1 || m_int_configs[CONFIG_START_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
{
LOG_ERROR("server.loading", "StartPlayerLevel ({}) must be in range 1..MaxPlayerLevel({}). Set to 1.", m_int_configs[CONFIG_START_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
m_int_configs[CONFIG_START_PLAYER_LEVEL] = 1;
}
m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfigMgr->GetOption("StartHeroicPlayerLevel", 55);
if (m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1 || m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
{
LOG_ERROR("server.loading", "StartHeroicPlayerLevel ({}) must be in range 1..MaxPlayerLevel({}). Set to 55.",
m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55;
}
m_int_configs[CONFIG_START_PLAYER_MONEY] = sConfigMgr->GetOption("StartPlayerMoney", 0);
if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0 || int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) > MAX_MONEY_AMOUNT)
{
LOG_ERROR("server.loading", "StartPlayerMoney ({}) must be in range 0..{}. Set to {}.", m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0);
m_int_configs[CONFIG_START_PLAYER_MONEY] = 0;
}
m_int_configs[CONFIG_MAX_HONOR_POINTS] = sConfigMgr->GetOption("MaxHonorPoints", 75000);
if (int32(m_int_configs[CONFIG_MAX_HONOR_POINTS]) < 0)
{
LOG_ERROR("server.loading", "MaxHonorPoints ({}) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_HONOR_POINTS]);
m_int_configs[CONFIG_MAX_HONOR_POINTS] = 0;
}
m_int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT] = sConfigMgr->GetOption("MaxHonorPointsMoneyPerPoint", 0);
if (int32(m_int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT]) < 0)
{
LOG_ERROR("server.loading", "MaxHonorPointsMoneyPerPoint ({}) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT]);
m_int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT] = 0;
}
m_int_configs[CONFIG_START_HONOR_POINTS] = sConfigMgr->GetOption("StartHonorPoints", 0);
if (int32(m_int_configs[CONFIG_START_HONOR_POINTS]) < 0 || int32(m_int_configs[CONFIG_START_HONOR_POINTS]) > int32(m_int_configs[CONFIG_MAX_HONOR_POINTS]))
{
LOG_ERROR("server.loading", "StartHonorPoints ({}) must be in range 0..MaxHonorPoints({}). Set to {}.",
m_int_configs[CONFIG_START_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS], 0);
m_int_configs[CONFIG_START_HONOR_POINTS] = 0;
}
m_int_configs[CONFIG_MAX_ARENA_POINTS] = sConfigMgr->GetOption("MaxArenaPoints", 10000);
if (int32(m_int_configs[CONFIG_MAX_ARENA_POINTS]) < 0)
{
LOG_ERROR("server.loading", "MaxArenaPoints ({}) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_ARENA_POINTS]);
m_int_configs[CONFIG_MAX_ARENA_POINTS] = 0;
}
m_int_configs[CONFIG_START_ARENA_POINTS] = sConfigMgr->GetOption("StartArenaPoints", 0);
if (int32(m_int_configs[CONFIG_START_ARENA_POINTS]) < 0 || int32(m_int_configs[CONFIG_START_ARENA_POINTS]) > int32(m_int_configs[CONFIG_MAX_ARENA_POINTS]))
{
LOG_ERROR("server.loading", "StartArenaPoints ({}) must be in range 0..MaxArenaPoints({}). Set to {}.",
m_int_configs[CONFIG_START_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS], 0);
m_int_configs[CONFIG_START_ARENA_POINTS] = 0;
}
m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = sConfigMgr->GetOption("RecruitAFriend.MaxLevel", 60);
if (m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL]
|| int32(m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL]) < 0)
{
LOG_ERROR("server.loading", "RecruitAFriend.MaxLevel ({}) must be in the range 0..MaxLevel({}). Set to {}.",
m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], 60);
m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = 60;
}
m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE] = sConfigMgr->GetOption("RecruitAFriend.MaxDifference", 4);
m_bool_configs[CONFIG_ALL_TAXI_PATHS] = sConfigMgr->GetOption("AllFlightPaths", false);
m_int_configs[CONFIG_INSTANT_TAXI] = sConfigMgr->GetOption("InstantFlightPaths", 0);
m_bool_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfigMgr->GetOption("Instance.IgnoreLevel", false);
m_bool_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfigMgr->GetOption("Instance.IgnoreRaid", false);
m_bool_configs[CONFIG_INSTANCE_GMSUMMON_PLAYER] = sConfigMgr->GetOption("Instance.GMSummonPlayer", false);
m_bool_configs[CONFIG_INSTANCE_SHARED_ID] = sConfigMgr->GetOption("Instance.SharedNormalHeroicId", false);
m_int_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfigMgr->GetOption("Instance.ResetTimeHour", 4);
m_int_configs[CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP] = sConfigMgr->GetOption("Instance.ResetTimeRelativeTimestamp", 1135814400);
m_int_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfigMgr->GetOption("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS);
m_int_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfigMgr->GetOption("MaxPrimaryTradeSkill", 2);
m_int_configs[CONFIG_MIN_PETITION_SIGNS] = sConfigMgr->GetOption("MinPetitionSigns", 9);
if (m_int_configs[CONFIG_MIN_PETITION_SIGNS] > 9 || int32(m_int_configs[CONFIG_MIN_PETITION_SIGNS]) < 0)
{
LOG_ERROR("server.loading", "MinPetitionSigns ({}) must be in range 0..9. Set to 9.", m_int_configs[CONFIG_MIN_PETITION_SIGNS]);
m_int_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
}
m_int_configs[CONFIG_GM_LOGIN_STATE] = sConfigMgr->GetOption("GM.LoginState", 2);
m_int_configs[CONFIG_GM_VISIBLE_STATE] = sConfigMgr->GetOption("GM.Visible", 2);
m_int_configs[CONFIG_GM_CHAT] = sConfigMgr->GetOption("GM.Chat", 2);
m_int_configs[CONFIG_GM_WHISPERING_TO] = sConfigMgr->GetOption("GM.WhisperingTo", 2);
m_int_configs[CONFIG_GM_LEVEL_IN_GM_LIST] = sConfigMgr->GetOption("GM.InGMList.Level", SEC_ADMINISTRATOR);
m_int_configs[CONFIG_GM_LEVEL_IN_WHO_LIST] = sConfigMgr->GetOption("GM.InWhoList.Level", SEC_ADMINISTRATOR);
m_int_configs[CONFIG_START_GM_LEVEL] = sConfigMgr->GetOption("GM.StartLevel", 1);
if (m_int_configs[CONFIG_START_GM_LEVEL] < m_int_configs[CONFIG_START_PLAYER_LEVEL])
{
LOG_ERROR("server.loading", "GM.StartLevel ({}) must be in range StartPlayerLevel({})..{}. Set to {}.",
m_int_configs[CONFIG_START_GM_LEVEL], m_int_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, m_int_configs[CONFIG_START_PLAYER_LEVEL]);
m_int_configs[CONFIG_START_GM_LEVEL] = m_int_configs[CONFIG_START_PLAYER_LEVEL];
}
else if (m_int_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL)
{
LOG_ERROR("server.loading", "GM.StartLevel ({}) must be in range 1..{}. Set to {}.", m_int_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL);
m_int_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL;
}
m_bool_configs[CONFIG_ALLOW_GM_GROUP] = sConfigMgr->GetOption("GM.AllowInvite", false);
m_bool_configs[CONFIG_ALLOW_GM_FRIEND] = sConfigMgr->GetOption("GM.AllowFriend", false);
m_bool_configs[CONFIG_GM_LOWER_SECURITY] = sConfigMgr->GetOption("GM.LowerSecurity", false);
m_float_configs[CONFIG_CHANCE_OF_GM_SURVEY] = sConfigMgr->GetOption("GM.TicketSystem.ChanceOfGMSurvey", 50.0f);
m_int_configs[CONFIG_GROUP_VISIBILITY] = sConfigMgr->GetOption("Visibility.GroupMode", 1);
m_int_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfigMgr->GetOption("MailDeliveryDelay", HOUR);
m_int_configs[CONFIG_UPTIME_UPDATE] = sConfigMgr->GetOption("UpdateUptimeInterval", 10);
if (int32(m_int_configs[CONFIG_UPTIME_UPDATE]) <= 0)
{
LOG_ERROR("server.loading", "UpdateUptimeInterval ({}) must be > 0, set to default 10.", m_int_configs[CONFIG_UPTIME_UPDATE]);
m_int_configs[CONFIG_UPTIME_UPDATE] = 1;
}
if (reload)
{
m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE * IN_MILLISECONDS);
m_timers[WUPDATE_UPTIME].Reset();
}
// log db cleanup interval
m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = sConfigMgr->GetOption("LogDB.Opt.ClearInterval", 10);
if (int32(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]) <= 0)
{
LOG_ERROR("server.loading", "LogDB.Opt.ClearInterval ({}) must be > 0, set to default 10.", m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = 10;
}
if (reload)
{
m_timers[WUPDATE_CLEANDB].SetInterval(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] * MINUTE * IN_MILLISECONDS);
m_timers[WUPDATE_CLEANDB].Reset();
}
m_int_configs[CONFIG_LOGDB_CLEARTIME] = sConfigMgr->GetOption("LogDB.Opt.ClearTime", 1209600); // 14 days default
LOG_INFO("server.loading", "Will clear `logs` table of entries older than {} seconds every {} minutes.",
m_int_configs[CONFIG_LOGDB_CLEARTIME], m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
m_int_configs[CONFIG_TELEPORT_TIMEOUT_NEAR] = sConfigMgr->GetOption("TeleportTimeoutNear", 25); // pussywizard
m_int_configs[CONFIG_TELEPORT_TIMEOUT_FAR] = sConfigMgr->GetOption("TeleportTimeoutFar", 45); // pussywizard
m_int_configs[CONFIG_MAX_ALLOWED_MMR_DROP] = sConfigMgr->GetOption("MaxAllowedMMRDrop", 500); // pussywizard
m_bool_configs[CONFIG_ENABLE_LOGIN_AFTER_DC] = sConfigMgr->GetOption("EnableLoginAfterDC", true); // pussywizard
m_bool_configs[CONFIG_DONT_CACHE_RANDOM_MOVEMENT_PATHS] = sConfigMgr->GetOption("DontCacheRandomMovementPaths", true); // pussywizard
m_int_configs[CONFIG_SKILL_CHANCE_ORANGE] = sConfigMgr->GetOption("SkillChance.Orange", 100);
m_int_configs[CONFIG_SKILL_CHANCE_YELLOW] = sConfigMgr->GetOption("SkillChance.Yellow", 75);
m_int_configs[CONFIG_SKILL_CHANCE_GREEN] = sConfigMgr->GetOption("SkillChance.Green", 25);
m_int_configs[CONFIG_SKILL_CHANCE_GREY] = sConfigMgr->GetOption("SkillChance.Grey", 0);
m_int_configs[CONFIG_SKILL_CHANCE_MINING_STEPS] = sConfigMgr->GetOption("SkillChance.MiningSteps", 75);
m_int_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfigMgr->GetOption("SkillChance.SkinningSteps", 75);
m_bool_configs[CONFIG_SKILL_PROSPECTING] = sConfigMgr->GetOption("SkillChance.Prospecting", false);
m_bool_configs[CONFIG_SKILL_MILLING] = sConfigMgr->GetOption("SkillChance.Milling", false);
m_int_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfigMgr->GetOption("SkillGain.Crafting", 1);
m_int_configs[CONFIG_SKILL_GAIN_DEFENSE] = sConfigMgr->GetOption("SkillGain.Defense", 1);
m_int_configs[CONFIG_SKILL_GAIN_GATHERING] = sConfigMgr->GetOption("SkillGain.Gathering", 1);
m_int_configs[CONFIG_SKILL_GAIN_WEAPON] = sConfigMgr->GetOption("SkillGain.Weapon", 1);
m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfigMgr->GetOption("MaxOverspeedPings", 2);
if (m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] < 2)
{
LOG_ERROR("server.loading", "MaxOverspeedPings ({}) must be in range 2..infinity (or 0 to disable check). Set to 2.", m_int_configs[CONFIG_MAX_OVERSPEED_PINGS]);
m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = 2;
}
m_bool_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY] = sConfigMgr->GetOption("SaveRespawnTimeImmediately", true);
m_bool_configs[CONFIG_WEATHER] = sConfigMgr->GetOption("ActivateWeather", true);
m_int_configs[CONFIG_DISABLE_BREATHING] = sConfigMgr->GetOption("DisableWaterBreath", SEC_CONSOLE);
m_bool_configs[CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL] = sConfigMgr->GetOption("AlwaysMaxSkillForLevel", false);
if (reload)
{
uint32 val = sConfigMgr->GetOption("Expansion", 2);
if (val != m_int_configs[CONFIG_EXPANSION])
LOG_ERROR("server.loading", "Expansion option can't be changed at worldserver.conf reload, using current value ({}).", m_int_configs[CONFIG_EXPANSION]);
}
else
m_int_configs[CONFIG_EXPANSION] = sConfigMgr->GetOption("Expansion", 2);
m_int_configs[CONFIG_CHATFLOOD_MESSAGE_COUNT] = sConfigMgr->GetOption("ChatFlood.MessageCount", 10);
m_int_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfigMgr->GetOption("ChatFlood.MessageDelay", 1);
m_int_configs[CONFIG_CHATFLOOD_MUTE_TIME] = sConfigMgr->GetOption("ChatFlood.MuteTime", 10);
m_bool_configs[CONFIG_CHAT_MUTE_FIRST_LOGIN] = sConfigMgr->GetOption("Chat.MuteFirstLogin", false);
m_int_configs[CONFIG_CHAT_TIME_MUTE_FIRST_LOGIN] = sConfigMgr->GetOption("Chat.MuteTimeFirstLogin", 120);
m_int_configs[CONFIG_EVENT_ANNOUNCE] = sConfigMgr->GetOption("Event.Announce", 0);
m_float_configs[CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS] = sConfigMgr->GetOption("CreatureFamilyFleeAssistanceRadius", 30.0f);
m_float_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS] = sConfigMgr->GetOption("CreatureFamilyAssistanceRadius", 10.0f);
m_int_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY] = sConfigMgr->GetOption("CreatureFamilyAssistanceDelay", 2000);
m_int_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD] = sConfigMgr->GetOption("CreatureFamilyAssistancePeriod", 3000);
m_int_configs[CONFIG_CREATURE_FAMILY_FLEE_DELAY] = sConfigMgr->GetOption("CreatureFamilyFleeDelay", 7000);
m_int_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfigMgr->GetOption("WorldBossLevelDiff", 3);
m_bool_configs[CONFIG_QUEST_ENABLE_QUEST_TRACKER] = sConfigMgr->GetOption("Quests.EnableQuestTracker", false);
// note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100)
m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfigMgr->GetOption("Quests.LowLevelHideDiff", 4);
if (m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > MAX_LEVEL)
m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = MAX_LEVEL;
m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfigMgr->GetOption("Quests.HighLevelHideDiff", 7);
if (m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > MAX_LEVEL)
m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = MAX_LEVEL;
m_bool_configs[CONFIG_QUEST_IGNORE_RAID] = sConfigMgr->GetOption("Quests.IgnoreRaid", false);
m_bool_configs[CONFIG_QUEST_IGNORE_AUTO_ACCEPT] = sConfigMgr->GetOption("Quests.IgnoreAutoAccept", false);
m_bool_configs[CONFIG_QUEST_IGNORE_AUTO_COMPLETE] = sConfigMgr->GetOption("Quests.IgnoreAutoComplete", false);
m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = sConfigMgr->GetOption("Battleground.Random.ResetHour", 6);
if (m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] > 23)
{
LOG_ERROR("server.loading", "Battleground.Random.ResetHour ({}) can't be load. Set to 6.", m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR]);
m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = 6;
}
m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] = sConfigMgr->GetOption("Calendar.DeleteOldEventsHour", 6);
if (m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] > 23 || int32(m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR]) < 0)
{
LOG_ERROR("server.loading", "Calendar.DeleteOldEventsHour ({}) can't be load. Set to 6.", m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR]);
m_int_configs[CONFIG_CALENDAR_DELETE_OLD_EVENTS_HOUR] = 6;
}
m_int_configs[CONFIG_GUILD_RESET_HOUR] = sConfigMgr->GetOption("Guild.ResetHour", 6);
if (m_int_configs[CONFIG_GUILD_RESET_HOUR] > 23)
{
LOG_ERROR("server.loading", "Guild.ResetHour ({}) can't be load. Set to 6.", m_int_configs[CONFIG_GUILD_RESET_HOUR]);
m_int_configs[CONFIG_GUILD_RESET_HOUR] = 6;
}
m_int_configs[CONFIG_GUILD_BANK_INITIAL_TABS] = sConfigMgr->GetOption