PageRenderTime 60ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/server/game/World/World.cpp

https://github.com/chucho/FaceCore
C++ | 992 lines | 790 code | 138 blank | 64 comment | 138 complexity | 53a0c93cdcfe0c409b06d5ab509e8418 MD5 | raw file
  1. /*
  2. * Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
  3. * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /** \file
  19. \ingroup world
  20. */
  21. #include "Common.h"
  22. #include "DatabaseEnv.h"
  23. #include "Config.h"
  24. #include "SystemConfig.h"
  25. #include "Log.h"
  26. #include "Opcodes.h"
  27. #include "WorldSession.h"
  28. #include "WorldPacket.h"
  29. #include "Player.h"
  30. #include "Vehicle.h"
  31. #include "SkillExtraItems.h"
  32. #include "SkillDiscovery.h"
  33. #include "World.h"
  34. #include "AccountMgr.h"
  35. #include "AchievementMgr.h"
  36. #include "AuctionHouseMgr.h"
  37. #include "ObjectMgr.h"
  38. #include "ArenaTeamMgr.h"
  39. #include "GuildMgr.h"
  40. #include "TicketMgr.h"
  41. #include "CreatureEventAIMgr.h"
  42. #include "SpellMgr.h"
  43. #include "GroupMgr.h"
  44. #include "Chat.h"
  45. #include "DBCStores.h"
  46. #include "LootMgr.h"
  47. #include "ItemEnchantmentMgr.h"
  48. #include "MapManager.h"
  49. #include "CreatureAIRegistry.h"
  50. #include "BattlegroundMgr.h"
  51. #include "OutdoorPvPMgr.h"
  52. #include "OutdoorPvPWG.h"
  53. #include "TemporarySummon.h"
  54. #include "WaypointMovementGenerator.h"
  55. #include "VMapFactory.h"
  56. #include "GameEventMgr.h"
  57. #include "PoolMgr.h"
  58. #include "GridNotifiersImpl.h"
  59. #include "CellImpl.h"
  60. #include "InstanceSaveMgr.h"
  61. #include "Util.h"
  62. #include "Language.h"
  63. #include "CreatureGroups.h"
  64. #include "Transport.h"
  65. #include "ScriptMgr.h"
  66. #include "AddonMgr.h"
  67. #include "LFGMgr.h"
  68. #include "ConditionMgr.h"
  69. #include "DisableMgr.h"
  70. #include "CharacterDatabaseCleaner.h"
  71. #include "ScriptMgr.h"
  72. #include "WeatherMgr.h"
  73. #include "CreatureTextMgr.h"
  74. #include "SmartAI.h"
  75. #include "Channel.h"
  76. volatile bool World::m_stopEvent = false;
  77. uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
  78. volatile uint32 World::m_worldLoopCounter = 0;
  79. float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
  80. float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
  81. float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
  82. int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
  83. int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
  84. int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
  85. /// World constructor
  86. World::World()
  87. {
  88. m_playerLimit = 0;
  89. m_allowedSecurityLevel = SEC_PLAYER;
  90. m_allowMovement = true;
  91. m_ShutdownMask = 0;
  92. m_ShutdownTimer = 0;
  93. m_gameTime = time(NULL);
  94. m_startTime = m_gameTime;
  95. m_maxActiveSessionCount = 0;
  96. m_maxQueuedSessionCount = 0;
  97. m_PlayerCount = 0;
  98. m_MaxPlayerCount = 0;
  99. m_NextDailyQuestReset = 0;
  100. m_NextWeeklyQuestReset = 0;
  101. m_defaultDbcLocale = LOCALE_enUS;
  102. m_availableDbcLocaleMask = 0;
  103. m_updateTimeSum = 0;
  104. m_updateTimeCount = 0;
  105. m_isClosed = false;
  106. m_CleaningFlags = 0;
  107. }
  108. /// World destructor
  109. World::~World()
  110. {
  111. ///- Empty the kicked session set
  112. while (!m_sessions.empty())
  113. {
  114. // not remove from queue, prevent loading new sessions
  115. delete m_sessions.begin()->second;
  116. m_sessions.erase(m_sessions.begin());
  117. }
  118. CliCommandHolder* command = NULL;
  119. while (cliCmdQueue.next(command))
  120. delete command;
  121. VMAP::VMapFactory::clear();
  122. //TODO free addSessQueue
  123. }
  124. /// Find a player in a specified zone
  125. Player* World::FindPlayerInZone(uint32 zone)
  126. {
  127. ///- circle through active sessions and return the first player found in the zone
  128. SessionMap::const_iterator itr;
  129. for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  130. {
  131. if (!itr->second)
  132. continue;
  133. Player* player = itr->second->GetPlayer();
  134. if (!player)
  135. continue;
  136. if (player->IsInWorld() && player->GetZoneId() == zone)
  137. {
  138. // Used by the weather system. We return the player to broadcast the change weather message to him and all players in the zone.
  139. return player;
  140. }
  141. }
  142. return NULL;
  143. }
  144. bool World::IsClosed() const
  145. {
  146. return m_isClosed;
  147. }
  148. void World::SetClosed(bool val)
  149. {
  150. m_isClosed = val;
  151. // Invert the value, for simplicity for scripters.
  152. sScriptMgr->OnOpenStateChange(!val);
  153. }
  154. void World::SetMotd(const std::string& motd)
  155. {
  156. m_motd = motd;
  157. sScriptMgr->OnMotdChange(m_motd);
  158. }
  159. const char* World::GetMotd() const
  160. {
  161. return m_motd.c_str();
  162. }
  163. /// Find a session by its id
  164. WorldSession* World::FindSession(uint32 id) const
  165. {
  166. SessionMap::const_iterator itr = m_sessions.find(id);
  167. if (itr != m_sessions.end())
  168. return itr->second; // also can return NULL for kicked session
  169. else
  170. return NULL;
  171. }
  172. /// Remove a given session
  173. bool World::RemoveSession(uint32 id)
  174. {
  175. ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation
  176. SessionMap::const_iterator itr = m_sessions.find(id);
  177. if (itr != m_sessions.end() && itr->second)
  178. {
  179. if (itr->second->PlayerLoading())
  180. return false;
  181. itr->second->KickPlayer();
  182. }
  183. return true;
  184. }
  185. void World::AddSession(WorldSession* s)
  186. {
  187. addSessQueue.add(s);
  188. }
  189. void
  190. World::AddSession_(WorldSession* s)
  191. {
  192. ASSERT (s);
  193. //NOTE - Still there is race condition in WorldSession* being used in the Sockets
  194. ///- kick already loaded player with same account (if any) and remove session
  195. ///- if player is in loading and want to load again, return
  196. if (!RemoveSession (s->GetAccountId()))
  197. {
  198. s->KickPlayer();
  199. delete s; // session not added yet in session list, so not listed in queue
  200. return;
  201. }
  202. // decrease session counts only at not reconnection case
  203. bool decrease_session = true;
  204. // if session already exist, prepare to it deleting at next world update
  205. // NOTE - KickPlayer() should be called on "old" in RemoveSession()
  206. {
  207. SessionMap::const_iterator old = m_sessions.find(s->GetAccountId());
  208. if (old != m_sessions.end())
  209. {
  210. // prevent decrease sessions count if session queued
  211. if (RemoveQueuedPlayer(old->second))
  212. decrease_session = false;
  213. // not remove replaced session form queue if listed
  214. delete old->second;
  215. }
  216. }
  217. m_sessions[s->GetAccountId()] = s;
  218. uint32 Sessions = GetActiveAndQueuedSessionCount();
  219. uint32 pLimit = GetPlayerAmountLimit();
  220. uint32 QueueSize = GetQueuedSessionCount(); //number of players in the queue
  221. //so we don't count the user trying to
  222. //login as a session and queue the socket that we are using
  223. if (decrease_session)
  224. --Sessions;
  225. if (pLimit > 0 && Sessions >= pLimit && AccountMgr::IsPlayerAccount(s->GetSecurity()) && !HasRecentlyDisconnected(s))
  226. {
  227. AddQueuedPlayer (s);
  228. UpdateMaxSessionCounters();
  229. sLog->outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId(), ++QueueSize);
  230. return;
  231. }
  232. s->SendAuthResponse(AUTH_OK, true);
  233. s->SendAddonsInfo();
  234. s->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
  235. s->SendTutorialsData();
  236. UpdateMaxSessionCounters();
  237. // Updates the population
  238. if (pLimit > 0)
  239. {
  240. float popu = (float)GetActiveSessionCount(); // updated number of users on the server
  241. popu /= pLimit;
  242. popu *= 2;
  243. sLog->outDetail ("Server Population (%f).", popu);
  244. }
  245. }
  246. bool World::HasRecentlyDisconnected(WorldSession* session)
  247. {
  248. if (!session)
  249. return false;
  250. if (uint32 tolerance = getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
  251. {
  252. for (DisconnectMap::iterator i = m_disconnects.begin(); i != m_disconnects.end();)
  253. {
  254. if (difftime(i->second, time(NULL)) < tolerance)
  255. {
  256. if (i->first == session->GetAccountId())
  257. return true;
  258. ++i;
  259. }
  260. else
  261. m_disconnects.erase(i++);
  262. }
  263. }
  264. return false;
  265. }
  266. int32 World::GetQueuePos(WorldSession* sess)
  267. {
  268. uint32 position = 1;
  269. for (Queue::const_iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position)
  270. if ((*iter) == sess)
  271. return position;
  272. return 0;
  273. }
  274. void World::AddQueuedPlayer(WorldSession* sess)
  275. {
  276. sess->SetInQueue(true);
  277. m_QueuedPlayer.push_back(sess);
  278. // The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
  279. sess->SendAuthResponse(AUTH_WAIT_QUEUE, false, GetQueuePos(sess));
  280. }
  281. bool World::RemoveQueuedPlayer(WorldSession* sess)
  282. {
  283. // sessions count including queued to remove (if removed_session set)
  284. uint32 sessions = GetActiveSessionCount();
  285. uint32 position = 1;
  286. Queue::iterator iter = m_QueuedPlayer.begin();
  287. // search to remove and count skipped positions
  288. bool found = false;
  289. for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
  290. {
  291. if (*iter == sess)
  292. {
  293. sess->SetInQueue(false);
  294. sess->ResetTimeOutTime();
  295. iter = m_QueuedPlayer.erase(iter);
  296. found = true; // removing queued session
  297. break;
  298. }
  299. }
  300. // iter point to next socked after removed or end()
  301. // position store position of removed socket and then new position next socket after removed
  302. // if session not queued then we need decrease sessions count
  303. if (!found && sessions)
  304. --sessions;
  305. // accept first in queue
  306. if ((!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty())
  307. {
  308. WorldSession* pop_sess = m_QueuedPlayer.front();
  309. pop_sess->SetInQueue(false);
  310. pop_sess->ResetTimeOutTime();
  311. pop_sess->SendAuthWaitQue(0);
  312. pop_sess->SendAddonsInfo();
  313. pop_sess->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
  314. pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK);
  315. pop_sess->SendTutorialsData();
  316. m_QueuedPlayer.pop_front();
  317. // update iter to point first queued socket or end() if queue is empty now
  318. iter = m_QueuedPlayer.begin();
  319. position = 1;
  320. }
  321. // update position from iter to end()
  322. // iter point to first not updated socket, position store new position
  323. for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
  324. (*iter)->SendAuthWaitQue(position);
  325. return found;
  326. }
  327. /// Initialize config values
  328. void World::LoadConfigSettings(bool reload)
  329. {
  330. if (reload)
  331. {
  332. if (!sConfig->Reload())
  333. {
  334. sLog->outError("World settings reload fail: can't read settings from %s.", sConfig->GetFilename().c_str());
  335. return;
  336. }
  337. sLog->ReloadConfig(); // Reload log levels and filters
  338. }
  339. ///- Read the player limit and the Message of the day from the config file
  340. SetPlayerAmountLimit(sConfig->GetIntDefault("PlayerLimit", 100));
  341. SetMotd(sConfig->GetStringDefault("Motd", "Welcome to a Trinity Core Server."));
  342. ///- Read ticket system setting from the config file
  343. m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfig->GetBoolDefault("AllowTickets", true);
  344. ///- Get string for new logins (newly created characters)
  345. SetNewCharString(sConfig->GetStringDefault("PlayerStart.String", ""));
  346. ///- Send server info on login?
  347. m_int_configs[CONFIG_ENABLE_SINFO_LOGIN] = sConfig->GetIntDefault("Server.LoginInfo", 0);
  348. ///- Read all rates from the config file
  349. rate_values[RATE_HEALTH] = sConfig->GetFloatDefault("Rate.Health", 1);
  350. if (rate_values[RATE_HEALTH] < 0)
  351. {
  352. sLog->outError("Rate.Health (%f) must be > 0. Using 1 instead.", rate_values[RATE_HEALTH]);
  353. rate_values[RATE_HEALTH] = 1;
  354. }
  355. rate_values[RATE_POWER_MANA] = sConfig->GetFloatDefault("Rate.Mana", 1);
  356. if (rate_values[RATE_POWER_MANA] < 0)
  357. {
  358. sLog->outError("Rate.Mana (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_MANA]);
  359. rate_values[RATE_POWER_MANA] = 1;
  360. }
  361. rate_values[RATE_POWER_RAGE_INCOME] = sConfig->GetFloatDefault("Rate.Rage.Income", 1);
  362. rate_values[RATE_POWER_RAGE_LOSS] = sConfig->GetFloatDefault("Rate.Rage.Loss", 1);
  363. if (rate_values[RATE_POWER_RAGE_LOSS] < 0)
  364. {
  365. sLog->outError("Rate.Rage.Loss (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RAGE_LOSS]);
  366. rate_values[RATE_POWER_RAGE_LOSS] = 1;
  367. }
  368. rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfig->GetFloatDefault("Rate.RunicPower.Income", 1);
  369. rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfig->GetFloatDefault("Rate.RunicPower.Loss", 1);
  370. if (rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0)
  371. {
  372. sLog->outError("Rate.RunicPower.Loss (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RUNICPOWER_LOSS]);
  373. rate_values[RATE_POWER_RUNICPOWER_LOSS] = 1;
  374. }
  375. rate_values[RATE_POWER_FOCUS] = sConfig->GetFloatDefault("Rate.Focus", 1.0f);
  376. rate_values[RATE_POWER_ENERGY] = sConfig->GetFloatDefault("Rate.Energy", 1.0f);
  377. rate_values[RATE_SKILL_DISCOVERY] = sConfig->GetFloatDefault("Rate.Skill.Discovery", 1.0f);
  378. rate_values[RATE_DROP_ITEM_POOR] = sConfig->GetFloatDefault("Rate.Drop.Item.Poor", 1.0f);
  379. rate_values[RATE_DROP_ITEM_NORMAL] = sConfig->GetFloatDefault("Rate.Drop.Item.Normal", 1.0f);
  380. rate_values[RATE_DROP_ITEM_UNCOMMON] = sConfig->GetFloatDefault("Rate.Drop.Item.Uncommon", 1.0f);
  381. rate_values[RATE_DROP_ITEM_RARE] = sConfig->GetFloatDefault("Rate.Drop.Item.Rare", 1.0f);
  382. rate_values[RATE_DROP_ITEM_EPIC] = sConfig->GetFloatDefault("Rate.Drop.Item.Epic", 1.0f);
  383. rate_values[RATE_DROP_ITEM_LEGENDARY] = sConfig->GetFloatDefault("Rate.Drop.Item.Legendary", 1.0f);
  384. rate_values[RATE_DROP_ITEM_ARTIFACT] = sConfig->GetFloatDefault("Rate.Drop.Item.Artifact", 1.0f);
  385. rate_values[RATE_DROP_ITEM_REFERENCED] = sConfig->GetFloatDefault("Rate.Drop.Item.Referenced", 1.0f);
  386. rate_values[RATE_DROP_ITEM_REFERENCED_AMOUNT] = sConfig->GetFloatDefault("Rate.Drop.Item.ReferencedAmount", 1.0f);
  387. rate_values[RATE_DROP_MONEY] = sConfig->GetFloatDefault("Rate.Drop.Money", 1.0f);
  388. rate_values[RATE_XP_KILL] = sConfig->GetFloatDefault("Rate.XP.Kill", 1.0f);
  389. rate_values[RATE_XP_QUEST] = sConfig->GetFloatDefault("Rate.XP.Quest", 1.0f);
  390. rate_values[RATE_XP_EXPLORE] = sConfig->GetFloatDefault("Rate.XP.Explore", 1.0f);
  391. rate_values[RATE_REPAIRCOST] = sConfig->GetFloatDefault("Rate.RepairCost", 1.0f);
  392. if (rate_values[RATE_REPAIRCOST] < 0.0f)
  393. {
  394. sLog->outError("Rate.RepairCost (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_REPAIRCOST]);
  395. rate_values[RATE_REPAIRCOST] = 0.0f;
  396. }
  397. rate_values[RATE_REPUTATION_GAIN] = sConfig->GetFloatDefault("Rate.Reputation.Gain", 1.0f);
  398. rate_values[RATE_REPUTATION_LOWLEVEL_KILL] = sConfig->GetFloatDefault("Rate.Reputation.LowLevel.Kill", 1.0f);
  399. rate_values[RATE_REPUTATION_LOWLEVEL_QUEST] = sConfig->GetFloatDefault("Rate.Reputation.LowLevel.Quest", 1.0f);
  400. rate_values[RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS] = sConfig->GetFloatDefault("Rate.Reputation.RecruitAFriendBonus", 0.1f);
  401. rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Normal.Damage", 1.0f);
  402. rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.Elite.Damage", 1.0f);
  403. rate_values[RATE_CREATURE_ELITE_RAREELITE_DAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.RAREELITE.Damage", 1.0f);
  404. rate_values[RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.Damage", 1.0f);
  405. rate_values[RATE_CREATURE_ELITE_RARE_DAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.RARE.Damage", 1.0f);
  406. rate_values[RATE_CREATURE_NORMAL_HP] = sConfig->GetFloatDefault("Rate.Creature.Normal.HP", 1.0f);
  407. rate_values[RATE_CREATURE_ELITE_ELITE_HP] = sConfig->GetFloatDefault("Rate.Creature.Elite.Elite.HP", 1.0f);
  408. rate_values[RATE_CREATURE_ELITE_RAREELITE_HP] = sConfig->GetFloatDefault("Rate.Creature.Elite.RAREELITE.HP", 1.0f);
  409. rate_values[RATE_CREATURE_ELITE_WORLDBOSS_HP] = sConfig->GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.HP", 1.0f);
  410. rate_values[RATE_CREATURE_ELITE_RARE_HP] = sConfig->GetFloatDefault("Rate.Creature.Elite.RARE.HP", 1.0f);
  411. rate_values[RATE_CREATURE_NORMAL_SPELLDAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Normal.SpellDamage", 1.0f);
  412. rate_values[RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.Elite.SpellDamage", 1.0f);
  413. rate_values[RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.RAREELITE.SpellDamage", 1.0f);
  414. rate_values[RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.SpellDamage", 1.0f);
  415. rate_values[RATE_CREATURE_ELITE_RARE_SPELLDAMAGE] = sConfig->GetFloatDefault("Rate.Creature.Elite.RARE.SpellDamage", 1.0f);
  416. rate_values[RATE_CREATURE_AGGRO] = sConfig->GetFloatDefault("Rate.Creature.Aggro", 1.0f);
  417. rate_values[RATE_REST_INGAME] = sConfig->GetFloatDefault("Rate.Rest.InGame", 1.0f);
  418. rate_values[RATE_REST_OFFLINE_IN_TAVERN_OR_CITY] = sConfig->GetFloatDefault("Rate.Rest.Offline.InTavernOrCity", 1.0f);
  419. rate_values[RATE_REST_OFFLINE_IN_WILDERNESS] = sConfig->GetFloatDefault("Rate.Rest.Offline.InWilderness", 1.0f);
  420. rate_values[RATE_DAMAGE_FALL] = sConfig->GetFloatDefault("Rate.Damage.Fall", 1.0f);
  421. rate_values[RATE_AUCTION_TIME] = sConfig->GetFloatDefault("Rate.Auction.Time", 1.0f);
  422. rate_values[RATE_AUCTION_DEPOSIT] = sConfig->GetFloatDefault("Rate.Auction.Deposit", 1.0f);
  423. rate_values[RATE_AUCTION_CUT] = sConfig->GetFloatDefault("Rate.Auction.Cut", 1.0f);
  424. rate_values[RATE_HONOR] = sConfig->GetFloatDefault("Rate.Honor", 1.0f);
  425. rate_values[RATE_MINING_AMOUNT] = sConfig->GetFloatDefault("Rate.Mining.Amount", 1.0f);
  426. rate_values[RATE_MINING_NEXT] = sConfig->GetFloatDefault("Rate.Mining.Next", 1.0f);
  427. rate_values[RATE_INSTANCE_RESET_TIME] = sConfig->GetFloatDefault("Rate.InstanceResetTime", 1.0f);
  428. rate_values[RATE_TALENT] = sConfig->GetFloatDefault("Rate.Talent", 1.0f);
  429. if (rate_values[RATE_TALENT] < 0.0f)
  430. {
  431. sLog->outError("Rate.Talent (%f) must be > 0. Using 1 instead.", rate_values[RATE_TALENT]);
  432. rate_values[RATE_TALENT] = 1.0f;
  433. }
  434. rate_values[RATE_MOVESPEED] = sConfig->GetFloatDefault("Rate.MoveSpeed", 1.0f);
  435. if (rate_values[RATE_MOVESPEED] < 0)
  436. {
  437. sLog->outError("Rate.MoveSpeed (%f) must be > 0. Using 1 instead.", rate_values[RATE_MOVESPEED]);
  438. rate_values[RATE_MOVESPEED] = 1.0f;
  439. }
  440. for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) playerBaseMoveSpeed[i] = baseMoveSpeed[i] * rate_values[RATE_MOVESPEED];
  441. rate_values[RATE_CORPSE_DECAY_LOOTED] = sConfig->GetFloatDefault("Rate.Corpse.Decay.Looted", 0.5f);
  442. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = sConfig->GetFloatDefault("TargetPosRecalculateRange", 1.5f);
  443. if (rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] < CONTACT_DISTANCE)
  444. {
  445. sLog->outError("TargetPosRecalculateRange (%f) must be >= %f. Using %f instead.", rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], CONTACT_DISTANCE, CONTACT_DISTANCE);
  446. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = CONTACT_DISTANCE;
  447. }
  448. else if (rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] > NOMINAL_MELEE_RANGE)
  449. {
  450. sLog->outError("TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.",
  451. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], NOMINAL_MELEE_RANGE, NOMINAL_MELEE_RANGE);
  452. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = NOMINAL_MELEE_RANGE;
  453. }
  454. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = sConfig->GetFloatDefault("DurabilityLoss.OnDeath", 10.0f);
  455. if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] < 0.0f)
  456. {
  457. sLog->outError("DurabilityLoss.OnDeath (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
  458. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
  459. }
  460. if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] > 100.0f)
  461. {
  462. sLog->outError("DurabilityLoss.OnDeath (%f) must be <= 100. Using 100.0 instead.", rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
  463. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
  464. }
  465. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = rate_values[RATE_DURABILITY_LOSS_ON_DEATH] / 100.0f;
  466. rate_values[RATE_DURABILITY_LOSS_DAMAGE] = sConfig->GetFloatDefault("DurabilityLossChance.Damage", 0.5f);
  467. if (rate_values[RATE_DURABILITY_LOSS_DAMAGE] < 0.0f)
  468. {
  469. sLog->outError("DurabilityLossChance.Damage (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_DAMAGE]);
  470. rate_values[RATE_DURABILITY_LOSS_DAMAGE] = 0.0f;
  471. }
  472. rate_values[RATE_DURABILITY_LOSS_ABSORB] = sConfig->GetFloatDefault("DurabilityLossChance.Absorb", 0.5f);
  473. if (rate_values[RATE_DURABILITY_LOSS_ABSORB] < 0.0f)
  474. {
  475. sLog->outError("DurabilityLossChance.Absorb (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_ABSORB]);
  476. rate_values[RATE_DURABILITY_LOSS_ABSORB] = 0.0f;
  477. }
  478. rate_values[RATE_DURABILITY_LOSS_PARRY] = sConfig->GetFloatDefault("DurabilityLossChance.Parry", 0.05f);
  479. if (rate_values[RATE_DURABILITY_LOSS_PARRY] < 0.0f)
  480. {
  481. sLog->outError("DurabilityLossChance.Parry (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_PARRY]);
  482. rate_values[RATE_DURABILITY_LOSS_PARRY] = 0.0f;
  483. }
  484. rate_values[RATE_DURABILITY_LOSS_BLOCK] = sConfig->GetFloatDefault("DurabilityLossChance.Block", 0.05f);
  485. if (rate_values[RATE_DURABILITY_LOSS_BLOCK] < 0.0f)
  486. {
  487. sLog->outError("DurabilityLossChance.Block (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_BLOCK]);
  488. rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f;
  489. }
  490. ///- Read other configuration items from the config file
  491. m_bool_configs[CONFIG_DURABILITY_LOSS_IN_PVP] = sConfig->GetBoolDefault("DurabilityLoss.InPvP", false);
  492. m_int_configs[CONFIG_COMPRESSION] = sConfig->GetIntDefault("Compression", 1);
  493. if (m_int_configs[CONFIG_COMPRESSION] < 1 || m_int_configs[CONFIG_COMPRESSION] > 9)
  494. {
  495. sLog->outError("Compression level (%i) must be in range 1..9. Using default compression level (1).", m_int_configs[CONFIG_COMPRESSION]);
  496. m_int_configs[CONFIG_COMPRESSION] = 1;
  497. }
  498. m_bool_configs[CONFIG_ADDON_CHANNEL] = sConfig->GetBoolDefault("AddonChannel", true);
  499. m_bool_configs[CONFIG_CLEAN_CHARACTER_DB] = sConfig->GetBoolDefault("CleanCharacterDB", false);
  500. m_int_configs[CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS] = sConfig->GetIntDefault("PersistentCharacterCleanFlags", 0);
  501. m_int_configs[CONFIG_CHAT_CHANNEL_LEVEL_REQ] = sConfig->GetIntDefault("ChatLevelReq.Channel", 1);
  502. m_int_configs[CONFIG_CHAT_WHISPER_LEVEL_REQ] = sConfig->GetIntDefault("ChatLevelReq.Whisper", 1);
  503. m_int_configs[CONFIG_CHAT_SAY_LEVEL_REQ] = sConfig->GetIntDefault("ChatLevelReq.Say", 1);
  504. m_int_configs[CONFIG_TRADE_LEVEL_REQ] = sConfig->GetIntDefault("LevelReq.Trade", 1);
  505. m_int_configs[CONFIG_TICKET_LEVEL_REQ] = sConfig->GetIntDefault("LevelReq.Ticket", 1);
  506. m_int_configs[CONFIG_AUCTION_LEVEL_REQ] = sConfig->GetIntDefault("LevelReq.Auction", 1);
  507. m_int_configs[CONFIG_MAIL_LEVEL_REQ] = sConfig->GetIntDefault("LevelReq.Mail", 1);
  508. m_bool_configs[CONFIG_ALLOW_PLAYER_COMMANDS] = sConfig->GetBoolDefault("AllowPlayerCommands", 1);
  509. m_bool_configs[CONFIG_PRESERVE_CUSTOM_CHANNELS] = sConfig->GetBoolDefault("PreserveCustomChannels", false);
  510. m_int_configs[CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION] = sConfig->GetIntDefault("PreserveCustomChannelDuration", 14);
  511. m_bool_configs[CONFIG_GRID_UNLOAD] = sConfig->GetBoolDefault("GridUnload", true);
  512. m_int_configs[CONFIG_INTERVAL_SAVE] = sConfig->GetIntDefault("PlayerSaveInterval", 15 * MINUTE * IN_MILLISECONDS);
  513. m_int_configs[CONFIG_INTERVAL_DISCONNECT_TOLERANCE] = sConfig->GetIntDefault("DisconnectToleranceInterval", 0);
  514. m_bool_configs[CONFIG_STATS_SAVE_ONLY_ON_LOGOUT] = sConfig->GetBoolDefault("PlayerSave.Stats.SaveOnlyOnLogout", true);
  515. m_bool_configs[CONFIG_DUEL_RESET_COOLDOWN] = sConfig->GetBoolDefault("DuelResetCooldown", false);
  516. m_bool_configs[CONFIG_PREVENT_PLAYERS_ACCESS_TO_GMISLAND] = sConfig->GetBoolDefault("PreventPlayersAccessToGMIsland", false);
  517. m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = sConfig->GetIntDefault("PlayerSave.Stats.MinLevel", 0);
  518. if (m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] > MAX_LEVEL)
  519. {
  520. sLog->outError("PlayerSave.Stats.MinLevel (%i) must be in range 0..80. Using default, do not save character stats (0).", m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]);
  521. m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
  522. }
  523. m_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfig->GetIntDefault("GridCleanUpDelay", 5 * MINUTE * IN_MILLISECONDS);
  524. if (m_int_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY)
  525. {
  526. sLog->outError("GridCleanUpDelay (%i) must be greater %u. Use this minimal value.", m_int_configs[CONFIG_INTERVAL_GRIDCLEAN], MIN_GRID_DELAY);
  527. m_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = MIN_GRID_DELAY;
  528. }
  529. if (reload)
  530. sMapMgr->SetGridCleanUpDelay(m_int_configs[CONFIG_INTERVAL_GRIDCLEAN]);
  531. m_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfig->GetIntDefault("MapUpdateInterval", 100);
  532. if (m_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
  533. {
  534. sLog->outError("MapUpdateInterval (%i) must be greater %u. Use this minimal value.", m_int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
  535. m_int_configs[CONFIG_INTERVAL_MAPUPDATE] = MIN_MAP_UPDATE_DELAY;
  536. }
  537. if (reload)
  538. sMapMgr->SetMapUpdateInterval(m_int_configs[CONFIG_INTERVAL_MAPUPDATE]);
  539. m_int_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfig->GetIntDefault("ChangeWeatherInterval", 10 * MINUTE * IN_MILLISECONDS);
  540. if (reload)
  541. {
  542. uint32 val = sConfig->GetIntDefault("WorldServerPort", 8085);
  543. if (val != m_int_configs[CONFIG_PORT_WORLD])
  544. sLog->outError("WorldServerPort option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_PORT_WORLD]);
  545. }
  546. else
  547. m_int_configs[CONFIG_PORT_WORLD] = sConfig->GetIntDefault("WorldServerPort", 8085);
  548. m_int_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfig->GetIntDefault("SocketTimeOutTime", 900000);
  549. m_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfig->GetIntDefault("SessionAddDelay", 10000);
  550. m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfig->GetFloatDefault("MaxGroupXPDistance", 74.0f);
  551. m_float_configs[CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE] = sConfig->GetFloatDefault("MaxRecruitAFriendBonusDistance", 100.0f);
  552. /// \todo Add MonsterSight and GuarderSight (with meaning) in worldserver.conf or put them as define
  553. m_float_configs[CONFIG_SIGHT_MONSTER] = sConfig->GetFloatDefault("MonsterSight", 50);
  554. m_float_configs[CONFIG_SIGHT_GUARDER] = sConfig->GetFloatDefault("GuarderSight", 50);
  555. if (reload)
  556. {
  557. uint32 val = sConfig->GetIntDefault("GameType", 0);
  558. if (val != m_int_configs[CONFIG_GAME_TYPE])
  559. sLog->outError("GameType option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_GAME_TYPE]);
  560. }
  561. else
  562. m_int_configs[CONFIG_GAME_TYPE] = sConfig->GetIntDefault("GameType", 0);
  563. if (reload)
  564. {
  565. uint32 val = sConfig->GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT);
  566. if (val != m_int_configs[CONFIG_REALM_ZONE])
  567. sLog->outError("RealmZone option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_REALM_ZONE]);
  568. }
  569. else
  570. m_int_configs[CONFIG_REALM_ZONE] = sConfig->GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT);
  571. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig->GetBoolDefault("AllowTwoSide.Accounts", true);
  572. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfig->GetBoolDefault("AllowTwoSide.Interaction.Chat", false);
  573. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfig->GetBoolDefault("AllowTwoSide.Interaction.Channel", false);
  574. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfig->GetBoolDefault("AllowTwoSide.Interaction.Group", false);
  575. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfig->GetBoolDefault("AllowTwoSide.Interaction.Guild", false);
  576. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfig->GetBoolDefault("AllowTwoSide.Interaction.Auction", false);
  577. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfig->GetBoolDefault("AllowTwoSide.Interaction.Mail", false);
  578. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfig->GetBoolDefault("AllowTwoSide.WhoList", false);
  579. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfig->GetBoolDefault("AllowTwoSide.AddFriend", false);
  580. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfig->GetBoolDefault("AllowTwoSide.trade", false);
  581. m_int_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfig->GetIntDefault ("StrictPlayerNames", 0);
  582. m_int_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig->GetIntDefault ("StrictCharterNames", 0);
  583. m_int_configs[CONFIG_STRICT_PET_NAMES] = sConfig->GetIntDefault ("StrictPetNames", 0);
  584. m_int_configs[CONFIG_MIN_PLAYER_NAME] = sConfig->GetIntDefault ("MinPlayerName", 2);
  585. if (m_int_configs[CONFIG_MIN_PLAYER_NAME] < 1 || m_int_configs[CONFIG_MIN_PLAYER_NAME] > MAX_PLAYER_NAME)
  586. {
  587. sLog->outError("MinPlayerName (%i) must be in range 1..%u. Set to 2.", m_int_configs[CONFIG_MIN_PLAYER_NAME], MAX_PLAYER_NAME);
  588. m_int_configs[CONFIG_MIN_PLAYER_NAME] = 2;
  589. }
  590. m_int_configs[CONFIG_MIN_CHARTER_NAME] = sConfig->GetIntDefault ("MinCharterName", 2);
  591. if (m_int_configs[CONFIG_MIN_CHARTER_NAME] < 1 || m_int_configs[CONFIG_MIN_CHARTER_NAME] > MAX_CHARTER_NAME)
  592. {
  593. sLog->outError("MinCharterName (%i) must be in range 1..%u. Set to 2.", m_int_configs[CONFIG_MIN_CHARTER_NAME], MAX_CHARTER_NAME);
  594. m_int_configs[CONFIG_MIN_CHARTER_NAME] = 2;
  595. }
  596. m_int_configs[CONFIG_MIN_PET_NAME] = sConfig->GetIntDefault ("MinPetName", 2);
  597. if (m_int_configs[CONFIG_MIN_PET_NAME] < 1 || m_int_configs[CONFIG_MIN_PET_NAME] > MAX_PET_NAME)
  598. {
  599. sLog->outError("MinPetName (%i) must be in range 1..%u. Set to 2.", m_int_configs[CONFIG_MIN_PET_NAME], MAX_PET_NAME);
  600. m_int_configs[CONFIG_MIN_PET_NAME] = 2;
  601. }
  602. m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED] = sConfig->GetIntDefault("CharacterCreating.Disabled", 0);
  603. m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfig->GetIntDefault("CharacterCreating.Disabled.RaceMask", 0);
  604. m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfig->GetIntDefault("CharacterCreating.Disabled.ClassMask", 0);
  605. m_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig->GetIntDefault("CharactersPerRealm", 10);
  606. if (m_int_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_int_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
  607. {
  608. sLog->outError("CharactersPerRealm (%i) must be in range 1..10. Set to 10.", m_int_configs[CONFIG_CHARACTERS_PER_REALM]);
  609. m_int_configs[CONFIG_CHARACTERS_PER_REALM] = 10;
  610. }
  611. // must be after CONFIG_CHARACTERS_PER_REALM
  612. m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfig->GetIntDefault("CharactersPerAccount", 50);
  613. if (m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] < m_int_configs[CONFIG_CHARACTERS_PER_REALM])
  614. {
  615. sLog->outError("CharactersPerAccount (%i) can't be less than CharactersPerRealm (%i).", m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT], m_int_configs[CONFIG_CHARACTERS_PER_REALM]);
  616. m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_int_configs[CONFIG_CHARACTERS_PER_REALM];
  617. }
  618. m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfig->GetIntDefault("HeroicCharactersPerRealm", 1);
  619. if (int32(m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]) < 0 || m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10)
  620. {
  621. sLog->outError("HeroicCharactersPerRealm (%i) must be in range 0..10. Set to 1.", m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]);
  622. m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1;
  623. }
  624. m_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER] = sConfig->GetIntDefault("CharacterCreating.MinLevelForHeroicCharacter", 55);
  625. m_int_configs[CONFIG_SKIP_CINEMATICS] = sConfig->GetIntDefault("SkipCinematics", 0);
  626. if (int32(m_int_configs[CONFIG_SKIP_CINEMATICS]) < 0 || m_int_configs[CONFIG_SKIP_CINEMATICS] > 2)
  627. {
  628. sLog->outError("SkipCinematics (%i) must be in range 0..2. Set to 0.", m_int_configs[CONFIG_SKIP_CINEMATICS]);
  629. m_int_configs[CONFIG_SKIP_CINEMATICS] = 0;
  630. }
  631. if (reload)
  632. {
  633. uint32 val = sConfig->GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
  634. if (val != m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  635. sLog->outError("MaxPlayerLevel option can't be changed at config reload, using current value (%u).", m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  636. }
  637. else
  638. m_int_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig->GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
  639. if (m_int_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL)
  640. {
  641. sLog->outError("MaxPlayerLevel (%i) must be in range 1..%u. Set to %u.", m_int_configs[CONFIG_MAX_PLAYER_LEVEL], MAX_LEVEL, MAX_LEVEL);
  642. m_int_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL;
  643. }
  644. m_int_configs[CONFIG_MIN_DUALSPEC_LEVEL] = sConfig->GetIntDefault("MinDualSpecLevel", 40);
  645. m_int_configs[CONFIG_START_PLAYER_LEVEL] = sConfig->GetIntDefault("StartPlayerLevel", 1);
  646. if (m_int_configs[CONFIG_START_PLAYER_LEVEL] < 1)
  647. {
  648. sLog->outError("StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 1.", m_int_configs[CONFIG_START_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  649. m_int_configs[CONFIG_START_PLAYER_LEVEL] = 1;
  650. }
  651. else if (m_int_configs[CONFIG_START_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  652. {
  653. sLog->outError("StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.", m_int_configs[CONFIG_START_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  654. m_int_configs[CONFIG_START_PLAYER_LEVEL] = m_int_configs[CONFIG_MAX_PLAYER_LEVEL];
  655. }
  656. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfig->GetIntDefault("StartHeroicPlayerLevel", 55);
  657. if (m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1)
  658. {
  659. sLog->outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 55.",
  660. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  661. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55;
  662. }
  663. else if (m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  664. {
  665. sLog->outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.",
  666. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  667. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = m_int_configs[CONFIG_MAX_PLAYER_LEVEL];
  668. }
  669. m_int_configs[CONFIG_START_PLAYER_MONEY] = sConfig->GetIntDefault("StartPlayerMoney", 0);
  670. if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0)
  671. {
  672. sLog->outError("StartPlayerMoney (%i) must be in range 0..%u. Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0);
  673. m_int_configs[CONFIG_START_PLAYER_MONEY] = 0;
  674. }
  675. else if (m_int_configs[CONFIG_START_PLAYER_MONEY] > MAX_MONEY_AMOUNT)
  676. {
  677. sLog->outError("StartPlayerMoney (%i) must be in range 0..%u. Set to %u.",
  678. m_int_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, MAX_MONEY_AMOUNT);
  679. m_int_configs[CONFIG_START_PLAYER_MONEY] = MAX_MONEY_AMOUNT;
  680. }
  681. m_int_configs[CONFIG_MAX_HONOR_POINTS] = sConfig->GetIntDefault("MaxHonorPoints", 75000);
  682. if (int32(m_int_configs[CONFIG_MAX_HONOR_POINTS]) < 0)
  683. {
  684. sLog->outError("MaxHonorPoints (%i) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_HONOR_POINTS]);
  685. m_int_configs[CONFIG_MAX_HONOR_POINTS] = 0;
  686. }
  687. m_int_configs[CONFIG_START_HONOR_POINTS] = sConfig->GetIntDefault("StartHonorPoints", 0);
  688. if (int32(m_int_configs[CONFIG_START_HONOR_POINTS]) < 0)
  689. {
  690. sLog->outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
  691. m_int_configs[CONFIG_START_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS], 0);
  692. m_int_configs[CONFIG_START_HONOR_POINTS] = 0;
  693. }
  694. else if (m_int_configs[CONFIG_START_HONOR_POINTS] > m_int_configs[CONFIG_MAX_HONOR_POINTS])
  695. {
  696. sLog->outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
  697. m_int_configs[CONFIG_START_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS], m_int_configs[CONFIG_MAX_HONOR_POINTS]);
  698. m_int_configs[CONFIG_START_HONOR_POINTS] = m_int_configs[CONFIG_MAX_HONOR_POINTS];
  699. }
  700. m_int_configs[CONFIG_MAX_ARENA_POINTS] = sConfig->GetIntDefault("MaxArenaPoints", 10000);
  701. if (int32(m_int_configs[CONFIG_MAX_ARENA_POINTS]) < 0)
  702. {
  703. sLog->outError("MaxArenaPoints (%i) can't be negative. Set to 0.", m_int_configs[CONFIG_MAX_ARENA_POINTS]);
  704. m_int_configs[CONFIG_MAX_ARENA_POINTS] = 0;
  705. }
  706. m_int_configs[CONFIG_START_ARENA_POINTS] = sConfig->GetIntDefault("StartArenaPoints", 0);
  707. if (int32(m_int_configs[CONFIG_START_ARENA_POINTS]) < 0)
  708. {
  709. sLog->outError("StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
  710. m_int_configs[CONFIG_START_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS], 0);
  711. m_int_configs[CONFIG_START_ARENA_POINTS] = 0;
  712. }
  713. else if (m_int_configs[CONFIG_START_ARENA_POINTS] > m_int_configs[CONFIG_MAX_ARENA_POINTS])
  714. {
  715. sLog->outError("StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
  716. m_int_configs[CONFIG_START_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS], m_int_configs[CONFIG_MAX_ARENA_POINTS]);
  717. m_int_configs[CONFIG_START_ARENA_POINTS] = m_int_configs[CONFIG_MAX_ARENA_POINTS];
  718. }
  719. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = sConfig->GetIntDefault("RecruitAFriend.MaxLevel", 60);
  720. if (m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  721. {
  722. sLog->outError("RecruitAFriend.MaxLevel (%i) must be in the range 0..MaxLevel(%u). Set to %u.",
  723. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], 60);
  724. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = 60;
  725. }
  726. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE] = sConfig->GetIntDefault("RecruitAFriend.MaxDifference", 4);
  727. m_bool_configs[CONFIG_ALL_TAXI_PATHS] = sConfig->GetBoolDefault("AllFlightPaths", false);
  728. m_bool_configs[CONFIG_INSTANT_TAXI] = sConfig->GetBoolDefault("InstantFlightPaths", false);
  729. m_bool_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfig->GetBoolDefault("Instance.IgnoreLevel", false);
  730. m_bool_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig->GetBoolDefault("Instance.IgnoreRaid", false);
  731. m_bool_configs[CONFIG_CAST_UNSTUCK] = sConfig->GetBoolDefault("CastUnstuck", true);
  732. m_int_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig->GetIntDefault("Instance.ResetTimeHour", 4);
  733. m_int_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig->GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS);
  734. m_int_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfig->GetIntDefault("MaxPrimaryTradeSkill", 2);
  735. m_int_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig->GetIntDefault("MinPetitionSigns", 9);
  736. if (m_int_configs[CONFIG_MIN_PETITION_SIGNS] > 9)
  737. {
  738. sLog->outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_int_configs[CONFIG_MIN_PETITION_SIGNS]);
  739. m_int_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
  740. }
  741. rate_values[RATE_PVP_RANK_EXTRA_HONOR] = sConfig->GetFloatDefault("PvPRank.Rate.ExtraHonor", 1);
  742. std::string s_pvp_ranks = sConfig->GetStringDefault("PvPRank.HKPerRank", "10,50,100,200,450,750,1300,2000,3500,6000,9500,15000,21000,30000");
  743. char *c_pvp_ranks = const_cast<char*>(s_pvp_ranks.c_str());
  744. for (int i = 0; i !=HKRANKMAX; i++)
  745. {
  746. if (i==0)
  747. pvp_ranks[0] = 0;
  748. else if (i==1)
  749. pvp_ranks[1] = atoi(strtok (c_pvp_ranks, ","));
  750. else
  751. pvp_ranks[i] = atoi(strtok (NULL, ","));
  752. }
  753. m_int_configs[CONFIG_GM_LOGIN_STATE] = sConfig->GetIntDefault("GM.LoginState", 2);
  754. m_int_configs[CONFIG_GM_VISIBLE_STATE] = sConfig->GetIntDefault("GM.Visible", 2);
  755. m_int_configs[CONFIG_GM_CHAT] = sConfig->GetIntDefault("GM.Chat", 2);
  756. m_int_configs[CONFIG_GM_WHISPERING_TO] = sConfig->GetIntDefault("GM.WhisperingTo", 2);
  757. m_int_configs[CONFIG_GM_LEVEL_IN_GM_LIST] = sConfig->GetIntDefault("GM.InGMList.Level", SEC_ADMINISTRATOR);
  758. m_int_configs[CONFIG_GM_LEVEL_IN_WHO_LIST] = sConfig->GetIntDefault("GM.InWhoList.Level", SEC_ADMINISTRATOR);
  759. m_bool_configs[CONFIG_GM_LOG_TRADE] = sConfig->GetBoolDefault("GM.LogTrade", false);
  760. m_int_configs[CONFIG_START_GM_LEVEL] = sConfig->GetIntDefault("GM.StartLevel", 1);
  761. if (m_int_configs[CONFIG_START_GM_LEVEL] < m_int_configs[CONFIG_START_PLAYER_LEVEL])
  762. {
  763. sLog->outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..%u. Set to %u.",
  764. m_int_configs[CONFIG_START_GM_LEVEL], m_int_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, m_int_configs[CONFIG_START_PLAYER_LEVEL]);
  765. m_int_configs[CONFIG_START_GM_LEVEL] = m_int_configs[CONFIG_START_PLAYER_LEVEL];
  766. }
  767. else if (m_int_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL)
  768. {
  769. sLog->outError("GM.StartLevel (%i) must be in range 1..%u. Set to %u.", m_int_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL);
  770. m_int_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL;
  771. }
  772. m_bool_configs[CONFIG_ALLOW_GM_GROUP] = sConfig->GetBoolDefault("GM.AllowInvite", false);
  773. m_bool_configs[CONFIG_ALLOW_GM_FRIEND] = sConfig->GetBoolDefault("GM.AllowFriend", false);
  774. m_bool_configs[CONFIG_GM_LOWER_SECURITY] = sConfig->GetBoolDefault("GM.LowerSecurity", false);
  775. m_float_configs[CONFIG_CHANCE_OF_GM_SURVEY] = sConfig->GetFloatDefault("GM.TicketSystem.ChanceOfGMSurvey", 50.0f);
  776. m_int_configs[CONFIG_GROUP_VISIBILITY] = sConfig->GetIntDefault("Visibility.GroupMode", 1);
  777. m_int_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfig->GetIntDefault("MailDeliveryDelay", HOUR);
  778. m_int_configs[CONFIG_UPTIME_UPDATE] = sConfig->GetIntDefault("UpdateUptimeInterval", 10);
  779. if (int32(m_int_configs[CONFIG_UPTIME_UPDATE]) <= 0)
  780. {
  781. sLog->outError("UpdateUptimeInterval (%i) must be > 0, set to default 10.", m_int_configs[CONFIG_UPTIME_UPDATE]);
  782. m_int_configs[CONFIG_UPTIME_UPDATE] = 10;
  783. }
  784. if (reload)
  785. {
  786. m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS);
  787. m_timers[WUPDATE_UPTIME].Reset();
  788. }
  789. // log db cleanup interval
  790. m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = sConfig->GetIntDefault("LogDB.Opt.ClearInterval", 10);
  791. if (int32(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]) <= 0)
  792. {
  793. sLog->outError("LogDB.Opt.ClearInterval (%i) must be > 0, set to default 10.", m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
  794. m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = 10;
  795. }
  796. if (reload)
  797. {
  798. m_timers[WUPDATE_CLEANDB].SetInterval(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] * MINUTE * IN_MILLISECONDS);
  799. m_timers[WUPDATE_CLEANDB].Reset();
  800. }
  801. m_int_configs[CONFIG_LOGDB_CLEARTIME] = sConfig->GetIntDefault("LogDB.Opt.ClearTime", 1209600); // 14 days default
  802. sLog->outString("Will clear `logs` table of entries older than %i seconds every %u minutes.",
  803. m_int_configs[CONFIG_LOGDB_CLEARTIME], m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
  804. m_int_configs[CONFIG_SKILL_CHANCE_ORANGE] = sConfig->GetIntDefault("SkillChance.Orange", 100);
  805. m_int_configs[CONFIG_SKILL_CHANCE_YELLOW] = sConfig->GetIntDefault("SkillChance.Yellow", 75);
  806. m_int_configs[CONFIG_SKILL_CHANCE_GREEN] = sConfig->GetIntDefault("SkillChance.Green", 25);
  807. m_int_configs[CONFIG_SKILL_CHANCE_GREY] = sConfig->GetIntDefault("SkillChance.Grey", 0);
  808. m_int_configs[CONFIG_SKILL_CHANCE_MINING_STEPS] = sConfig->GetIntDefault("SkillChance.MiningSteps", 75);
  809. m_int_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfig->GetIntDefault("SkillChance.SkinningSteps", 75);
  810. m_bool_configs[CONFIG_SKILL_PROSPECTING] = sConfig->GetBoolDefault("SkillChance.Prospecting", false);
  811. m_bool_configs[CONFIG_SKILL_MILLING] = sConfig->GetBoolDefault("SkillChance.Milling", false);
  812. m_int_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfig->GetIntDefault("SkillGain.Crafting", 1);
  813. m_int_configs[CONFIG_SKILL_GAIN_DEFENSE] = sConfig->GetIntDefault("SkillGain.Defense", 1);
  814. m_int_configs[CONFIG_SKILL_GAIN_GATHERING] = sConfig->GetIntDefault("SkillGain.Gathering", 1);
  815. m_int_configs[CONFIG_SKILL_GAIN_WEAPON] = sConfig->GetIntDefault("SkillGain.Weapon", 1);
  816. m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfig->GetIntDefault("MaxOverspeedPings", 2);
  817. if (m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] < 2)
  818. {
  819. sLog->outError("MaxOverspeedPings (%i) must be in range 2..infinity (or 0 to disable check). Set to 2.", m_int_configs[CONFIG_MAX_OVERSPEED_PINGS]);
  820. m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = 2;
  821. }
  822. m_bool_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY] = sConfig->GetBoolDefault("SaveRespawnTimeImmediately", true);
  823. m_bool_configs[CONFIG_WEATHER] = sConfig->GetBoolDefault("ActivateWeather", true);
  824. m_int_configs[CONFIG_DISABLE_BREATHING] = sConfig->GetIntDefault("DisableWaterBreath", SEC_CONSOLE);
  825. m_bool_configs[CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL] = sConfig->GetBoolDefault("AlwaysMaxSkillForLevel", false);
  826. if (reload)
  827. {
  828. uint32 val = sConfig->GetIntDefault("Expansion", 1);
  829. if (val != m_int_configs[CONFIG_EXPANSION])
  830. sLog->outError("Expansion option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_EXPANSION]);
  831. }
  832. else
  833. m_int_configs[CONFIG_EXPANSION] = sConfig->GetIntDefault("Expansion", 1);
  834. m_int_configs[CONFIG_CHATFLOOD_MESSAGE_COUNT] = sConfig->GetIntDefault("ChatFlood.MessageCount", 10);
  835. m_int_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfig->GetIntDefault("ChatFlood.MessageDelay", 1);
  836. m_int_configs[CONFIG_CHATFLOOD_MUTE_TIME] = sConfig->GetIntDefault("ChatFlood.MuteTime", 10);
  837. m_int_configs[CONFIG_EVENT_ANNOUNCE] = sConfig->GetIntDefault("Event.Announce", 0);
  838. m_float_configs[CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS] = sConfig->GetFloatDefault("CreatureFamilyFleeAssistanceRadius", 30.0f);
  839. m_float_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS] = sConfig->GetFloatDefault("CreatureFamilyAssistanceRadius", 10.0f);
  840. m_int_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY] = sConfig->GetIntDefault("CreatureFamilyAssistanceDelay", 1500);
  841. m_int_configs[CONFIG_CREATURE_FAMILY_FLEE_DELAY] = sConfig->GetIntDefault("CreatureFamilyFleeDelay", 7000);
  842. m_int_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfig->GetIntDefault("WorldBossLevelDiff", 3);
  843. // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100)
  844. m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig->GetIntDefault("Quests.LowLevelHideDiff", 4);
  845. if (m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > MAX_LEVEL)
  846. m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = MAX_LEVEL;
  847. m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig->GetIntDefault("Quests.HighLevelHideDiff", 7);
  848. if (m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > MAX_LEVEL)
  849. m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = MAX_LEVEL;
  850. m_bool_configs[CONFIG_QUEST_IGNORE_RAID] = sConfig->GetBoolDefault("Quests.IgnoreRaid", false);
  851. m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = sConfig->GetIntDefault("Battleground.Random.ResetHour", 6);
  852. if (m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] > 23)
  853. {
  854. sLog->outError("Battleground.Random.ResetHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_RANDOM_BG_