/*
* 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 "AutobroadcastMgr.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 "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 "MotdMgr.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::_stopEvent = false;
uint8 World::_exitCode = SHUTDOWN_EXIT_CODE;
uint32 World::m_worldLoopCounter = 0;
float World::_maxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
float World::_maxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
float World::_maxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
Realm realm;
/// World constructor
World::World()
{
_playerLimit = 0;
_allowedSecurityLevel = SEC_PLAYER;
_allowMovement = true;
_shutdownMask = 0;
_shutdownTimer = 0;
_maxActiveSessionCount = 0;
_maxQueuedSessionCount = 0;
_playerCount = 0;
_maxPlayerCount = 0;
_nextDailyQuestReset = 0s;
_nextWeeklyQuestReset = 0s;
_nextMonthlyQuestReset = 0s;
_nextRandomBGReset = 0s;
_nextCalendarOldEventsDeletionTime = 0s;
_nextGuildReset = 0s;
_defaultDbcLocale = LOCALE_enUS;
_mail_expire_check_timer = 0s;
_isClosed = false;
_cleaningFlags = 0;
memset(_rate_values, 0, sizeof(_rate_values));
memset(_int_configs, 0, sizeof(_int_configs));
memset(_bool_configs, 0, sizeof(_bool_configs));
memset(_float_configs, 0, sizeof(_float_configs));
}
/// World destructor
World::~World()
{
///- Empty the kicked session set
while (!_sessions.empty())
{
// not remove from queue, prevent loading new sessions
delete _sessions.begin()->second;
_sessions.erase(_sessions.begin());
}
while (!_offlineSessions.empty())
{
delete _offlineSessions.begin()->second;
_offlineSessions.erase(_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 = _sessions.begin(); itr != _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 _isClosed;
}
void World::SetClosed(bool val)
{
_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 = _sessions.find(id);
if (itr != _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 = _offlineSessions.find(id);
if (itr != _offlineSessions.end())
return itr->second;
else
return nullptr;
}
WorldSession* World::FindOfflineSessionForCharacterGUID(ObjectGuid::LowType guidLow) const
{
if (_offlineSessions.empty())
return nullptr;
for (SessionMap::const_iterator itr = _offlineSessions.begin(); itr != _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 = _sessions.find(id);
if (itr != _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 = _sessions.find(s->GetAccountId());
if (old != _sessions.end())
{
WorldSession* oldSession = old->second;
if (!RemoveQueuedPlayer(oldSession) && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
_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 = _offlineSessions.find(oldSession->GetAccountId())) != _offlineSessions.end())
{
WorldSession* tmp = iter->second;
_offlineSessions.erase(iter);
delete tmp;
}
oldSession->SetOfflineTime(GameTime::GetGameTime().count());
_offlineSessions[oldSession->GetAccountId()] = oldSession;
}
else
{
delete oldSession;
}
}
_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->InitializeSession();
UpdateMaxSessionCounters();
}
bool World::HasRecentlyDisconnected(WorldSession* session)
{
if (!session)
return false;
if (uint32 tolerance = getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
{
for (DisconnectMap::iterator i = _disconnects.begin(); i != _disconnects.end();)
{
if ((GameTime::GetGameTime().count() - i->second) < tolerance)
{
if (i->first == session->GetAccountId())
return true;
++i;
}
else
_disconnects.erase(i++);
}
}
return false;
}
int32 World::GetQueuePos(WorldSession* sess)
{
uint32 position = 1;
for (Queue::const_iterator iter = _queuedPlayer.begin(); iter != _queuedPlayer.end(); ++iter, ++position)
if ((*iter) == sess)
return position;
return 0;
}
void World::AddQueuedPlayer(WorldSession* sess)
{
sess->SetInQueue(true);
_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 = _queuedPlayer.begin();
// search to remove and count skipped positions
bool found = false;
for (; iter != _queuedPlayer.end(); ++iter, ++position)
{
if (*iter == sess)
{
sess->SetInQueue(false);
sess->ResetTimeOutTime(false);
iter = _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()) && !_queuedPlayer.empty())
{
WorldSession* pop_sess = _queuedPlayer.front();
pop_sess->InitializeSession();
_queuedPlayer.pop_front();
// update iter to point first queued socket or end() if queue is empty now
iter = _queuedPlayer.begin();
position = 1;
}
// update queue position from iter to end()
for (; iter != _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));
}
///- Read ticket system setting from the config file
_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetOption("AllowTickets", true);
_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?
_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_ITEM_GROUP_AMOUNT] = sConfigMgr->GetOption("Rate.Drop.Item.GroupAmount", 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);
_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
_bool_configs[CONFIG_DURABILITY_LOSS_IN_PVP] = sConfigMgr->GetOption("DurabilityLoss.InPvP", false);
_int_configs[CONFIG_COMPRESSION] = sConfigMgr->GetOption("Compression", 1);
if (_int_configs[CONFIG_COMPRESSION] < 1 || _int_configs[CONFIG_COMPRESSION] > 9)
{
LOG_ERROR("server.loading", "Compression level ({}) must be in range 1..9. Using default compression level (1).", _int_configs[CONFIG_COMPRESSION]);
_int_configs[CONFIG_COMPRESSION] = 1;
}
_bool_configs[CONFIG_ADDON_CHANNEL] = sConfigMgr->GetOption("AddonChannel", true);
_bool_configs[CONFIG_CLEAN_CHARACTER_DB] = sConfigMgr->GetOption("CleanCharacterDB", false);
_int_configs[CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS] = sConfigMgr->GetOption("PersistentCharacterCleanFlags", 0);
_int_configs[CONFIG_CHAT_CHANNEL_LEVEL_REQ] = sConfigMgr->GetOption("ChatLevelReq.Channel", 1);
_int_configs[CONFIG_CHAT_WHISPER_LEVEL_REQ] = sConfigMgr->GetOption("ChatLevelReq.Whisper", 1);
_int_configs[CONFIG_CHAT_SAY_LEVEL_REQ] = sConfigMgr->GetOption("ChatLevelReq.Say", 1);
_int_configs[CONFIG_PARTY_LEVEL_REQ] = sConfigMgr->GetOption("PartyLevelReq", 1);
_int_configs[CONFIG_TRADE_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Trade", 1);
_int_configs[CONFIG_TICKET_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Ticket", 1);
_int_configs[CONFIG_AUCTION_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Auction", 1);
_int_configs[CONFIG_MAIL_LEVEL_REQ] = sConfigMgr->GetOption("LevelReq.Mail", 1);
_bool_configs[CONFIG_ALLOW_PLAYER_COMMANDS] = sConfigMgr->GetOption("AllowPlayerCommands", 1);
_bool_configs[CONFIG_PRESERVE_CUSTOM_CHANNELS] = sConfigMgr->GetOption("PreserveCustomChannels", false);
_int_configs[CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION] = sConfigMgr->GetOption("PreserveCustomChannelDuration", 14);
_int_configs[CONFIG_INTERVAL_SAVE] = sConfigMgr->GetOption("PlayerSaveInterval", 15 * MINUTE * IN_MILLISECONDS);
_int_configs[CONFIG_INTERVAL_DISCONNECT_TOLERANCE] = sConfigMgr->GetOption("DisconnectToleranceInterval", 0);
_bool_configs[CONFIG_STATS_SAVE_ONLY_ON_LOGOUT] = sConfigMgr->GetOption("PlayerSave.Stats.SaveOnlyOnLogout", true);
_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = sConfigMgr->GetOption("PlayerSave.Stats.MinLevel", 0);
if (_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] > MAX_LEVEL || int32(_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).", _int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]);
_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
}
_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfigMgr->GetOption("GridCleanUpDelay", 5 * MINUTE * IN_MILLISECONDS);
if (_int_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY)
{
LOG_ERROR("server.loading", "GridCleanUpDelay (%i) must be greater %u. Use this minimal value.", _int_configs[CONFIG_INTERVAL_GRIDCLEAN], MIN_GRID_DELAY);
_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = MIN_GRID_DELAY;
}
if (reload)
sMapMgr->SetGridCleanUpDelay(_int_configs[CONFIG_INTERVAL_GRIDCLEAN]);
_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption("MapUpdateInterval", 10);
if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
{
LOG_ERROR("server.loading", "MapUpdateInterval ({}) must be greater {}. Use this minimal value.", _int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
_int_configs[CONFIG_INTERVAL_MAPUPDATE] = MIN_MAP_UPDATE_DELAY;
}
if (reload)
sMapMgr->SetMapUpdateInterval(_int_configs[CONFIG_INTERVAL_MAPUPDATE]);
_int_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfigMgr->GetOption("ChangeWeatherInterval", 10 * MINUTE * IN_MILLISECONDS);
if (reload)
{
uint32 val = sConfigMgr->GetOption("WorldServerPort", 8085);
if (val != _int_configs[CONFIG_PORT_WORLD])
LOG_ERROR("server.loading", "WorldServerPort option can't be changed at worldserver.conf reload, using current value ({}).", _int_configs[CONFIG_PORT_WORLD]);
}
else
_int_configs[CONFIG_PORT_WORLD] = sConfigMgr->GetOption("WorldServerPort", 8085);
_bool_configs[CONFIG_CLOSE_IDLE_CONNECTIONS] = sConfigMgr->GetOption("CloseIdleConnections", true);
_int_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfigMgr->GetOption("SocketTimeOutTime", 900000);
_int_configs[CONFIG_SOCKET_TIMEOUTTIME_ACTIVE] = sConfigMgr->GetOption("SocketTimeOutTimeActive", 60000);
_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfigMgr->GetOption("SessionAddDelay", 10000);
_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetOption("MaxGroupXPDistance", 74.0f);
_float_configs[CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE] = sConfigMgr->GetOption("MaxRecruitAFriendBonusDistance", 100.0f);
/// \todo Add MonsterSight in worldserver.conf or put it as define
_float_configs[CONFIG_SIGHT_MONSTER] = sConfigMgr->GetOption("MonsterSight", 50);
if (reload)
{
uint32 val = sConfigMgr->GetOption("GameType", 0);
if (val != _int_configs[CONFIG_GAME_TYPE])
LOG_ERROR("server.loading", "GameType option can't be changed at worldserver.conf reload, using current value ({}).", _int_configs[CONFIG_GAME_TYPE]);
}
else
_int_configs[CONFIG_GAME_TYPE] = sConfigMgr->GetOption("GameType", 0);
if (reload)
{
uint32 val = sConfigMgr->GetOption("RealmZone", REALM_ZONE_DEVELOPMENT);
if (val != _int_configs[CONFIG_REALM_ZONE])
LOG_ERROR("server.loading", "RealmZone option can't be changed at worldserver.conf reload, using current value ({}).", _int_configs[CONFIG_REALM_ZONE]);
}
else
_int_configs[CONFIG_REALM_ZONE] = sConfigMgr->GetOption("RealmZone", REALM_ZONE_DEVELOPMENT);
_bool_configs[CONFIG_STRICT_NAMES_RESERVED] = sConfigMgr->GetOption ("StrictNames.Reserved", true);
_bool_configs[CONFIG_STRICT_NAMES_PROFANITY] = sConfigMgr->GetOption ("StrictNames.Profanity", true);
_int_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfigMgr->GetOption ("StrictPlayerNames", 0);
_int_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfigMgr->GetOption ("StrictCharterNames", 0);
_int_configs[CONFIG_STRICT_CHANNEL_NAMES] = sConfigMgr->GetOption ("StrictChannelNames", 0);
_int_configs[CONFIG_STRICT_PET_NAMES] = sConfigMgr->GetOption ("StrictPetNames", 0);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfigMgr->GetOption("AllowTwoSide.Accounts", true);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Calendar", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Chat", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Channel", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Group", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Guild", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_ARENA] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Arena", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Auction", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Mail", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfigMgr->GetOption("AllowTwoSide.WhoList", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfigMgr->GetOption("AllowTwoSide.AddFriend", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfigMgr->GetOption("AllowTwoSide.Trade", false);
_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_EMOTE] = sConfigMgr->GetOption("AllowTwoSide.Interaction.Emote", false);
_int_configs[CONFIG_MIN_PLAYER_NAME] = sConfigMgr->GetOption ("MinPlayerName", 2);
if (_int_configs[CONFIG_MIN_PLAYER_NAME] < 1 || _int_configs[CONFIG_MIN_PLAYER_NAME] > MAX_PLAYER_NAME)
{
LOG_ERROR("server.loading", "MinPlayerName ({}) must be in range 1..{}. Set to 2.", _int_configs[CONFIG_MIN_PLAYER_NAME], MAX_PLAYER_NAME);
_int_configs[CONFIG_MIN_PLAYER_NAME] = 2;
}
_int_configs[CONFIG_MIN_CHARTER_NAME] = sConfigMgr->GetOption ("MinCharterName", 2);
if (_int_configs[CONFIG_MIN_CHARTER_NAME] < 1 || _int_configs[CONFIG_MIN_CHARTER_NAME] > MAX_CHARTER_NAME)
{
LOG_ERROR("server.loading", "MinCharterName ({}) must be in range 1..{}. Set to 2.", _int_configs[CONFIG_MIN_CHARTER_NAME], MAX_CHARTER_NAME);
_int_configs[CONFIG_MIN_CHARTER_NAME] = 2;
}
_int_configs[CONFIG_MIN_PET_NAME] = sConfigMgr->GetOption ("MinPetName", 2);
if (_int_configs[CONFIG_MIN_PET_NAME] < 1 || _int_configs[CONFIG_MIN_PET_NAME] > MAX_PET_NAME)
{
LOG_ERROR("server.loading", "MinPetName ({}) must be in range 1..{}. Set to 2.", _int_configs[CONFIG_MIN_PET_NAME], MAX_PET_NAME);
_int_configs[CONFIG_MIN_PET_NAME] = 2;
}
_int_configs[CONFIG_CHARTER_COST_GUILD] = sConfigMgr->GetOption("Guild.CharterCost", 1000);
_int_configs[CONFIG_CHARTER_COST_ARENA_2v2] = sConfigMgr->GetOption("ArenaTeam.CharterCost.2v2", 800000);
_int_configs[CONFIG_CHARTER_COST_ARENA_3v3] = sConfigMgr->GetOption("ArenaTeam.CharterCost.3v3", 1200000);
_int_configs[CONFIG_CHARTER_COST_ARENA_5v5] = sConfigMgr->GetOption("ArenaTeam.CharterCost.5v5", 2000000);
_int_configs[CONFIG_MAX_WHO_LIST_RETURN] = sConfigMgr->GetOption("MaxWhoListReturns", 49);
_int_configs[CONFIG_CHARACTER_CREATING_DISABLED] = sConfigMgr->GetOption("CharacterCreating.Disabled", 0);
_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfigMgr->GetOption("CharacterCreating.Disabled.RaceMask", 0);
_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfigMgr->GetOption("CharacterCreating.Disabled.ClassMask", 0);
_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfigMgr->GetOption("CharactersPerRealm", 10);
if (_int_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || _int_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
{
LOG_ERROR("server.loading", "CharactersPerRealm ({}) must be in range 1..10. Set to 10.", _int_configs[CONFIG_CHARACTERS_PER_REALM]);
_int_configs[CONFIG_CHARACTERS_PER_REALM] = 10;
}
// must be after CONFIG_CHARACTERS_PER_REALM
_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfigMgr->GetOption("CharactersPerAccount", 50);
if (_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] < _int_configs[CONFIG_CHARACTERS_PER_REALM])
{
LOG_ERROR("server.loading", "CharactersPerAccount ({}) can't be less than CharactersPerRealm ({}).", _int_configs[CONFIG_CHARACTERS_PER_ACCOUNT], _int_configs[CONFIG_CHARACTERS_PER_REALM]);
_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = _int_configs[CONFIG_CHARACTERS_PER_REALM];
}
_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfigMgr->GetOption("HeroicCharactersPerRealm", 1);
if (int32(_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]) < 0 || _int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10)
{
LOG_ERROR("server.loading", "HeroicCharactersPerRealm ({}) must be in range 0..10. Set to 1.", _int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]);
_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1;
}
_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER] = sConfigMgr->GetOption("CharacterCreating.MinLevelForHeroicCharacter", 55);
_int_configs[CONFIG_SKIP_CINEMATICS] = sConfigMgr->GetOption("SkipCinematics", 0);
if (int32(_int_configs[CONFIG_SKIP_CINEMATICS]) < 0 || _int_configs[CONFIG_SKIP_CINEMATICS] > 2)
{
LOG_ERROR("server.loading", "SkipCinematics ({}) must be in range 0..2. Set to 0.", _int_configs[CONFIG_SKIP_CINEMATICS]);
_int_configs[CONFIG_SKIP_CINEMATICS] = 0;
}
if (reload)
{
uint32 val = sConfigMgr->GetOption("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
if (val != _int_configs[CONFIG_MAX_PLAYER_LEVEL])
LOG_ERROR("server.loading", "MaxPlayerLevel option can't be changed at config reload, using current value ({}).", _int_configs[CONFIG_MAX_PLAYER_LEVEL]);
}
else
_int_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfigMgr->GetOption("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
if (_int_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL || _int_configs[CONFIG_MAX_PLAYER_LEVEL] < 1)
{
LOG_ERROR("server.loading", "MaxPlayerLevel ({}) must be in range 1..{}. Set to {}.", _int_configs[CONFIG_MAX_PLAYER_LEVEL], MAX_LEVEL, MAX_LEVEL);
_int_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL;
}
_int_configs[CONFIG_MIN_DUALSPEC_LEVEL] = sConfigMgr->GetOption("MinDualSpecLevel", 40);
_int_configs[CONFIG_START_PLAYER_LEVEL] = sConfigMgr->GetOption("StartPlayerLevel", 1);
if (_int_configs[CONFIG_START_PLAYER_LEVEL] < 1 || _int_configs[CONFIG_START_PLAYER_LEVEL] > _int_configs[CONFIG_MAX_PLAYER_LEVEL])
{
LOG_ERROR("server.loading", "StartPlayerLevel ({}) must be in range 1..MaxPlayerLevel({}). Set to 1.", _int_configs[CONFIG_START_PLAYER_LEVEL], _int_configs[CONFIG_MAX_PLAYER_LEVEL]);
_int_configs[CONFIG_START_PLAYER_LEVEL] = 1;
}
_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfigMgr->GetOption("StartHeroicPlayerLevel", 55);
if (_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1 || _int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > _int_configs[CONFIG_MAX_PLAYER_LEVEL])
{
LOG_ERROR("server.loading", "StartHeroicPlayerLevel ({}) must be in range 1..MaxPlayerLevel({}). Set to 55.",
_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL], _int_configs[CONFIG_MAX_PLAYER_LEVEL]);
_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55;
}
_int_configs[CONFIG_START_PLAYER_MONEY] = sConfigMgr->GetOption("StartPlayerMoney", 0);
if (int32(_int_configs[CONFIG_START_PLAYER_MONEY]) < 0 || int32(_int_configs[CONFIG_START_PLAYER_MONEY]) > MAX_MONEY_AMOUNT)
{
LOG_ERROR("server.loading", "StartPlayerMoney ({}) must be in range 0..{}. Set to {}.", _int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0);
_int_configs[CONFIG_START_PLAYER_MONEY] = 0;
}
_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY] = sConfigMgr->GetOption("StartHeroicPlayerMoney", 2000);
if (int32(_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY]) < 0 || int32(_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY]) > MAX_MONEY_AMOUNT)
{
LOG_ERROR("server.loading", "StartHeroicPlayerMoney ({}) must be in range 0..{}. Set to {}.", _int_configs[CONFIG_START_HEROIC_PLAYER_MONEY], MAX_MONEY_AMOUNT, 2000);
_int_configs[CONFIG_START_HEROIC_PLAYER_MONEY] = 2000;
}
_int_configs[CONFIG_MAX_HONOR_POINTS] = sConfigMgr->GetOption("MaxHonorPoints", 75000);
if (int32(_int_configs[CONFIG_MAX_HONOR_POINTS]) < 0)
{
LOG_ERROR("server.loading", "MaxHonorPoints ({}) can't be negative. Set to 0.", _int_configs[CONFIG_MAX_HONOR_POINTS]);
_int_configs[CONFIG_MAX_HONOR_POINTS] = 0;
}
_int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT] = sConfigMgr->GetOption("MaxHonorPointsMoneyPerPoint", 0);
if (int32(_int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT]) < 0)
{
LOG_ERROR("server.loading", "MaxHonorPointsMoneyPerPoint ({}) can't be negative. Set to 0.", _int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT]);
_int_configs[CONFIG_MAX_HONOR_POINTS_MONEY_PER_POINT] = 0;
}
_int_configs[CONFIG_START_HONOR_POINTS] = sConfigMgr->GetOption("StartHonorPoints", 0);
if (int32(_int_configs[CONFIG_START_HONOR_POINTS]) < 0 || int32(_int_configs[CONFIG_START_HONOR_POINTS]) > int32(_int_configs[CONFIG_MAX_HONOR_POINTS]))
{
LOG_ERROR("server.loading", "StartHonorPoints ({}) must be in range 0..MaxHonorPoints({}). Set to {}.",
_int_configs[CONFIG_START_HONOR_POINTS], _int_configs[CONFIG_MAX_HONOR_POINTS], 0);
_int_configs[CONFIG_START_HONOR_POINTS] = 0;
}
_int_configs[CONFIG_MAX_ARENA_POINTS] = sConfigMgr->GetOption("MaxArenaPoints", 10000);
if (int32(_int_configs[CONFIG_MAX_ARENA_POINTS]) < 0)
{
LOG_ERROR("server.loading", "MaxArenaPoints ({}) can't be negative. Set to 0.", _int_configs[CONFIG_MAX_ARENA_POINTS]);
_int_configs[CONFIG_MAX_ARENA_POINTS] = 0;
}
_int_configs[CONFIG_START_ARENA_POINTS] = sConfigMgr->GetOption("StartArenaPoints", 0);
if (int32(_int_configs[CONFIG_START_ARENA_POINTS]) < 0 || int32(_int_configs[CONFIG_START_ARENA_POINTS]) > int32(_int_configs[CONFIG_MAX_ARENA_POINTS]))
{
LOG_ERROR("server.loading", "StartArenaPoints ({}) must be in range 0..MaxArenaPoints({}). Set to {}.",
_int_configs[CONFIG_START_ARENA_POINTS], _int_configs[CONFIG_MAX_ARENA_POINTS], 0);
_int_configs[CONFIG_START_ARENA_POINTS] = 0;
}
_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = sConfigMgr->GetOption("RecruitAFriend.MaxLevel", 60);
if (_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] > _int_configs[CONFIG_MAX_PLAYER_LEVEL]
|| int32(_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 {}.",
_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL], _int_configs[CONFIG_MAX_PLAYER_LEVEL], 60);
_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = 60;
}
_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE] = sConfigMgr->GetOption("RecruitAFriend.MaxDifference", 4);
_bool_configs[CONFIG_ALL_TAXI_PATHS] = sConfigMgr->GetOption("AllFlightPaths", false);
_int_configs[CONFIG_INSTANT_TAXI] = sConfigMgr->GetOption("InstantFlightPaths", 0);
_bool_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfigMgr->GetOption("Instance.IgnoreLevel", false);
_bool_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfigMgr->GetOption("Instance.IgnoreRaid", false);
_bool_configs[CONFIG_INSTANCE_GMSUMMON_PLAYER] = sConfigMgr->GetOption("Instance.GMSummonPlayer", false);
_bool_configs[CONFIG_INSTANCE_SHARED_ID] = sConfigMgr->GetOption("Instance.SharedNormalHeroicId", false);
_int_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfigMgr->GetOption("Instance.ResetTimeHour", 4);
_int_configs[CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP] = sConfigMgr->GetOption("Instance.ResetTimeRelativeTimestamp", 1135814400);
_int_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfigMgr->GetOption("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS);
_int_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfigMgr->GetOption("MaxPrimaryTradeSkill", 2);
_int_configs[CONFIG_MIN_PETITION_SIGNS] = sConfigMgr->GetOption("MinPetitionSigns", 9);
if (_int_configs[CONFIG_MIN_PETITION_SIGNS] > 9 || int32(_int_configs[CONFIG_MIN_PETITION_SIGNS]) < 0)
{
LOG_ERROR("server.loading", "MinPetitionSigns ({}) must be in range 0..9. Set to 9.", _int_configs[CONFIG_MIN_PETITION_SIGNS]);
_int_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
}
_int_configs[CONFIG_GM_LOGIN_STATE] = sConfigMgr->GetOption("GM.LoginState", 2);
_int_configs[CONFIG_GM_VISIBLE_STATE] = sConfigMgr->GetOption("GM.Visible", 2);
_int_configs[CONFIG_GM_CHAT] = sConfigMgr->GetOption("GM.Chat", 2);
_int_configs[CONFIG_GM_WHISPERING_TO] = sConfigMgr->GetOption("GM.WhisperingTo", 2);
_int_configs[CONFIG_GM_LEVEL_IN_GM_LIST] = sConfigMgr->GetOption("GM.InGMList.Level", SEC_ADMINISTRATOR);
_int_configs[CONFIG_GM_LEVEL_IN_WHO_LIST] = sConfigMgr->GetOption("GM.InWhoList.Level", SEC_ADMINISTRATOR);
_int_configs[CONFIG_START_GM_LEVEL] = sConfigMgr->GetOption("GM.StartLevel", 1);
if (_int_configs[CONFIG_START_GM_LEVEL] < _int_configs[CONFIG_START_PLAYER_LEVEL])
{
LOG_ERROR("server.loading", "GM.StartLevel ({}) must be in range StartPlayerLevel({})..{}. Set to {}.",
_int_configs[CONFIG_START_GM_LEVEL], _int_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, _int_configs[CONFIG_START_PLAYER_LEVEL]);
_int_configs[CONFIG_START_GM_LEVEL] = _int_configs[CONFIG_START_PLAYER_LEVEL];
}
else if (_int_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL)
{
LOG_ERROR("server.loading", "GM.StartLevel ({}) must be in range 1..{}. Set to {}.", _int_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL);
_int_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL;
}
_bool_configs[CONFIG_ALLOW_GM_GROUP] = sConfigMgr->GetOption("GM.AllowInvite", false);
_bool_configs[CONFIG_ALLOW_GM_FRIEND] = sConfigMgr->GetOption("GM.AllowFriend", false);
_bool_configs[CONFIG_GM_LOWER_SECURITY] = sConfigMgr->GetOption("GM.LowerSecurity", false);
_float_configs[CONFIG_CHANCE_OF_GM_SURVEY] = sConfigMgr->GetOption("GM.TicketSystem.ChanceOfGMSurvey", 50.0f);
_int_configs[CONFIG_GROUP_VISIBILITY] = sConfigMgr->GetOption("Visibility.GroupMode", 1);
_bool_configs[CONFIG_OBJECT_SPARKLES] = sConfigMgr->GetOption("Visibility.ObjectSparkles", true);
_bool_configs[CONFIG_LOW_LEVEL_REGEN_BOOST] = sConfigMgr->GetOption("EnableLowLevelRegenBoost", true);
_bool_configs[CONFIG_OBJECT_QUEST_MARKERS] = sConfigMgr->GetOption("Visibility.ObjectQuestMarkers", true);
_int_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfigMgr->GetOption("MailDeliveryDelay", HOUR);
_int_configs[CONFIG_UPTIME_UPDATE] = sConfigMgr->GetOption("UpdateUptimeInterval", 10);
if (int32(_int_configs[CONFIG_UPTIME_UPDATE]) <= 0)
{
LOG_ERROR("server.loading", "UpdateUptimeInterval ({}) must be > 0, set to default 10.", _int_configs[CONFIG_UPTIME_UPDATE]);
_int_configs[CONFIG_UPTIME_UPDATE] = 1;
}
if (reload)
{
_timers[WUPDATE_UPTIME].SetInterval(_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE * IN_MILLISECONDS);
_timers[WUPDATE_UPTIME].Reset();
}
// log db cleanup interval
_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = sConfigMgr->GetOption("LogDB.Opt.ClearInterval", 10);
if (int32(_int_configs[CONFIG_LOGDB_CLEARINTERVAL]) <= 0)
{
LOG_ERROR("server.loading", "LogDB.Opt.ClearInterval ({}) must be > 0, set to default 10.", _int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = 10;
}
if (reload)
{
_timers[WUPDATE_CLEANDB].SetInterval(_int_configs[CONFIG_LOGDB_CLEARINTERVAL] * MINUTE * IN_MILLISECONDS);
_timers[WUPDATE_CLEANDB].Reset();
}
_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.",
_int_configs[CONFIG_LOGDB_CLEARTIME], _int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
_int_configs[CONFIG_TELEPORT_TIMEOUT_NEAR] = sConfigMgr->GetOption("TeleportTimeoutNear", 25); // pussywizard
_int_configs[CONFIG_TELEPORT_TIMEOUT_FAR] = sConfigMgr->GetOption("TeleportTimeoutFar", 45); // pussywizard
_int_configs[CONFIG_MAX_ALLOWED_MMR_DROP] = sConfigMgr->GetOption("MaxAllowedMMRDrop", 500); // pussywizard
_bool_configs[CONFIG_ENABLE_LOGIN_AFTER_DC] = sConfigMgr->GetOption("EnableLoginAfterDC", true); // pussywizard
_bool_configs[CONFIG_DONT_CACHE_RANDOM_MOVEMENT_PATHS] = sConfigMgr->GetOption("DontCacheRandomMovementPaths", true); // pussywizard
_int_configs[CONFIG_SKILL_CHANCE_ORANGE] = sConfigMgr->GetOption("SkillChance.Orange", 100);
_int_configs[CONFIG_SKILL_CHANCE_YELLOW] = sConfigMgr->GetOption("SkillChance.Yellow", 75);
_int_configs[CONFIG_SKILL_CHANCE_GREEN] = sConfigMgr->GetOption("SkillChance.Green", 25);
_int_configs[CONFIG_SKILL_CHANCE_GREY] = sConfigMgr->GetOption("SkillChance.Grey", 0);
_int_configs[CONFIG_SKILL_CHANCE_MINING_STEPS] = sConfigMgr->GetOption("SkillChance.MiningSteps", 75);
_int_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfigMgr->GetOption("SkillChance.SkinningSteps", 75);
_bool_configs[CONFIG_SKILL_PROSPECTING] = sConfigMgr->GetOption("SkillChance.Prospecting", false);
_bool_configs[CONFIG_SKILL_MILLING] = sConfigMgr->GetOption("SkillChance.Milling", false);
_int_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfigMgr->GetOption("SkillGain.Crafting", 1);
_int_configs[CONFIG_SKILL_GAIN_DEFENSE] = sConfigMgr->GetOption("SkillGain.Defense", 1);
_int_configs[CONFIG_SKILL_GAIN_GATHERING] = sConfigMgr->GetOption("SkillGain.Gathering", 1);
_int_configs[CONFIG_SKILL_GAIN_WEAPON] = sConfigMgr->GetOption("SkillGain.Weapon", 1);
_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfigMgr->GetOption("MaxOverspeedPings", 2);
if (_int_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && _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.", _int_configs[CONFIG_MAX_OVERSPEED_PINGS]);
_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = 2;
}
_bool_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY] = sConfigMgr->GetOption("SaveRespawnTimeImmediately", true);
_bool_configs[CONFIG_WEATHER] = sConfigMgr->GetOption("ActivateWeather", true);
_int_configs[CONFIG_DISABLE_BREATHING] = sConfigMgr->GetOption("DisableWaterBreath", SEC_CONSOLE);
_bool_configs[CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL] = sConfigMgr->GetOption("AlwaysMaxSkillForLevel", false);
if (reload)
{
uint32 val = sConfigMgr->GetOption("Expansion", 2);
if (val != _int_configs[CONFIG_EXPANSION])
LOG_ERROR("server.loading", "Expansion option can't be changed at worldserver.conf reload, using current value ({}).", _int_configs[CONFIG_EXPANSION]);
}
else
_int_configs[CONFIG_EXPANSION] = sConfigMgr->GetOption("Expansion", 2);
_int_configs[CONFIG_CHATFLOOD_MESSAGE_COUNT] = sConfigMgr->GetOption("ChatFlood.MessageCount", 10);
_int_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfigMgr->GetOption("ChatFlood.MessageDelay", 1);
_int_configs[CONFIG_CHATFLOOD_ADDON_MESSAGE_COUNT] = sConfigMgr->GetOption("ChatFlood.AddonMessageCount", 100);
_int_configs[CONFIG_CHATFLOOD_ADDON_MESSAGE_DELAY] = sConfigMgr->GetOption("ChatFlood.AddonMessageDelay", 1);
_int_configs[CONFIG_CHATFLOOD_MUTE_TIME] = sConfigMgr->GetOption("ChatFlood.MuteTime", 10);
_bool_configs[CONFIG_CHAT_MUTE_FIRST_LOGIN] = sConfigMgr->GetOption("Chat.MuteFirstLogin", false);
_int_configs[CONFIG_CHAT_TIME_MUTE_FIRST_LOGIN] = sConfigMgr->GetOption("Chat.MuteTimeFirstLogin", 120);
_int_configs[CONFIG_EVENT_ANNOUNCE] = sConfigMgr->GetOption("Event.Announce", 0);
_float_configs[CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS] = sConfigMgr->GetOption("CreatureFamilyFleeAssistanceRadius", 30.0f);
_float_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS] = sConfigMgr->GetOption("CreatureFamilyAssistanceRadius", 10.0f);
_int_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY] = sConfigMgr->GetOption("CreatureFamilyAssistanceDelay", 2000);
_int_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD] = sConfigMgr->GetOption("CreatureFamilyAssistancePeriod", 3000);
_int_configs[CONFIG_CREATURE_FAMILY_FLEE_DELAY] = sConfigMgr->GetOption("CreatureFamilyFleeDelay", 7000);
_int_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfigMgr->GetOption("WorldBossLevelDiff", 3);
_bool_configs[CONFIG_QUEST_ENABLE_QUEST_TRACKER] = sConfigMgr->GetOption