[9581] Fixed apply damage reduction to melee/ranged damage.
[getmangos.git] / src / game / World.cpp
blob853a7a4aee6a120ed3934608c74a134e67bb17fa
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /** \file
20 \ingroup world
23 #include "Common.h"
24 #include "Database/DatabaseEnv.h"
25 #include "Config/ConfigEnv.h"
26 #include "SystemConfig.h"
27 #include "Log.h"
28 #include "Opcodes.h"
29 #include "WorldSession.h"
30 #include "WorldPacket.h"
31 #include "Weather.h"
32 #include "Player.h"
33 #include "Vehicle.h"
34 #include "SkillExtraItems.h"
35 #include "SkillDiscovery.h"
36 #include "World.h"
37 #include "AccountMgr.h"
38 #include "AchievementMgr.h"
39 #include "AuctionHouseMgr.h"
40 #include "ObjectMgr.h"
41 #include "CreatureEventAIMgr.h"
42 #include "SpellMgr.h"
43 #include "Chat.h"
44 #include "DBCStores.h"
45 #include "LootMgr.h"
46 #include "ItemEnchantmentMgr.h"
47 #include "MapManager.h"
48 #include "ScriptCalls.h"
49 #include "CreatureAIRegistry.h"
50 #include "Policies/SingletonImp.h"
51 #include "BattleGroundMgr.h"
52 #include "TemporarySummon.h"
53 #include "VMapFactory.h"
54 #include "GlobalEvents.h"
55 #include "GameEventMgr.h"
56 #include "PoolManager.h"
57 #include "Database/DatabaseImpl.h"
58 #include "GridNotifiersImpl.h"
59 #include "CellImpl.h"
60 #include "InstanceSaveMgr.h"
61 #include "WaypointManager.h"
62 #include "GMTicketMgr.h"
63 #include "Util.h"
65 INSTANTIATE_SINGLETON_1( World );
67 volatile bool World::m_stopEvent = false;
68 uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
69 volatile uint32 World::m_worldLoopCounter = 0;
71 float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
72 float World::m_MaxVisibleDistanceInInctances = DEFAULT_VISIBILITY_INSTANCE;
73 float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
74 float World::m_MaxVisibleDistanceForObject = DEFAULT_VISIBILITY_DISTANCE;
76 float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
77 float World::m_VisibleUnitGreyDistance = 0;
78 float World::m_VisibleObjectGreyDistance = 0;
80 /// World constructor
81 World::World()
83 m_playerLimit = 0;
84 m_allowMovement = true;
85 m_ShutdownMask = 0;
86 m_ShutdownTimer = 0;
87 m_gameTime=time(NULL);
88 m_startTime=m_gameTime;
89 m_maxActiveSessionCount = 0;
90 m_maxQueuedSessionCount = 0;
91 m_resultQueue = NULL;
92 m_NextDailyQuestReset = 0;
93 m_scheduledScripts = 0;
95 m_defaultDbcLocale = LOCALE_enUS;
96 m_availableDbcLocaleMask = 0;
98 for(int i = 0; i < CONFIG_UINT32_VALUE_COUNT; ++i)
99 m_configUint32Values[i] = 0;
101 for(int i = 0; i < CONFIG_INT32_VALUE_COUNT; ++i)
102 m_configInt32Values[i] = 0;
104 for(int i = 0; i < CONFIG_FLOAT_VALUE_COUNT; ++i)
105 m_configFloatValues[i] = 0.0f;
107 for(int i = 0; i < CONFIG_BOOL_VALUE_COUNT; ++i)
108 m_configBoolValues[i] = false;
111 /// World destructor
112 World::~World()
114 ///- Empty the kicked session set
115 while (!m_sessions.empty())
117 // not remove from queue, prevent loading new sessions
118 delete m_sessions.begin()->second;
119 m_sessions.erase(m_sessions.begin());
122 ///- Empty the WeatherMap
123 for (WeatherMap::const_iterator itr = m_weathers.begin(); itr != m_weathers.end(); ++itr)
124 delete itr->second;
126 m_weathers.clear();
128 CliCommandHolder* command;
129 while (cliCmdQueue.next(command))
130 delete command;
132 VMAP::VMapFactory::clear();
134 if(m_resultQueue) delete m_resultQueue;
136 //TODO free addSessQueue
139 /// Find a player in a specified zone
140 Player* World::FindPlayerInZone(uint32 zone)
142 ///- circle through active sessions and return the first player found in the zone
143 SessionMap::const_iterator itr;
144 for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
146 if(!itr->second)
147 continue;
148 Player *player = itr->second->GetPlayer();
149 if(!player)
150 continue;
151 if( player->IsInWorld() && player->GetZoneId() == zone )
153 // Used by the weather system. We return the player to broadcast the change weather message to him and all players in the zone.
154 return player;
157 return NULL;
160 /// Find a session by its id
161 WorldSession* World::FindSession(uint32 id) const
163 SessionMap::const_iterator itr = m_sessions.find(id);
165 if(itr != m_sessions.end())
166 return itr->second; // also can return NULL for kicked session
167 else
168 return NULL;
171 /// Remove a given session
172 bool World::RemoveSession(uint32 id)
174 ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation
175 SessionMap::const_iterator itr = m_sessions.find(id);
177 if(itr != m_sessions.end() && itr->second)
179 if (itr->second->PlayerLoading())
180 return false;
181 itr->second->KickPlayer();
184 return true;
187 void World::AddSession(WorldSession* s)
189 addSessQueue.add(s);
192 void
193 World::AddSession_ (WorldSession* s)
195 ASSERT (s);
197 //NOTE - Still there is race condition in WorldSession* being used in the Sockets
199 ///- kick already loaded player with same account (if any) and remove session
200 ///- if player is in loading and want to load again, return
201 if (!RemoveSession (s->GetAccountId ()))
203 s->KickPlayer ();
204 delete s; // session not added yet in session list, so not listed in queue
205 return;
208 // decrease session counts only at not reconnection case
209 bool decrease_session = true;
211 // if session already exist, prepare to it deleting at next world update
212 // NOTE - KickPlayer() should be called on "old" in RemoveSession()
214 SessionMap::const_iterator old = m_sessions.find(s->GetAccountId ());
216 if(old != m_sessions.end())
218 // prevent decrease sessions count if session queued
219 if(RemoveQueuedPlayer(old->second))
220 decrease_session = false;
221 // not remove replaced session form queue if listed
222 delete old->second;
226 m_sessions[s->GetAccountId ()] = s;
228 uint32 Sessions = GetActiveAndQueuedSessionCount ();
229 uint32 pLimit = GetPlayerAmountLimit ();
230 uint32 QueueSize = GetQueueSize (); //number of players in the queue
232 //so we don't count the user trying to
233 //login as a session and queue the socket that we are using
234 if(decrease_session)
235 --Sessions;
237 if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER )
239 AddQueuedPlayer (s);
240 UpdateMaxSessionCounters ();
241 sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
242 return;
245 WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
246 packet << uint8 (AUTH_OK);
247 packet << uint32 (0); // BillingTimeRemaining
248 packet << uint8 (0); // BillingPlanFlags
249 packet << uint32 (0); // BillingTimeRested
250 packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
251 s->SendPacket (&packet);
253 s->SendAddonsInfo();
255 WorldPacket pkt(SMSG_CLIENTCACHE_VERSION, 4);
256 pkt << uint32(getConfig(CONFIG_UINT32_CLIENTCACHE_VERSION));
257 s->SendPacket(&pkt);
259 s->SendTutorialsData();
261 UpdateMaxSessionCounters ();
263 // Updates the population
264 if (pLimit > 0)
266 float popu = float(GetActiveSessionCount()); // updated number of users on the server
267 popu /= pLimit;
268 popu *= 2;
269 loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
270 sLog.outDetail ("Server Population (%f).", popu);
274 int32 World::GetQueuePos(WorldSession* sess)
276 uint32 position = 1;
278 for(Queue::const_iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position)
279 if((*iter) == sess)
280 return position;
282 return 0;
285 void World::AddQueuedPlayer(WorldSession* sess)
287 sess->SetInQueue(true);
288 m_QueuedPlayer.push_back (sess);
290 // The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
291 WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + 4 + 1);
292 packet << uint8 (AUTH_WAIT_QUEUE);
293 packet << uint32 (0); // BillingTimeRemaining
294 packet << uint8 (0); // BillingPlanFlags
295 packet << uint32 (0); // BillingTimeRested
296 packet << uint8 (sess->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
297 packet << uint32(GetQueuePos (sess)); // position in queue
298 packet << uint8(0); // unk 3.3.0
299 sess->SendPacket (&packet);
302 bool World::RemoveQueuedPlayer(WorldSession* sess)
304 // sessions count including queued to remove (if removed_session set)
305 uint32 sessions = GetActiveSessionCount();
307 uint32 position = 1;
308 Queue::iterator iter = m_QueuedPlayer.begin();
310 // search to remove and count skipped positions
311 bool found = false;
313 for(;iter != m_QueuedPlayer.end(); ++iter, ++position)
315 if(*iter==sess)
317 sess->SetInQueue(false);
318 iter = m_QueuedPlayer.erase(iter);
319 found = true; // removing queued session
320 break;
324 // iter point to next socked after removed or end()
325 // position store position of removed socket and then new position next socket after removed
327 // if session not queued then we need decrease sessions count
328 if(!found && sessions)
329 --sessions;
331 // accept first in queue
332 if( (!m_playerLimit || (int32)sessions < m_playerLimit) && !m_QueuedPlayer.empty() )
334 WorldSession* pop_sess = m_QueuedPlayer.front();
335 pop_sess->SetInQueue(false);
336 pop_sess->SendAuthWaitQue(0);
337 pop_sess->SendAddonsInfo();
339 WorldPacket pkt(SMSG_CLIENTCACHE_VERSION, 4);
340 pkt << uint32(getConfig(CONFIG_UINT32_CLIENTCACHE_VERSION));
341 pop_sess->SendPacket(&pkt);
343 pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK);
344 pop_sess->SendTutorialsData();
346 m_QueuedPlayer.pop_front();
348 // update iter to point first queued socket or end() if queue is empty now
349 iter = m_QueuedPlayer.begin();
350 position = 1;
353 // update position from iter to end()
354 // iter point to first not updated socket, position store new position
355 for(; iter != m_QueuedPlayer.end(); ++iter, ++position)
356 (*iter)->SendAuthWaitQue(position);
358 return found;
361 /// Find a Weather object by the given zoneid
362 Weather* World::FindWeather(uint32 id) const
364 WeatherMap::const_iterator itr = m_weathers.find(id);
366 if(itr != m_weathers.end())
367 return itr->second;
368 else
369 return 0;
372 /// Remove a Weather object for the given zoneid
373 void World::RemoveWeather(uint32 id)
375 // not called at the moment. Kept for completeness
376 WeatherMap::iterator itr = m_weathers.find(id);
378 if(itr != m_weathers.end())
380 delete itr->second;
381 m_weathers.erase(itr);
385 /// Add a Weather object to the list
386 Weather* World::AddWeather(uint32 zone_id)
388 WeatherZoneChances const* weatherChances = sObjectMgr.GetWeatherChances(zone_id);
390 // zone not have weather, ignore
391 if(!weatherChances)
392 return NULL;
394 Weather* w = new Weather(zone_id,weatherChances);
395 m_weathers[w->GetZone()] = w;
396 w->ReGenerate();
397 w->UpdateWeather();
398 return w;
401 /// Initialize config values
402 void World::LoadConfigSettings(bool reload)
404 if(reload)
406 if(!sConfig.Reload())
408 sLog.outError("World settings reload fail: can't read settings from %s.",sConfig.GetFilename().c_str());
409 return;
413 ///- Read the version of the configuration file and warn the user in case of emptiness or mismatch
414 uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
415 if(!confVersion)
417 sLog.outError("*****************************************************************************");
418 sLog.outError(" WARNING: mangosd.conf does not include a ConfVersion variable.");
419 sLog.outError(" Your configuration file may be out of date!");
420 sLog.outError("*****************************************************************************");
421 clock_t pause = 3000 + clock();
422 while (pause > clock())
423 ; // empty body
425 else
427 if (confVersion < _MANGOSDCONFVERSION)
429 sLog.outError("*****************************************************************************");
430 sLog.outError(" WARNING: Your mangosd.conf version indicates your conf file is out of date!");
431 sLog.outError(" Please check for updates, as your current default values may cause");
432 sLog.outError(" unexpected behavior.");
433 sLog.outError("*****************************************************************************");
434 clock_t pause = 3000 + clock();
435 while (pause > clock())
436 ; // empty body
440 ///- Read the player limit and the Message of the day from the config file
441 SetPlayerLimit( sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT), true );
442 SetMotd( sConfig.GetStringDefault("Motd", "Welcome to the Massive Network Game Object Server." ) );
444 ///- Read all rates from the config file
445 setConfigPos(CONFIG_FLOAT_RATE_HEALTH, "Rate.Health", 1.0f);
446 setConfigPos(CONFIG_FLOAT_RATE_POWER_MANA, "Rate.Mana", 1.0f);
447 setConfig(CONFIG_FLOAT_RATE_POWER_RAGE_INCOME, "Rate.Rage.Income", 1.0f);
448 setConfigPos(CONFIG_FLOAT_RATE_POWER_RAGE_LOSS, "Rate.Rage.Loss", 1.0f);
449 setConfig(CONFIG_FLOAT_RATE_POWER_RUNICPOWER_INCOME, "Rate.RunicPower.Income", 1.0f);
450 setConfigPos(CONFIG_FLOAT_RATE_POWER_RUNICPOWER_LOSS, "Rate.RunicPower.Loss", 1.0f);
451 setConfig(CONFIG_FLOAT_RATE_POWER_FOCUS, "Rate.Focus", 1.0f);
452 setConfigPos(CONFIG_FLOAT_RATE_SKILL_DISCOVERY, "Rate.Skill.Discovery", 1.0f);
453 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_POOR, "Rate.Drop.Item.Poor", 1.0f);
454 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_NORMAL, "Rate.Drop.Item.Normal", 1.0f);
455 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_UNCOMMON, "Rate.Drop.Item.Uncommon", 1.0f);
456 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_RARE, "Rate.Drop.Item.Rare", 1.0f);
457 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_EPIC, "Rate.Drop.Item.Epic", 1.0f);
458 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_LEGENDARY, "Rate.Drop.Item.Legendary", 1.0f);
459 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_ARTIFACT, "Rate.Drop.Item.Artifact", 1.0f);
460 setConfigPos(CONFIG_FLOAT_RATE_DROP_ITEM_REFERENCED, "Rate.Drop.Item.Referenced", 1.0f);
461 setConfigPos(CONFIG_FLOAT_RATE_DROP_MONEY, "Rate.Drop.Money", 1.0f);
462 setConfig(CONFIG_FLOAT_RATE_XP_KILL, "Rate.XP.Kill", 1.0f);
463 setConfig(CONFIG_FLOAT_RATE_XP_QUEST, "Rate.XP.Quest", 1.0f);
464 setConfig(CONFIG_FLOAT_RATE_XP_EXPLORE, "Rate.XP.Explore", 1.0f);
465 setConfig(CONFIG_FLOAT_RATE_REPUTATION_GAIN, "Rate.Reputation.Gain", 1.0f);
466 setConfig(CONFIG_FLOAT_RATE_REPUTATION_LOWLEVEL_KILL, "Rate.Reputation.LowLevel.Kill", 1.0f);
467 setConfig(CONFIG_FLOAT_RATE_REPUTATION_LOWLEVEL_QUEST, "Rate.Reputation.LowLevel.Quest", 1.0f);
468 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_NORMAL_DAMAGE, "Rate.Creature.Normal.Damage", 1.0f);
469 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_ELITE_DAMAGE, "Rate.Creature.Elite.Elite.Damage", 1.0f);
470 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_RAREELITE_DAMAGE, "Rate.Creature.Elite.RAREELITE.Damage", 1.0f);
471 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE, "Rate.Creature.Elite.WORLDBOSS.Damage", 1.0f);
472 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_RARE_DAMAGE, "Rate.Creature.Elite.RARE.Damage", 1.0f);
473 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_NORMAL_HP, "Rate.Creature.Normal.HP", 1.0f);
474 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_ELITE_HP, "Rate.Creature.Elite.Elite.HP", 1.0f);
475 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_RAREELITE_HP, "Rate.Creature.Elite.RAREELITE.HP", 1.0f);
476 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_WORLDBOSS_HP, "Rate.Creature.Elite.WORLDBOSS.HP", 1.0f);
477 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_RARE_HP, "Rate.Creature.Elite.RARE.HP", 1.0f);
478 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_NORMAL_SPELLDAMAGE, "Rate.Creature.Normal.SpellDamage", 1.0f);
479 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE, "Rate.Creature.Elite.Elite.SpellDamage", 1.0f);
480 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE, "Rate.Creature.Elite.RAREELITE.SpellDamage", 1.0f);
481 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE, "Rate.Creature.Elite.WORLDBOSS.SpellDamage", 1.0f);
482 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_ELITE_RARE_SPELLDAMAGE, "Rate.Creature.Elite.RARE.SpellDamage", 1.0f);
483 setConfigPos(CONFIG_FLOAT_RATE_CREATURE_AGGRO, "Rate.Creature.Aggro", 1.0f);
484 setConfig(CONFIG_FLOAT_RATE_REST_INGAME, "Rate.Rest.InGame", 1.0f);
485 setConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_TAVERN_OR_CITY, "Rate.Rest.Offline.InTavernOrCity", 1.0f);
486 setConfig(CONFIG_FLOAT_RATE_REST_OFFLINE_IN_WILDERNESS, "Rate.Rest.Offline.InWilderness", 1.0f);
487 setConfigPos(CONFIG_FLOAT_RATE_DAMAGE_FALL, "Rate.Damage.Fall", 1.0f);
488 setConfigPos(CONFIG_FLOAT_RATE_AUCTION_TIME, "Rate.Auction.Time", 1.0f);
489 setConfig(CONFIG_FLOAT_RATE_AUCTION_DEPOSIT, "Rate.Auction.Deposit", 1.0f);
490 setConfig(CONFIG_FLOAT_RATE_AUCTION_CUT, "Rate.Auction.Cut", 1.0f);
491 setConfig(CONFIG_FLOAT_RATE_HONOR, "Rate.Honor",1.0f);
492 setConfigPos(CONFIG_FLOAT_RATE_MINING_AMOUNT, "Rate.Mining.Amount", 1.0f);
493 setConfigPos(CONFIG_FLOAT_RATE_MINING_NEXT, "Rate.Mining.Next", 1.0f);
494 setConfigPos(CONFIG_FLOAT_RATE_INSTANCE_RESET_TIME, "Rate.InstanceResetTime", 1.0f);
495 setConfigPos(CONFIG_FLOAT_RATE_TALENT, "Rate.Talent", 1.0f);
496 setConfigPos(CONFIG_FLOAT_RATE_CORPSE_DECAY_LOOTED, "Rate.Corpse.Decay.Looted", 0.1f);
498 setConfigMinMax(CONFIG_FLOAT_RATE_TARGET_POS_RECALCULATION_RANGE, "TargetPosRecalculateRange", 1.5f, CONTACT_DISTANCE, ATTACK_DISTANCE);
500 setConfigPos(CONFIG_FLOAT_RATE_DURABILITY_LOSS_DAMAGE, "DurabilityLossChance.Damage", 0.5f);
501 setConfigPos(CONFIG_FLOAT_RATE_DURABILITY_LOSS_ABSORB, "DurabilityLossChance.Absorb", 0.5f);
502 setConfigPos(CONFIG_FLOAT_RATE_DURABILITY_LOSS_PARRY, "DurabilityLossChance.Parry", 0.05f);
503 setConfigPos(CONFIG_FLOAT_RATE_DURABILITY_LOSS_BLOCK, "DurabilityLossChance.Block", 0.05f);
505 setConfigPos(CONFIG_FLOAT_LISTEN_RANGE_SAY, "ListenRange.Say", 25.0f);
506 setConfigPos(CONFIG_FLOAT_LISTEN_RANGE_YELL, "ListenRange.Yell", 300.0f);
507 setConfigPos(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE, "ListenRange.TextEmote", 25.0f);
509 setConfigPos(CONFIG_FLOAT_GROUP_XP_DISTANCE, "MaxGroupXPDistance", 74.0f);
510 setConfigPos(CONFIG_FLOAT_SIGHT_GUARDER, "GuarderSight", 50.0f);
511 setConfigPos(CONFIG_FLOAT_SIGHT_MONSTER, "MonsterSight", 50.0f);
513 setConfigPos(CONFIG_FLOAT_CREATURE_FAMILY_ASSISTANCE_RADIUS, "CreatureFamilyAssistanceRadius", 10.0f);
514 setConfigPos(CONFIG_FLOAT_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS, "CreatureFamilyFleeAssistanceRadius", 30.0f);
516 ///- Read other configuration items from the config file
517 setConfigMinMax(CONFIG_UINT32_COMPRESSION, "Compression", 1, 1, 9);
518 setConfig(CONFIG_BOOL_ADDON_CHANNEL, "AddonChannel", true);
519 setConfig(CONFIG_BOOL_GRID_UNLOAD, "GridUnload", true);
520 setConfigPos(CONFIG_UINT32_INTERVAL_SAVE, "PlayerSaveInterval", 15 * MINUTE * IN_MILISECONDS);
522 setConfigMin(CONFIG_UINT32_INTERVAL_GRIDCLEAN, "GridCleanUpDelay", 5 * MINUTE * IN_MILISECONDS, MIN_GRID_DELAY);
523 if (reload)
524 sMapMgr.SetGridCleanUpDelay(getConfig(CONFIG_UINT32_INTERVAL_GRIDCLEAN));
526 setConfigMin(CONFIG_UINT32_INTERVAL_MAPUPDATE, "MapUpdateInterval", 100, MIN_MAP_UPDATE_DELAY);
527 if (reload)
528 sMapMgr.SetMapUpdateInterval(getConfig(CONFIG_UINT32_INTERVAL_MAPUPDATE));
530 setConfig(CONFIG_UINT32_INTERVAL_CHANGEWEATHER, "ChangeWeatherInterval", 10 * MINUTE * IN_MILISECONDS);
532 if (configNoReload(reload, CONFIG_UINT32_PORT_WORLD, "WorldServerPort", DEFAULT_WORLDSERVER_PORT))
533 setConfig(CONFIG_UINT32_PORT_WORLD, "WorldServerPort", DEFAULT_WORLDSERVER_PORT);
535 if (configNoReload(reload, CONFIG_UINT32_SOCKET_SELECTTIME, "SocketSelectTime", DEFAULT_SOCKET_SELECT_TIME))
536 setConfig(CONFIG_UINT32_SOCKET_SELECTTIME, "SocketSelectTime", DEFAULT_SOCKET_SELECT_TIME);
538 if (configNoReload(reload, CONFIG_UINT32_GAME_TYPE, "GameType", 0))
539 setConfig(CONFIG_UINT32_GAME_TYPE, "GameType", 0);
541 if (configNoReload(reload, CONFIG_UINT32_REALM_ZONE, "RealmZone", REALM_ZONE_DEVELOPMENT))
542 setConfig(CONFIG_UINT32_REALM_ZONE, "RealmZone", REALM_ZONE_DEVELOPMENT);
544 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_ACCOUNTS, "AllowTwoSide.Accounts", false);
545 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHAT, "AllowTwoSide.Interaction.Chat", false);
546 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_CHANNEL, "AllowTwoSide.Interaction.Channel", false);
547 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP, "AllowTwoSide.Interaction.Group", false);
548 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GUILD, "AllowTwoSide.Interaction.Guild", false);
549 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_AUCTION, "AllowTwoSide.Interaction.Auction", false);
550 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_MAIL, "AllowTwoSide.Interaction.Mail", false);
551 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST, "AllowTwoSide.WhoList", false);
552 setConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_ADD_FRIEND, "AllowTwoSide.AddFriend", false);
554 setConfig(CONFIG_UINT32_STRICT_PLAYER_NAMES, "StrictPlayerNames", 0);
555 setConfig(CONFIG_UINT32_STRICT_CHARTER_NAMES, "StrictCharterNames", 0);
556 setConfig(CONFIG_UINT32_STRICT_PET_NAMES, "StrictPetNames", 0);
558 setConfigMinMax(CONFIG_UINT32_MIN_PLAYER_NAME, "MinPlayerName", 2, 1, MAX_PLAYER_NAME);
559 setConfigMinMax(CONFIG_UINT32_MIN_CHARTER_NAME, "MinCharterName", 2, 1, MAX_CHARTER_NAME);
560 setConfigMinMax(CONFIG_UINT32_MIN_PET_NAME, "MinPetName", 2, 1, MAX_PET_NAME);
562 setConfig(CONFIG_UINT32_CHARACTERS_CREATING_DISABLED, "CharactersCreatingDisabled", 0);
564 setConfigMinMax(CONFIG_UINT32_CHARACTERS_PER_REALM, "CharactersPerRealm", 10, 1, 10);
566 // must be after CONFIG_UINT32_CHARACTERS_PER_REALM
567 setConfigMin(CONFIG_UINT32_CHARACTERS_PER_ACCOUNT, "CharactersPerAccount", 50, getConfig(CONFIG_UINT32_CHARACTERS_PER_REALM));
569 setConfigMinMax(CONFIG_UINT32_HEROIC_CHARACTERS_PER_REALM, "HeroicCharactersPerRealm", 1, 1, 10);
571 setConfig(CONFIG_UINT32_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING, "MinLevelForHeroicCharacterCreating", 55);
573 setConfigMinMax(CONFIG_UINT32_SKIP_CINEMATICS, "SkipCinematics", 0, 0, 2);
575 if (configNoReload(reload, CONFIG_UINT32_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL))
576 setConfigMinMax(CONFIG_UINT32_MAX_PLAYER_LEVEL, "MaxPlayerLevel", DEFAULT_MAX_LEVEL, 1, DEFAULT_MAX_LEVEL);
578 setConfigMinMax(CONFIG_UINT32_START_PLAYER_LEVEL, "StartPlayerLevel", 1, 1, getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL));
579 setConfigMinMax(CONFIG_UINT32_START_HEROIC_PLAYER_LEVEL, "StartHeroicPlayerLevel", 55, 1, getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL));
581 setConfigMinMax(CONFIG_UINT32_START_PLAYER_MONEY, "StartPlayerMoney", 0, 0, MAX_MONEY_AMOUNT);
583 setConfigPos(CONFIG_UINT32_MAX_HONOR_POINTS, "MaxHonorPoints", 75000);
585 setConfigMinMax(CONFIG_UINT32_START_HONOR_POINTS, "StartHonorPoints", 0, 0, getConfig(CONFIG_UINT32_MAX_HONOR_POINTS));
587 setConfigPos(CONFIG_UINT32_MAX_ARENA_POINTS, "MaxArenaPoints", 5000);
589 setConfigMinMax(CONFIG_UINT32_START_ARENA_POINTS, "StartArenaPoints", 0, 0, getConfig(CONFIG_UINT32_MAX_ARENA_POINTS));
591 setConfig(CONFIG_BOOL_ALL_TAXI_PATHS, "AllFlightPaths", false);
593 setConfig(CONFIG_BOOL_INSTANCE_IGNORE_LEVEL, "Instance.IgnoreLevel", false);
594 setConfig(CONFIG_BOOL_INSTANCE_IGNORE_RAID, "Instance.IgnoreRaid", false);
596 setConfig(CONFIG_BOOL_CAST_UNSTUCK, "CastUnstuck", true);
597 setConfig(CONFIG_UINT32_MAX_SPELL_CASTS_IN_CHAIN, "MaxSpellCastsInChain", 10);
598 setConfig(CONFIG_UINT32_INSTANCE_RESET_TIME_HOUR, "Instance.ResetTimeHour", 4);
599 setConfig(CONFIG_UINT32_INSTANCE_UNLOAD_DELAY, "Instance.UnloadDelay", 30 * MINUTE * IN_MILISECONDS);
601 setConfig(CONFIG_UINT32_MAX_PRIMARY_TRADE_SKILL, "MaxPrimaryTradeSkill", 2);
602 setConfigMinMax(CONFIG_UINT32_MIN_PETITION_SIGNS, "MinPetitionSigns", 9, 0, 9);
604 setConfig(CONFIG_UINT32_GM_LOGIN_STATE, "GM.LoginState", 2);
605 setConfig(CONFIG_UINT32_GM_VISIBLE_STATE, "GM.Visible", 2);
606 setConfig(CONFIG_UINT32_GM_ACCEPT_TICKETS, "GM.AcceptTickets", 2);
607 setConfig(CONFIG_UINT32_GM_CHAT, "GM.Chat", 2);
608 setConfig(CONFIG_UINT32_GM_WISPERING_TO, "GM.WhisperingTo", 2);
610 setConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST, "GM.InGMList.Level", SEC_ADMINISTRATOR);
611 setConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST, "GM.InWhoList.Level", SEC_ADMINISTRATOR);
612 setConfig(CONFIG_BOOL_GM_LOG_TRADE, "GM.LogTrade", false);
614 setConfigMinMax(CONFIG_UINT32_START_GM_LEVEL, "GM.StartLevel", 1, getConfig(CONFIG_UINT32_START_PLAYER_LEVEL), MAX_LEVEL);
615 setConfig(CONFIG_BOOL_GM_LOWER_SECURITY, "GM.LowerSecurity", false);
616 setConfig(CONFIG_BOOL_GM_ALLOW_ACHIEVEMENT_GAINS, "GM.AllowAchievementGain", true);
618 setConfig(CONFIG_UINT32_GROUP_VISIBILITY, "Visibility.GroupMode", 0);
620 setConfig(CONFIG_UINT32_MAIL_DELIVERY_DELAY, "MailDeliveryDelay", HOUR);
622 setConfigPos(CONFIG_UINT32_UPTIME_UPDATE, "UpdateUptimeInterval", 10);
623 if (reload)
625 m_timers[WUPDATE_UPTIME].SetInterval(getConfig(CONFIG_UINT32_UPTIME_UPDATE)*MINUTE*IN_MILISECONDS);
626 m_timers[WUPDATE_UPTIME].Reset();
629 setConfig(CONFIG_UINT32_SKILL_CHANCE_ORANGE, "SkillChance.Orange", 100);
630 setConfig(CONFIG_UINT32_SKILL_CHANCE_YELLOW, "SkillChance.Yellow", 75);
631 setConfig(CONFIG_UINT32_SKILL_CHANCE_GREEN, "SkillChance.Green", 25);
632 setConfig(CONFIG_UINT32_SKILL_CHANCE_GREY, "SkillChance.Grey", 0);
634 setConfigPos(CONFIG_UINT32_SKILL_CHANCE_MINING_STEPS, "SkillChance.MiningSteps", 75);
635 setConfigPos(CONFIG_UINT32_SKILL_CHANCE_SKINNING_STEPS, "SkillChance.SkinningSteps", 75);
637 setConfig(CONFIG_BOOL_SKILL_PROSPECTING, "SkillChance.Prospecting", false);
638 setConfig(CONFIG_BOOL_SKILL_MILLING, "SkillChance.Milling", false);
640 setConfigPos(CONFIG_UINT32_SKILL_GAIN_CRAFTING, "SkillGain.Crafting", 1);
641 setConfigPos(CONFIG_UINT32_SKILL_GAIN_DEFENSE, "SkillGain.Defense", 1);
642 setConfigPos(CONFIG_UINT32_SKILL_GAIN_GATHERING, "SkillGain.Gathering", 1);
643 setConfig(CONFIG_UINT32_SKILL_GAIN_WEAPON, "SkillGain.Weapon", 1);
645 setConfig(CONFIG_UINT32_MAX_OVERSPEED_PINGS, "MaxOverspeedPings", 2);
646 if (getConfig(CONFIG_UINT32_MAX_OVERSPEED_PINGS) != 0 && getConfig(CONFIG_UINT32_MAX_OVERSPEED_PINGS) < 2)
648 sLog.outError("MaxOverspeedPings (%i) must be in range 2..infinity (or 0 to disable check). Set to 2.", getConfig(CONFIG_UINT32_MAX_OVERSPEED_PINGS));
649 setConfig(CONFIG_UINT32_MAX_OVERSPEED_PINGS, 2);
652 setConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY, "SaveRespawnTimeImmediately", true);
653 setConfig(CONFIG_BOOL_WEATHER, "ActivateWeather", true);
655 setConfig(CONFIG_BOOL_ALWAYS_MAX_SKILL_FOR_LEVEL, "AlwaysMaxSkillForLevel", false);
657 if (configNoReload(reload, CONFIG_UINT32_EXPANSION, "Expansion", MAX_EXPANSION))
658 setConfigMinMax(CONFIG_UINT32_EXPANSION, "Expansion", MAX_EXPANSION, 0, MAX_EXPANSION);
660 setConfig(CONFIG_UINT32_CHATFLOOD_MESSAGE_COUNT, "ChatFlood.MessageCount", 10);
661 setConfig(CONFIG_UINT32_CHATFLOOD_MESSAGE_DELAY, "ChatFlood.MessageDelay", 1);
662 setConfig(CONFIG_UINT32_CHATFLOOD_MUTE_TIME, "ChatFlood.MuteTime", 10);
664 setConfig(CONFIG_BOOL_EVENT_ANNOUNCE, "Event.Announce", false);
666 setConfig(CONFIG_UINT32_CREATURE_FAMILY_ASSISTANCE_DELAY, "CreatureFamilyAssistanceDelay", 1500);
667 setConfig(CONFIG_UINT32_CREATURE_FAMILY_FLEE_DELAY, "CreatureFamilyFleeDelay", 7000);
669 setConfig(CONFIG_UINT32_WORLD_BOSS_LEVEL_DIFF, "WorldBossLevelDiff", 3);
671 // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100)
672 setConfig(CONFIG_UINT32_QUEST_LOW_LEVEL_HIDE_DIFF, "Quests.LowLevelHideDiff", 4);
673 if (getConfig(CONFIG_UINT32_QUEST_LOW_LEVEL_HIDE_DIFF) > MAX_LEVEL)
674 setConfig(CONFIG_UINT32_QUEST_LOW_LEVEL_HIDE_DIFF, MAX_LEVEL);
675 setConfig(CONFIG_UINT32_QUEST_HIGH_LEVEL_HIDE_DIFF, "Quests.HighLevelHideDiff", 7);
676 if (getConfig(CONFIG_UINT32_QUEST_HIGH_LEVEL_HIDE_DIFF) > MAX_LEVEL)
677 setConfig(CONFIG_UINT32_QUEST_HIGH_LEVEL_HIDE_DIFF, MAX_LEVEL);
679 setConfig(CONFIG_BOOL_DETECT_POS_COLLISION, "DetectPosCollision", true);
681 setConfig(CONFIG_BOOL_RESTRICTED_LFG_CHANNEL, "Channel.RestrictedLfg", true);
682 setConfig(CONFIG_BOOL_SILENTLY_GM_JOIN_TO_CHANNEL, "Channel.SilentlyGMJoin", false);
684 setConfig(CONFIG_BOOL_TALENTS_INSPECTING, "TalentsInspecting", true);
685 setConfig(CONFIG_BOOL_CHAT_FAKE_MESSAGE_PREVENTING, "ChatFakeMessagePreventing", false);
687 setConfig(CONFIG_UINT32_CHAT_STRICT_LINK_CHECKING_SEVERITY, "ChatStrictLinkChecking.Severity", 0);
688 setConfig(CONFIG_UINT32_CHAT_STRICT_LINK_CHECKING_KICK, "ChatStrictLinkChecking.Kick", 0);
690 setConfigPos(CONFIG_UINT32_CORPSE_DECAY_NORMAL, "Corpse.Decay.NORMAL", 60);
691 setConfigPos(CONFIG_UINT32_CORPSE_DECAY_RARE, "Corpse.Decay.RARE", 300);
692 setConfigPos(CONFIG_UINT32_CORPSE_DECAY_ELITE, "Corpse.Decay.ELITE", 300);
693 setConfigPos(CONFIG_UINT32_CORPSE_DECAY_RAREELITE, "Corpse.Decay.RAREELITE", 300);
694 setConfigPos(CONFIG_UINT32_CORPSE_DECAY_WORLDBOSS, "Corpse.Decay.WORLDBOSS", 3600);
696 setConfig(CONFIG_INT32_DEATH_SICKNESS_LEVEL, "Death.SicknessLevel", 11);
698 setConfig(CONFIG_BOOL_DEATH_CORPSE_RECLAIM_DELAY_PVP, "Death.CorpseReclaimDelay.PvP", true);
699 setConfig(CONFIG_BOOL_DEATH_CORPSE_RECLAIM_DELAY_PVE, "Death.CorpseReclaimDelay.PvE", true);
700 setConfig(CONFIG_BOOL_DEATH_BONES_WORLD, "Death.Bones.World", true);
701 setConfig(CONFIG_BOOL_DEATH_BONES_BG_OR_ARENA, "Death.Bones.BattlegroundOrArena", true);
703 setConfig(CONFIG_FLOAT_THREAT_RADIUS, "ThreatRadius", 100.0f);
705 // always use declined names in the russian client
706 if (getConfig(CONFIG_UINT32_REALM_ZONE) == REALM_ZONE_RUSSIAN)
707 setConfig(CONFIG_BOOL_DECLINED_NAMES_USED, true);
708 else
709 setConfig(CONFIG_BOOL_DECLINED_NAMES_USED, "DeclinedNames", false);
711 setConfig(CONFIG_BOOL_BATTLEGROUND_CAST_DESERTER, "Battleground.CastDeserter", true);
712 setConfigMinMax(CONFIG_UINT32_BATTLEGROUND_QUEUE_ANNOUNCER_JOIN, "Battleground.QueueAnnouncer.Join", 0, 0, 2);
713 setConfig(CONFIG_BOOL_BATTLEGROUND_QUEUE_ANNOUNCER_START, "Battleground.QueueAnnouncer.Start", false);
714 setConfig(CONFIG_UINT32_BATTLEGROUND_INVITATION_TYPE, "Battleground.InvitationType", 0);
715 setConfig(CONFIG_UINT32_BATTLEGROUND_PREMATURE_FINISH_TIMER, "BattleGround.PrematureFinishTimer", 5 * MINUTE * IN_MILISECONDS);
716 setConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH, "BattleGround.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILISECONDS);
717 setConfig(CONFIG_UINT32_ARENA_MAX_RATING_DIFFERENCE, "Arena.MaxRatingDifference", 150);
718 setConfig(CONFIG_UINT32_ARENA_RATING_DISCARD_TIMER, "Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILISECONDS);
719 setConfig(CONFIG_BOOL_ARENA_AUTO_DISTRIBUTE_POINTS, "Arena.AutoDistributePoints", false);
720 setConfig(CONFIG_UINT32_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, "Arena.AutoDistributeInterval", 7);
721 setConfig(CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_JOIN, "Arena.QueueAnnouncer.Join", false);
722 setConfig(CONFIG_BOOL_ARENA_QUEUE_ANNOUNCER_EXIT, "Arena.QueueAnnouncer.Exit", false);
723 setConfig(CONFIG_UINT32_ARENA_SEASON_ID, "Arena.ArenaSeason.ID", 1);
724 setConfig(CONFIG_BOOL_ARENA_SEASON_IN_PROGRESS, "Arena.ArenaSeason.InProgress", true);
726 setConfig(CONFIG_BOOL_OFFHAND_CHECK_AT_TALENTS_RESET, "OffhandCheckAtTalentsReset", false);
728 setConfig(CONFIG_BOOL_KICK_PLAYER_ON_BAD_PACKET, "Network.KickOnBadPacket", false);
730 if(int clientCacheId = sConfig.GetIntDefault("ClientCacheVersion", 0))
732 // overwrite DB/old value
733 if(clientCacheId > 0)
735 setConfig(CONFIG_UINT32_CLIENTCACHE_VERSION, clientCacheId);
736 sLog.outString("Client cache version set to: %u", clientCacheId);
738 else
739 sLog.outError("ClientCacheVersion can't be negative %d, ignored.", clientCacheId);
742 setConfig(CONFIG_UINT32_INSTANT_LOGOUT, "InstantLogout", SEC_MODERATOR);
744 setConfigMin(CONFIG_UINT32_GUILD_EVENT_LOG_COUNT, "Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS, GUILD_EVENTLOG_MAX_RECORDS);
745 setConfigMin(CONFIG_UINT32_GUILD_BANK_EVENT_LOG_COUNT, "Guild.BankEventLogRecordsCount", GUILD_BANK_MAX_LOGS, GUILD_BANK_MAX_LOGS);
747 setConfig(CONFIG_UINT32_TIMERBAR_FATIGUE_GMLEVEL, "TimerBar.Fatigue.GMLevel", SEC_CONSOLE);
748 setConfig(CONFIG_UINT32_TIMERBAR_FATIGUE_MAX, "TimerBar.Fatigue.Max", 60);
749 setConfig(CONFIG_UINT32_TIMERBAR_BREATH_GMLEVEL, "TimerBar.Breath.GMLevel", SEC_CONSOLE);
750 setConfig(CONFIG_UINT32_TIMERBAR_BREATH_MAX, "TimerBar.Breath.Max", 180);
751 setConfig(CONFIG_UINT32_TIMERBAR_FIRE_GMLEVEL, "TimerBar.Fire.GMLevel", SEC_CONSOLE);
752 setConfig(CONFIG_UINT32_TIMERBAR_FIRE_MAX, "TimerBar.Fire.Max", 1);
754 m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1);
755 if(m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
757 sLog.outError("Visibility.Distance.Grey.Unit can't be greater %f",MAX_VISIBILITY_DISTANCE);
758 m_VisibleUnitGreyDistance = MAX_VISIBILITY_DISTANCE;
760 m_VisibleObjectGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Object", 10);
761 if(m_VisibleObjectGreyDistance > MAX_VISIBILITY_DISTANCE)
763 sLog.outError("Visibility.Distance.Grey.Object can't be greater %f",MAX_VISIBILITY_DISTANCE);
764 m_VisibleObjectGreyDistance = MAX_VISIBILITY_DISTANCE;
767 //visibility on continents
768 m_MaxVisibleDistanceOnContinents = sConfig.GetFloatDefault("Visibility.Distance.Continents", DEFAULT_VISIBILITY_DISTANCE);
769 if(m_MaxVisibleDistanceOnContinents < 45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO))
771 sLog.outError("Visibility.Distance.Continents can't be less max aggro radius %f", 45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO));
772 m_MaxVisibleDistanceOnContinents = 45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
774 else if(m_MaxVisibleDistanceOnContinents + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
776 sLog.outError("Visibility.Distance.Continents can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
777 m_MaxVisibleDistanceOnContinents = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
780 //visibility in instances
781 m_MaxVisibleDistanceInInctances = sConfig.GetFloatDefault("Visibility.Distance.Instances", DEFAULT_VISIBILITY_INSTANCE);
782 if(m_MaxVisibleDistanceInInctances < 45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO))
784 sLog.outError("Visibility.Distance.Instances can't be less max aggro radius %f",45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO));
785 m_MaxVisibleDistanceInInctances = 45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
787 else if(m_MaxVisibleDistanceInInctances + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
789 sLog.outError("Visibility.Distance.Instances can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
790 m_MaxVisibleDistanceInInctances = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
793 //visibility in BG/Arenas
794 m_MaxVisibleDistanceInBGArenas = sConfig.GetFloatDefault("Visibility.Distance.BGArenas", DEFAULT_VISIBILITY_BGARENAS);
795 if(m_MaxVisibleDistanceInBGArenas < 45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO))
797 sLog.outError("Visibility.Distance.BGArenas can't be less max aggro radius %f",45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO));
798 m_MaxVisibleDistanceInBGArenas = 45*getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
800 else if(m_MaxVisibleDistanceInBGArenas + m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE)
802 sLog.outError("Visibility.Distance.BGArenas can't be greater %f",MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance);
803 m_MaxVisibleDistanceInBGArenas = MAX_VISIBILITY_DISTANCE - m_VisibleUnitGreyDistance;
806 m_MaxVisibleDistanceForObject = sConfig.GetFloatDefault("Visibility.Distance.Object", DEFAULT_VISIBILITY_DISTANCE);
807 if(m_MaxVisibleDistanceForObject < INTERACTION_DISTANCE)
809 sLog.outError("Visibility.Distance.Object can't be less max aggro radius %f",float(INTERACTION_DISTANCE));
810 m_MaxVisibleDistanceForObject = INTERACTION_DISTANCE;
812 else if(m_MaxVisibleDistanceForObject + m_VisibleObjectGreyDistance > MAX_VISIBILITY_DISTANCE)
814 sLog.outError("Visibility.Distance.Object can't be greater %f",MAX_VISIBILITY_DISTANCE-m_VisibleObjectGreyDistance);
815 m_MaxVisibleDistanceForObject = MAX_VISIBILITY_DISTANCE - m_VisibleObjectGreyDistance;
817 m_MaxVisibleDistanceInFlight = sConfig.GetFloatDefault("Visibility.Distance.InFlight", DEFAULT_VISIBILITY_DISTANCE);
818 if(m_MaxVisibleDistanceInFlight + m_VisibleObjectGreyDistance > MAX_VISIBILITY_DISTANCE)
820 sLog.outError("Visibility.Distance.InFlight can't be greater %f",MAX_VISIBILITY_DISTANCE-m_VisibleObjectGreyDistance);
821 m_MaxVisibleDistanceInFlight = MAX_VISIBILITY_DISTANCE - m_VisibleObjectGreyDistance;
824 ///- Read the "Data" directory from the config file
825 std::string dataPath = sConfig.GetStringDefault("DataDir","./");
826 if( dataPath.at(dataPath.length()-1)!='/' && dataPath.at(dataPath.length()-1)!='\\' )
827 dataPath.append("/");
829 if(reload)
831 if(dataPath!=m_dataPath)
832 sLog.outError("DataDir option can't be changed at mangosd.conf reload, using current value (%s).",m_dataPath.c_str());
834 else
836 m_dataPath = dataPath;
837 sLog.outString("Using DataDir %s",m_dataPath.c_str());
840 bool enableLOS = sConfig.GetBoolDefault("vmap.enableLOS", false);
841 bool enableHeight = sConfig.GetBoolDefault("vmap.enableHeight", false);
842 std::string ignoreMapIds = sConfig.GetStringDefault("vmap.ignoreMapIds", "");
843 std::string ignoreSpellIds = sConfig.GetStringDefault("vmap.ignoreSpellIds", "");
844 VMAP::VMapFactory::createOrGetVMapManager()->setEnableLineOfSightCalc(enableLOS);
845 VMAP::VMapFactory::createOrGetVMapManager()->setEnableHeightCalc(enableHeight);
846 VMAP::VMapFactory::createOrGetVMapManager()->preventMapsFromBeingUsed(ignoreMapIds.c_str());
847 VMAP::VMapFactory::preventSpellsFromBeingTestedForLoS(ignoreSpellIds.c_str());
848 sLog.outString( "WORLD: VMap support included. LineOfSight:%i, getHeight:%i",enableLOS, enableHeight);
849 sLog.outString( "WORLD: VMap data directory is: %svmaps",m_dataPath.c_str());
850 sLog.outString( "WORLD: VMap config keys are: vmap.enableLOS, vmap.enableHeight, vmap.ignoreMapIds, vmap.ignoreSpellIds");
853 /// Initialize the World
854 void World::SetInitialWorldSettings()
856 ///- Initialize the random number generator
857 srand((unsigned int)time(NULL));
859 ///- Time server startup
860 uint32 uStartTime = getMSTime();
862 ///- Initialize config settings
863 LoadConfigSettings();
865 ///- Init highest guids before any table loading to prevent using not initialized guids in some code.
866 sObjectMgr.SetHighestGuids();
868 ///- Check the existence of the map files for all races' startup areas.
869 if( !MapManager::ExistMapAndVMap(0,-6240.32f, 331.033f)
870 ||!MapManager::ExistMapAndVMap(0,-8949.95f,-132.493f)
871 ||!MapManager::ExistMapAndVMap(0,-8949.95f,-132.493f)
872 ||!MapManager::ExistMapAndVMap(1,-618.518f,-4251.67f)
873 ||!MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f)
874 ||!MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f)
875 ||!MapManager::ExistMapAndVMap(1,-2917.58f,-257.98f)
876 ||m_configUint32Values[CONFIG_UINT32_EXPANSION] && (
877 !MapManager::ExistMapAndVMap(530,10349.6f,-6357.29f) || !MapManager::ExistMapAndVMap(530,-3961.64f,-13931.2f) ) )
879 sLog.outError("Correct *.map files not found in path '%smaps' or *.vmap/*vmdir files in '%svmaps'. Please place *.map/*.vmap/*.vmdir files in appropriate directories or correct the DataDir value in the mangosd.conf file.",m_dataPath.c_str(),m_dataPath.c_str());
880 exit(1);
883 ///- Loading strings. Getting no records means core load has to be canceled because no error message can be output.
884 sLog.outString();
885 sLog.outString("Loading MaNGOS strings...");
886 if (!sObjectMgr.LoadMangosStrings())
887 exit(1); // Error message displayed in function already
889 ///- Update the realm entry in the database with the realm type from the config file
890 //No SQL injection as values are treated as integers
892 // not send custom type REALM_FFA_PVP to realm list
893 uint32 server_type = IsFFAPvPRealm() ? REALM_TYPE_PVP : getConfig(CONFIG_UINT32_GAME_TYPE);
894 uint32 realm_zone = getConfig(CONFIG_UINT32_REALM_ZONE);
895 loginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID);
897 ///- Remove the bones after a restart
898 CharacterDatabase.PExecute("DELETE FROM corpse WHERE corpse_type = '0'");
900 ///- Load the DBC files
901 sLog.outString("Initialize data stores...");
902 LoadDBCStores(m_dataPath);
903 DetectDBCLang();
905 sLog.outString( "Loading Script Names...");
906 sObjectMgr.LoadScriptNames();
908 sLog.outString( "Loading InstanceTemplate..." );
909 sObjectMgr.LoadInstanceTemplate();
911 sLog.outString( "Loading SkillLineAbilityMultiMap Data..." );
912 sSpellMgr.LoadSkillLineAbilityMap();
914 ///- Clean up and pack instances
915 sLog.outString( "Cleaning up instances..." );
916 sInstanceSaveMgr.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
918 sLog.outString( "Packing instances..." );
919 sInstanceSaveMgr.PackInstances();
921 sLog.outString( "Packing groups..." );
922 sObjectMgr.PackGroupIds();
924 sLog.outString();
925 sLog.outString( "Loading Localization strings..." );
926 sObjectMgr.LoadCreatureLocales();
927 sObjectMgr.LoadGameObjectLocales();
928 sObjectMgr.LoadItemLocales();
929 sObjectMgr.LoadQuestLocales();
930 sObjectMgr.LoadNpcTextLocales();
931 sObjectMgr.LoadPageTextLocales();
932 sObjectMgr.LoadGossipMenuItemsLocales();
933 sObjectMgr.LoadPointOfInterestLocales();
934 sObjectMgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
935 sLog.outString( ">>> Localization strings loaded" );
936 sLog.outString();
938 sLog.outString( "Loading Page Texts..." );
939 sObjectMgr.LoadPageTexts();
941 sLog.outString( "Loading Game Object Templates..." ); // must be after LoadPageTexts
942 sObjectMgr.LoadGameobjectInfo();
944 sLog.outString( "Loading Spell Chain Data..." );
945 sSpellMgr.LoadSpellChains();
947 sLog.outString( "Loading Spell Elixir types..." );
948 sSpellMgr.LoadSpellElixirs();
950 sLog.outString( "Loading Spell Learn Skills..." );
951 sSpellMgr.LoadSpellLearnSkills(); // must be after LoadSpellChains
953 sLog.outString( "Loading Spell Learn Spells..." );
954 sSpellMgr.LoadSpellLearnSpells();
956 sLog.outString( "Loading Spell Proc Event conditions..." );
957 sSpellMgr.LoadSpellProcEvents();
959 sLog.outString( "Loading Spell Bonus Data..." );
960 sSpellMgr.LoadSpellBonusess();
962 sLog.outString( "Loading Spell Proc Item Enchant..." );
963 sSpellMgr.LoadSpellProcItemEnchant(); // must be after LoadSpellChains
965 sLog.outString( "Loading Aggro Spells Definitions...");
966 sSpellMgr.LoadSpellThreats();
968 sLog.outString( "Loading NPC Texts..." );
969 sObjectMgr.LoadGossipText();
971 sLog.outString( "Loading Item Random Enchantments Table..." );
972 LoadRandomEnchantmentsTable();
974 sLog.outString( "Loading Items..." ); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
975 sObjectMgr.LoadItemPrototypes();
977 sLog.outString( "Loading Item Texts..." );
978 sObjectMgr.LoadItemTexts();
980 sLog.outString( "Loading Creature Model Based Info Data..." );
981 sObjectMgr.LoadCreatureModelInfo();
983 sLog.outString( "Loading Equipment templates...");
984 sObjectMgr.LoadEquipmentTemplates();
986 sLog.outString( "Loading Creature templates..." );
987 sObjectMgr.LoadCreatureTemplates();
989 sLog.outString( "Loading SpellsScriptTarget...");
990 sSpellMgr.LoadSpellScriptTarget(); // must be after LoadCreatureTemplates and LoadGameobjectInfo
992 sLog.outString( "Loading ItemRequiredTarget...");
993 sObjectMgr.LoadItemRequiredTarget();
995 sLog.outString( "Loading Creature Reputation OnKill Data..." );
996 sObjectMgr.LoadReputationOnKill();
998 sLog.outString( "Loading Points Of Interest Data..." );
999 sObjectMgr.LoadPointsOfInterest();
1001 sLog.outString( "Loading Creature Data..." );
1002 sObjectMgr.LoadCreatures();
1004 sLog.outString( "Loading pet levelup spells..." );
1005 sSpellMgr.LoadPetLevelupSpellMap();
1007 sLog.outString( "Loading pet default spell additional to levelup spells..." );
1008 sSpellMgr.LoadPetDefaultSpells();
1010 sLog.outString( "Loading Creature Addon Data..." );
1011 sLog.outString();
1012 sObjectMgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
1013 sLog.outString( ">>> Creature Addon Data loaded" );
1014 sLog.outString();
1016 sLog.outString( "Loading Creature Respawn Data..." ); // must be after PackInstances()
1017 sObjectMgr.LoadCreatureRespawnTimes();
1019 sLog.outString( "Loading Gameobject Data..." );
1020 sObjectMgr.LoadGameobjects();
1022 sLog.outString( "Loading Gameobject Respawn Data..." ); // must be after PackInstances()
1023 sObjectMgr.LoadGameobjectRespawnTimes();
1025 sLog.outString( "Loading Objects Pooling Data...");
1026 sPoolMgr.LoadFromDB();
1028 sLog.outString( "Loading Game Event Data...");
1029 sLog.outString();
1030 sGameEventMgr.LoadFromDB();
1031 sLog.outString( ">>> Game Event Data loaded" );
1032 sLog.outString();
1034 sLog.outString( "Loading Weather Data..." );
1035 sObjectMgr.LoadWeatherZoneChances();
1037 sLog.outString( "Loading Quests..." );
1038 sObjectMgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
1040 sLog.outString( "Loading Quest POI" );
1041 sObjectMgr.LoadQuestPOI();
1043 sLog.outString( "Loading Quests Relations..." );
1044 sLog.outString();
1045 sObjectMgr.LoadQuestRelations(); // must be after quest load
1046 sLog.outString( ">>> Quests Relations loaded" );
1047 sLog.outString();
1049 sLog.outString( "Loading UNIT_NPC_FLAG_SPELLCLICK Data..." );
1050 sObjectMgr.LoadNPCSpellClickSpells();
1052 sLog.outString( "Loading SpellArea Data..." ); // must be after quest load
1053 sSpellMgr.LoadSpellAreas();
1055 sLog.outString( "Loading AreaTrigger definitions..." );
1056 sObjectMgr.LoadAreaTriggerTeleports(); // must be after item template load
1058 sLog.outString( "Loading Quest Area Triggers..." );
1059 sObjectMgr.LoadQuestAreaTriggers(); // must be after LoadQuests
1061 sLog.outString( "Loading Tavern Area Triggers..." );
1062 sObjectMgr.LoadTavernAreaTriggers();
1064 sLog.outString( "Loading AreaTrigger script names..." );
1065 sObjectMgr.LoadAreaTriggerScripts();
1067 sLog.outString( "Loading Graveyard-zone links...");
1068 sObjectMgr.LoadGraveyardZones();
1070 sLog.outString( "Loading Spell target coordinates..." );
1071 sSpellMgr.LoadSpellTargetPositions();
1073 sLog.outString( "Loading spell pet auras..." );
1074 sSpellMgr.LoadSpellPetAuras();
1076 sLog.outString( "Loading Player Create Info & Level Stats..." );
1077 sLog.outString();
1078 sObjectMgr.LoadPlayerInfo();
1079 sLog.outString( ">>> Player Create Info & Level Stats loaded" );
1080 sLog.outString();
1082 sLog.outString( "Loading Exploration BaseXP Data..." );
1083 sObjectMgr.LoadExplorationBaseXP();
1085 sLog.outString( "Loading Pet Name Parts..." );
1086 sObjectMgr.LoadPetNames();
1088 sLog.outString( "Loading the max pet number..." );
1089 sObjectMgr.LoadPetNumber();
1091 sLog.outString( "Loading pet level stats..." );
1092 sObjectMgr.LoadPetLevelInfo();
1094 sLog.outString( "Loading Player Corpses..." );
1095 sObjectMgr.LoadCorpses();
1097 sLog.outString( "Loading Player level dependent mail rewards..." );
1098 sObjectMgr.LoadMailLevelRewards();
1100 sLog.outString( "Loading Loot Tables..." );
1101 sLog.outString();
1102 LoadLootTables();
1103 sLog.outString( ">>> Loot Tables loaded" );
1104 sLog.outString();
1106 sLog.outString( "Loading Skill Discovery Table..." );
1107 LoadSkillDiscoveryTable();
1109 sLog.outString( "Loading Skill Extra Item Table..." );
1110 LoadSkillExtraItemTable();
1112 sLog.outString( "Loading Skill Fishing base level requirements..." );
1113 sObjectMgr.LoadFishingBaseSkillLevel();
1115 sLog.outString( "Loading Achievements..." );
1116 sLog.outString();
1117 sAchievementMgr.LoadAchievementReferenceList();
1118 sAchievementMgr.LoadAchievementCriteriaList();
1119 sAchievementMgr.LoadAchievementCriteriaRequirements();
1120 sAchievementMgr.LoadRewards();
1121 sAchievementMgr.LoadRewardLocales();
1122 sAchievementMgr.LoadCompletedAchievements();
1123 sLog.outString( ">>> Achievements loaded" );
1124 sLog.outString();
1126 ///- Load dynamic data tables from the database
1127 sLog.outString( "Loading Auctions..." );
1128 sLog.outString();
1129 sAuctionMgr.LoadAuctionItems();
1130 sAuctionMgr.LoadAuctions();
1131 sLog.outString( ">>> Auctions loaded" );
1132 sLog.outString();
1134 sLog.outString( "Loading Guilds..." );
1135 sObjectMgr.LoadGuilds();
1137 sLog.outString( "Loading ArenaTeams..." );
1138 sObjectMgr.LoadArenaTeams();
1140 sLog.outString( "Loading Groups..." );
1141 sObjectMgr.LoadGroups();
1143 sLog.outString( "Loading ReservedNames..." );
1144 sObjectMgr.LoadReservedPlayersNames();
1146 sLog.outString( "Loading GameObjects for quests..." );
1147 sObjectMgr.LoadGameObjectForQuests();
1149 sLog.outString( "Loading BattleMasters..." );
1150 sBattleGroundMgr.LoadBattleMastersEntry();
1152 sLog.outString( "Loading BattleGround event indexes..." );
1153 sBattleGroundMgr.LoadBattleEventIndexes();
1155 sLog.outString( "Loading GameTeleports..." );
1156 sObjectMgr.LoadGameTele();
1158 sLog.outString( "Loading Npc Text Id..." );
1159 sObjectMgr.LoadNpcTextId(); // must be after load Creature and NpcText
1161 sLog.outString( "Loading Gossip scripts..." );
1162 sObjectMgr.LoadGossipScripts(); // must be before gossip menu options
1164 sLog.outString( "Loading Gossip menus..." );
1165 sObjectMgr.LoadGossipMenu();
1167 sLog.outString( "Loading Gossip menu options..." );
1168 sObjectMgr.LoadGossipMenuItems();
1170 sLog.outString( "Loading Vendors..." );
1171 sObjectMgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
1173 sLog.outString( "Loading Trainers..." );
1174 sObjectMgr.LoadTrainerSpell(); // must be after load CreatureTemplate
1176 sLog.outString( "Loading Waypoints..." );
1177 sLog.outString();
1178 sWaypointMgr.Load();
1180 sLog.outString( "Loading GM tickets...");
1181 sTicketMgr.LoadGMTickets();
1183 ///- Handle outdated emails (delete/return)
1184 sLog.outString( "Returning old mails..." );
1185 sObjectMgr.ReturnOrDeleteOldMails(false);
1187 ///- Load and initialize scripts
1188 sLog.outString( "Loading Scripts..." );
1189 sLog.outString();
1190 sObjectMgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
1191 sObjectMgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
1192 sObjectMgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
1193 sObjectMgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
1194 sObjectMgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
1195 sLog.outString( ">>> Scripts loaded" );
1196 sLog.outString();
1198 sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
1199 sObjectMgr.LoadDbScriptStrings();
1201 sLog.outString( "Loading CreatureEventAI Texts...");
1202 sEventAIMgr.LoadCreatureEventAI_Texts(false); // false, will checked in LoadCreatureEventAI_Scripts
1204 sLog.outString( "Loading CreatureEventAI Summons...");
1205 sEventAIMgr.LoadCreatureEventAI_Summons(false); // false, will checked in LoadCreatureEventAI_Scripts
1207 sLog.outString( "Loading CreatureEventAI Scripts...");
1208 sEventAIMgr.LoadCreatureEventAI_Scripts();
1210 sLog.outString( "Initializing Scripts..." );
1211 if(!LoadScriptingModule())
1212 exit(1);
1214 ///- Initialize game time and timers
1215 sLog.outString( "DEBUG:: Initialize game time and timers" );
1216 m_gameTime = time(NULL);
1217 m_startTime=m_gameTime;
1219 tm local;
1220 time_t curr;
1221 time(&curr);
1222 local=*(localtime(&curr)); // dereference and assign
1223 char isoDate[128];
1224 sprintf( isoDate, "%04d-%02d-%02d %02d:%02d:%02d",
1225 local.tm_year+1900, local.tm_mon+1, local.tm_mday, local.tm_hour, local.tm_min, local.tm_sec);
1227 loginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, startstring, uptime) VALUES('%u', " UI64FMTD ", '%s', 0)",
1228 realmID, uint64(m_startTime), isoDate);
1230 m_timers[WUPDATE_OBJECTS].SetInterval(0);
1231 m_timers[WUPDATE_SESSIONS].SetInterval(0);
1232 m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILISECONDS);
1233 m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILISECONDS);
1234 m_timers[WUPDATE_UPTIME].SetInterval(m_configUint32Values[CONFIG_UINT32_UPTIME_UPDATE]*MINUTE*IN_MILISECONDS);
1235 //Update "uptime" table based on configuration entry in minutes.
1236 m_timers[WUPDATE_CORPSES].SetInterval(20*MINUTE*IN_MILISECONDS);
1237 //erase corpses every 20 minutes
1239 //to set mailtimer to return mails every day between 4 and 5 am
1240 //mailtimer is increased when updating auctions
1241 //one second is 1000 -(tested on win system)
1242 mail_timer = uint32((((localtime( &m_gameTime )->tm_hour + 20) % 24)* HOUR * IN_MILISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval() );
1243 //1440
1244 mail_timer_expires = uint32( (DAY * IN_MILISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval()));
1245 sLog.outDebug("Mail timer set to: %u, mail return is called every %u minutes", mail_timer, mail_timer_expires);
1247 ///- Initilize static helper structures
1248 AIRegistry::Initialize();
1249 Player::InitVisibleBits();
1251 ///- Initialize MapManager
1252 sLog.outString( "Starting Map System" );
1253 sMapMgr.Initialize();
1255 ///- Initialize Battlegrounds
1256 sLog.outString( "Starting BattleGround System" );
1257 sBattleGroundMgr.CreateInitialBattleGrounds();
1258 sBattleGroundMgr.InitAutomaticArenaPointDistribution();
1260 //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager
1261 sLog.outString( "Loading Transports..." );
1262 sMapMgr.LoadTransports();
1264 sLog.outString("Deleting expired bans..." );
1265 loginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
1267 sLog.outString("Calculate next daily quest reset time..." );
1268 InitDailyQuestResetTime();
1270 sLog.outString("Starting objects Pooling system..." );
1271 sPoolMgr.Initialize();
1273 sLog.outString("Starting Game Event system..." );
1274 uint32 nextGameEvent = sGameEventMgr.Initialize();
1275 m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); //depend on next event
1277 sLog.outString( "WORLD: World initialized" );
1279 uint32 uStartInterval = getMSTimeDiff(uStartTime, getMSTime());
1280 sLog.outString( "SERVER STARTUP TIME: %i minutes %i seconds", uStartInterval / 60000, (uStartInterval % 60000) / 1000 );
1283 void World::DetectDBCLang()
1285 uint32 m_lang_confid = sConfig.GetIntDefault("DBC.Locale", 255);
1287 if(m_lang_confid != 255 && m_lang_confid >= MAX_LOCALE)
1289 sLog.outError("Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)",MAX_LOCALE);
1290 m_lang_confid = LOCALE_enUS;
1293 ChrRacesEntry const* race = sChrRacesStore.LookupEntry(1);
1295 std::string availableLocalsStr;
1297 int default_locale = MAX_LOCALE;
1298 for (int i = MAX_LOCALE-1; i >= 0; --i)
1300 if ( strlen(race->name[i]) > 0) // check by race names
1302 default_locale = i;
1303 m_availableDbcLocaleMask |= (1 << i);
1304 availableLocalsStr += localeNames[i];
1305 availableLocalsStr += " ";
1309 if( default_locale != m_lang_confid && m_lang_confid < MAX_LOCALE &&
1310 (m_availableDbcLocaleMask & (1 << m_lang_confid)) )
1312 default_locale = m_lang_confid;
1315 if(default_locale >= MAX_LOCALE)
1317 sLog.outError("Unable to determine your DBC Locale! (corrupt DBC?)");
1318 exit(1);
1321 m_defaultDbcLocale = LocaleConstant(default_locale);
1323 sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s",localeNames[m_defaultDbcLocale],availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
1324 sLog.outString();
1327 /// Update the World !
1328 void World::Update(uint32 diff)
1330 ///- Update the different timers
1331 for(int i = 0; i < WUPDATE_COUNT; ++i)
1332 if(m_timers[i].GetCurrent()>=0)
1333 m_timers[i].Update(diff);
1334 else m_timers[i].SetCurrent(0);
1336 ///- Update the game time and check for shutdown time
1337 _UpdateGameTime();
1339 /// Handle daily quests reset time
1340 if(m_gameTime > m_NextDailyQuestReset)
1342 ResetDailyQuests();
1343 m_NextDailyQuestReset += DAY;
1346 /// <ul><li> Handle auctions when the timer has passed
1347 if (m_timers[WUPDATE_AUCTIONS].Passed())
1349 m_timers[WUPDATE_AUCTIONS].Reset();
1351 ///- Update mails (return old mails with item, or delete them)
1352 //(tested... works on win)
1353 if (++mail_timer > mail_timer_expires)
1355 mail_timer = 0;
1356 sObjectMgr.ReturnOrDeleteOldMails(true);
1359 ///- Handle expired auctions
1360 sAuctionMgr.Update();
1363 /// <li> Handle session updates when the timer has passed
1364 if (m_timers[WUPDATE_SESSIONS].Passed())
1366 m_timers[WUPDATE_SESSIONS].Reset();
1368 UpdateSessions(diff);
1371 /// <li> Handle weather updates when the timer has passed
1372 if (m_timers[WUPDATE_WEATHERS].Passed())
1374 m_timers[WUPDATE_WEATHERS].Reset();
1376 ///- Send an update signal to Weather objects
1377 WeatherMap::iterator itr, next;
1378 for (itr = m_weathers.begin(); itr != m_weathers.end(); itr = next)
1380 next = itr;
1381 ++next;
1383 ///- and remove Weather objects for zones with no player
1384 //As interval > WorldTick
1385 if(!itr->second->Update(m_timers[WUPDATE_WEATHERS].GetInterval()))
1387 delete itr->second;
1388 m_weathers.erase(itr);
1392 /// <li> Update uptime table
1393 if (m_timers[WUPDATE_UPTIME].Passed())
1395 uint32 tmpDiff = uint32(m_gameTime - m_startTime);
1396 uint32 maxClientsNum = GetMaxActiveSessionCount();
1398 m_timers[WUPDATE_UPTIME].Reset();
1399 loginDatabase.PExecute("UPDATE uptime SET uptime = %u, maxplayers = %u WHERE realmid = %u AND starttime = " UI64FMTD, tmpDiff, maxClientsNum, realmID, uint64(m_startTime));
1402 /// <li> Handle all other objects
1403 if (m_timers[WUPDATE_OBJECTS].Passed())
1405 m_timers[WUPDATE_OBJECTS].Reset();
1406 ///- Update objects when the timer has passed (maps, transport, creatures,...)
1407 sMapMgr.Update(diff); // As interval = 0
1409 sBattleGroundMgr.Update(diff);
1412 // execute callbacks from sql queries that were queued recently
1413 UpdateResultQueue();
1415 ///- Erase corpses once every 20 minutes
1416 if (m_timers[WUPDATE_CORPSES].Passed())
1418 m_timers[WUPDATE_CORPSES].Reset();
1420 CorpsesErase();
1423 ///- Process Game events when necessary
1424 if (m_timers[WUPDATE_EVENTS].Passed())
1426 m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
1427 uint32 nextGameEvent = sGameEventMgr.Update();
1428 m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
1429 m_timers[WUPDATE_EVENTS].Reset();
1432 /// </ul>
1433 ///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"
1434 sMapMgr.RemoveAllObjectsInRemoveList();
1436 // update the instance reset times
1437 sInstanceSaveMgr.Update();
1439 // And last, but not least handle the issued cli commands
1440 ProcessCliCommands();
1443 /// Send a packet to all players (except self if mentioned)
1444 void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team)
1446 SessionMap::const_iterator itr;
1447 for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1449 if (itr->second &&
1450 itr->second->GetPlayer() &&
1451 itr->second->GetPlayer()->IsInWorld() &&
1452 itr->second != self &&
1453 (team == 0 || itr->second->GetPlayer()->GetTeam() == team) )
1455 itr->second->SendPacket(packet);
1460 namespace MaNGOS
1462 class WorldWorldTextBuilder
1464 public:
1465 typedef std::vector<WorldPacket*> WorldPacketList;
1466 explicit WorldWorldTextBuilder(int32 textId, va_list* args = NULL) : i_textId(textId), i_args(args) {}
1467 void operator()(WorldPacketList& data_list, int32 loc_idx)
1469 char const* text = sObjectMgr.GetMangosString(i_textId,loc_idx);
1471 if(i_args)
1473 // we need copy va_list before use or original va_list will corrupted
1474 va_list ap;
1475 va_copy(ap,*i_args);
1477 char str [2048];
1478 vsnprintf(str,2048,text, ap );
1479 va_end(ap);
1481 do_helper(data_list,&str[0]);
1483 else
1484 do_helper(data_list,(char*)text);
1486 private:
1487 char* lineFromMessage(char*& pos) { char* start = strtok(pos,"\n"); pos = NULL; return start; }
1488 void do_helper(WorldPacketList& data_list, char* text)
1490 char* pos = text;
1492 while(char* line = lineFromMessage(pos))
1494 WorldPacket* data = new WorldPacket();
1496 uint32 lineLength = (line ? strlen(line) : 0) + 1;
1498 data->Initialize(SMSG_MESSAGECHAT, 100); // guess size
1499 *data << uint8(CHAT_MSG_SYSTEM);
1500 *data << uint32(LANG_UNIVERSAL);
1501 *data << uint64(0);
1502 *data << uint32(0); // can be chat msg group or something
1503 *data << uint64(0);
1504 *data << uint32(lineLength);
1505 *data << line;
1506 *data << uint8(0);
1508 data_list.push_back(data);
1512 int32 i_textId;
1513 va_list* i_args;
1515 } // namespace MaNGOS
1517 /// Send a System Message to all players (except self if mentioned)
1518 void World::SendWorldText(int32 string_id, ...)
1520 va_list ap;
1521 va_start(ap, string_id);
1523 MaNGOS::WorldWorldTextBuilder wt_builder(string_id, &ap);
1524 MaNGOS::LocalizedPacketListDo<MaNGOS::WorldWorldTextBuilder> wt_do(wt_builder);
1525 for(SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1527 if(!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld() )
1528 continue;
1530 wt_do(itr->second->GetPlayer());
1533 va_end(ap);
1536 /// DEPRICATED, only for debug purpose. Send a System Message to all players (except self if mentioned)
1537 void World::SendGlobalText(const char* text, WorldSession *self)
1539 WorldPacket data;
1541 // need copy to prevent corruption by strtok call in LineFromMessage original string
1542 char* buf = mangos_strdup(text);
1543 char* pos = buf;
1545 while(char* line = ChatHandler::LineFromMessage(pos))
1547 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
1548 SendGlobalMessage(&data, self);
1551 delete [] buf;
1554 /// Send a packet to all players (or players selected team) in the zone (except self if mentioned)
1555 void World::SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self, uint32 team)
1557 SessionMap::const_iterator itr;
1558 for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1560 if (itr->second &&
1561 itr->second->GetPlayer() &&
1562 itr->second->GetPlayer()->IsInWorld() &&
1563 itr->second->GetPlayer()->GetZoneId() == zone &&
1564 itr->second != self &&
1565 (team == 0 || itr->second->GetPlayer()->GetTeam() == team) )
1567 itr->second->SendPacket(packet);
1572 /// Send a System Message to all players in the zone (except self if mentioned)
1573 void World::SendZoneText(uint32 zone, const char* text, WorldSession *self, uint32 team)
1575 WorldPacket data;
1576 ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, text, NULL);
1577 SendZoneMessage(zone, &data, self,team);
1580 /// Kick (and save) all players
1581 void World::KickAll()
1583 m_QueuedPlayer.clear(); // prevent send queue update packet and login queued sessions
1585 // session not removed at kick and will removed in next update tick
1586 for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1587 itr->second->KickPlayer();
1590 /// Kick (and save) all players with security level less `sec`
1591 void World::KickAllLess(AccountTypes sec)
1593 // session not removed at kick and will removed in next update tick
1594 for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1595 if(itr->second->GetSecurity() < sec)
1596 itr->second->KickPlayer();
1599 /// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
1600 BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author)
1602 loginDatabase.escape_string(nameOrIP);
1603 loginDatabase.escape_string(reason);
1604 std::string safe_author=author;
1605 loginDatabase.escape_string(safe_author);
1607 uint32 duration_secs = TimeStringToSecs(duration);
1608 QueryResult *resultAccounts = NULL; //used for kicking
1610 ///- Update the database with ban information
1611 switch(mode)
1613 case BAN_IP:
1614 //No SQL injection as strings are escaped
1615 resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str());
1616 loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str());
1617 break;
1618 case BAN_ACCOUNT:
1619 //No SQL injection as string is escaped
1620 resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str());
1621 break;
1622 case BAN_CHARACTER:
1623 //No SQL injection as string is escaped
1624 resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str());
1625 break;
1626 default:
1627 return BAN_SYNTAX_ERROR;
1630 if(!resultAccounts)
1632 if(mode==BAN_IP)
1633 return BAN_SUCCESS; // ip correctly banned but nobody affected (yet)
1634 else
1635 return BAN_NOTFOUND; // Nobody to ban
1638 ///- Disconnect all affected players (for IP it can be several)
1641 Field* fieldsAccount = resultAccounts->Fetch();
1642 uint32 account = fieldsAccount->GetUInt32();
1644 if(mode!=BAN_IP)
1646 //No SQL injection as strings are escaped
1647 loginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
1648 account,duration_secs,safe_author.c_str(),reason.c_str());
1651 if (WorldSession* sess = FindSession(account))
1652 if(std::string(sess->GetPlayerName()) != author)
1653 sess->KickPlayer();
1655 while( resultAccounts->NextRow() );
1657 delete resultAccounts;
1658 return BAN_SUCCESS;
1661 /// Remove a ban from an account or IP address
1662 bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
1664 if (mode == BAN_IP)
1666 loginDatabase.escape_string(nameOrIP);
1667 loginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP.c_str());
1669 else
1671 uint32 account = 0;
1672 if (mode == BAN_ACCOUNT)
1673 account = sAccountMgr.GetId (nameOrIP);
1674 else if (mode == BAN_CHARACTER)
1675 account = sObjectMgr.GetPlayerAccountIdByPlayerName (nameOrIP);
1677 if (!account)
1678 return false;
1680 //NO SQL injection as account is uint32
1681 loginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account);
1683 return true;
1686 /// Update the game time
1687 void World::_UpdateGameTime()
1689 ///- update the time
1690 time_t thisTime = time(NULL);
1691 uint32 elapsed = uint32(thisTime - m_gameTime);
1692 m_gameTime = thisTime;
1694 ///- if there is a shutdown timer
1695 if(!m_stopEvent && m_ShutdownTimer > 0 && elapsed > 0)
1697 ///- ... and it is overdue, stop the world (set m_stopEvent)
1698 if( m_ShutdownTimer <= elapsed )
1700 if(!(m_ShutdownMask & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0)
1701 m_stopEvent = true; // exist code already set
1702 else
1703 m_ShutdownTimer = 1; // minimum timer value to wait idle state
1705 ///- ... else decrease it and if necessary display a shutdown countdown to the users
1706 else
1708 m_ShutdownTimer -= elapsed;
1710 ShutdownMsg();
1715 /// Shutdown the server
1716 void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
1718 // ignore if server shutdown at next tick
1719 if(m_stopEvent)
1720 return;
1722 m_ShutdownMask = options;
1723 m_ExitCode = exitcode;
1725 ///- If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions)
1726 if(time==0)
1728 if(!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount()==0)
1729 m_stopEvent = true; // exist code already set
1730 else
1731 m_ShutdownTimer = 1; //So that the session count is re-evaluated at next world tick
1733 ///- Else set the shutdown timer and warn users
1734 else
1736 m_ShutdownTimer = time;
1737 ShutdownMsg(true);
1741 /// Display a shutdown message to the user(s)
1742 void World::ShutdownMsg(bool show, Player* player)
1744 // not show messages for idle shutdown mode
1745 if(m_ShutdownMask & SHUTDOWN_MASK_IDLE)
1746 return;
1748 ///- Display a message every 12 hours, hours, 5 minutes, minute, 5 seconds and finally seconds
1749 if ( show ||
1750 (m_ShutdownTimer < 10) ||
1751 // < 30 sec; every 5 sec
1752 (m_ShutdownTimer<30 && (m_ShutdownTimer % 5 )==0) ||
1753 // < 5 min ; every 1 min
1754 (m_ShutdownTimer<5*MINUTE && (m_ShutdownTimer % MINUTE )==0) ||
1755 // < 30 min ; every 5 min
1756 (m_ShutdownTimer<30*MINUTE && (m_ShutdownTimer % (5*MINUTE))==0) ||
1757 // < 12 h ; every 1 h
1758 (m_ShutdownTimer<12*HOUR && (m_ShutdownTimer % HOUR )==0) ||
1759 // > 12 h ; every 12 h
1760 (m_ShutdownTimer>12*HOUR && (m_ShutdownTimer % (12*HOUR) )==0))
1762 std::string str = secsToTimeString(m_ShutdownTimer);
1764 ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME;
1766 SendServerMessage(msgid,str.c_str(),player);
1767 DEBUG_LOG("Server is %s in %s",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"),str.c_str());
1771 /// Cancel a planned server shutdown
1772 void World::ShutdownCancel()
1774 // nothing cancel or too later
1775 if(!m_ShutdownTimer || m_stopEvent)
1776 return;
1778 ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_CANCELLED : SERVER_MSG_SHUTDOWN_CANCELLED;
1780 m_ShutdownMask = 0;
1781 m_ShutdownTimer = 0;
1782 m_ExitCode = SHUTDOWN_EXIT_CODE; // to default value
1783 SendServerMessage(msgid);
1785 DEBUG_LOG("Server %s cancelled.",(m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"));
1788 /// Send a server message to the user(s)
1789 void World::SendServerMessage(ServerMessageType type, const char *text, Player* player)
1791 WorldPacket data(SMSG_SERVER_MESSAGE, 50); // guess size
1792 data << uint32(type);
1793 if(type <= SERVER_MSG_STRING)
1794 data << text;
1796 if(player)
1797 player->GetSession()->SendPacket(&data);
1798 else
1799 SendGlobalMessage( &data );
1802 void World::UpdateSessions( uint32 diff )
1804 ///- Add new sessions
1805 WorldSession* sess;
1806 while(addSessQueue.next(sess))
1807 AddSession_ (sess);
1809 ///- Then send an update signal to remaining ones
1810 for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
1812 next = itr;
1813 ++next;
1814 ///- and remove not active sessions from the list
1815 if(!itr->second->Update(diff)) // As interval = 0
1817 RemoveQueuedPlayer (itr->second);
1818 delete itr->second;
1819 m_sessions.erase(itr);
1824 // This handles the issued and queued CLI/RA commands
1825 void World::ProcessCliCommands()
1827 CliCommandHolder::Print* zprint = NULL;
1828 void* callbackArg = NULL;
1829 CliCommandHolder* command;
1830 while (cliCmdQueue.next(command))
1832 sLog.outDebug("CLI command under processing...");
1833 zprint = command->m_print;
1834 callbackArg = command->m_callbackArg;
1835 CliHandler handler(command->m_cliAccountId, command->m_cliAccessLevel, callbackArg, zprint);
1836 handler.ParseCommands(command->m_command);
1838 if(command->m_commandFinished)
1839 command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage());
1841 delete command;
1845 void World::InitResultQueue()
1847 m_resultQueue = new SqlResultQueue;
1848 CharacterDatabase.SetResultQueue(m_resultQueue);
1851 void World::UpdateResultQueue()
1853 m_resultQueue->Update();
1856 void World::UpdateRealmCharCount(uint32 accountId)
1858 CharacterDatabase.AsyncPQuery(this, &World::_UpdateRealmCharCount, accountId,
1859 "SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId);
1862 void World::_UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId)
1864 if (resultCharCount)
1866 Field *fields = resultCharCount->Fetch();
1867 uint32 charCount = fields[0].GetUInt32();
1868 delete resultCharCount;
1869 loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID);
1870 loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID);
1874 void World::InitDailyQuestResetTime()
1876 time_t mostRecentQuestTime;
1878 QueryResult* result = CharacterDatabase.Query("SELECT MAX(time) FROM character_queststatus_daily");
1879 if(result)
1881 Field *fields = result->Fetch();
1883 mostRecentQuestTime = (time_t)fields[0].GetUInt64();
1884 delete result;
1886 else
1887 mostRecentQuestTime = 0;
1889 // client built-in time for reset is 6:00 AM
1890 // FIX ME: client not show day start time
1891 time_t curTime = time(NULL);
1892 tm localTm = *localtime(&curTime);
1893 localTm.tm_hour = 6;
1894 localTm.tm_min = 0;
1895 localTm.tm_sec = 0;
1897 // current day reset time
1898 time_t curDayResetTime = mktime(&localTm);
1900 // last reset time before current moment
1901 time_t resetTime = (curTime < curDayResetTime) ? curDayResetTime - DAY : curDayResetTime;
1903 // need reset (if we have quest time before last reset time (not processed by some reason)
1904 if(mostRecentQuestTime && mostRecentQuestTime <= resetTime)
1905 m_NextDailyQuestReset = mostRecentQuestTime;
1906 else
1908 // plan next reset time
1909 m_NextDailyQuestReset = (curTime >= curDayResetTime) ? curDayResetTime + DAY : curDayResetTime;
1913 void World::ResetDailyQuests()
1915 sLog.outDetail("Daily quests reset for all characters.");
1916 CharacterDatabase.Execute("DELETE FROM character_queststatus_daily");
1917 for(SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1918 if(itr->second->GetPlayer())
1919 itr->second->GetPlayer()->ResetDailyQuestStatus();
1922 void World::SetPlayerLimit( int32 limit, bool needUpdate )
1924 if(limit < -SEC_ADMINISTRATOR)
1925 limit = -SEC_ADMINISTRATOR;
1927 // lock update need
1928 bool db_update_need = needUpdate || (limit < 0) != (m_playerLimit < 0) || (limit < 0 && m_playerLimit < 0 && limit != m_playerLimit);
1930 m_playerLimit = limit;
1932 if(db_update_need)
1933 loginDatabase.PExecute("UPDATE realmlist SET allowedSecurityLevel = '%u' WHERE id = '%d'",uint8(GetPlayerSecurityLimit()),realmID);
1936 void World::UpdateMaxSessionCounters()
1938 m_maxActiveSessionCount = std::max(m_maxActiveSessionCount,uint32(m_sessions.size()-m_QueuedPlayer.size()));
1939 m_maxQueuedSessionCount = std::max(m_maxQueuedSessionCount,uint32(m_QueuedPlayer.size()));
1942 void World::LoadDBVersion()
1944 QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version, cache_id FROM db_version LIMIT 1");
1945 if(result)
1947 Field* fields = result->Fetch();
1949 m_DBVersion = fields[0].GetCppString();
1950 m_CreatureEventAIVersion = fields[1].GetCppString();
1952 // will be overwrite by config values if different and non-0
1953 setConfig(CONFIG_UINT32_CLIENTCACHE_VERSION, fields[2].GetUInt32());
1954 delete result;
1957 if(m_DBVersion.empty())
1958 m_DBVersion = "Unknown world database.";
1960 if(m_CreatureEventAIVersion.empty())
1961 m_CreatureEventAIVersion = "Unknown creature EventAI.";
1964 void World::setConfig(eConfigUint32Values index, char const* fieldname, uint32 defvalue)
1966 setConfig(index, sConfig.GetIntDefault(fieldname,defvalue));
1969 void World::setConfig(eConfigInt32Values index, char const* fieldname, int32 defvalue)
1971 setConfig(index, sConfig.GetIntDefault(fieldname,defvalue));
1974 void World::setConfig(eConfigFLoatValues index, char const* fieldname, float defvalue)
1976 setConfig(index, sConfig.GetFloatDefault(fieldname,defvalue));
1979 void World::setConfig( eConfigBoolValues index, char const* fieldname, bool defvalue )
1981 setConfig(index, sConfig.GetBoolDefault(fieldname,defvalue));
1984 void World::setConfigPos(eConfigUint32Values index, char const* fieldname, uint32 defvalue)
1986 setConfig(index, fieldname, defvalue);
1987 if (int32(getConfig(index)) < 0)
1989 sLog.outError("%s (%i) can't be negative. Using %u instead.", fieldname, int32(getConfig(index)), defvalue);
1990 setConfig(index, defvalue);
1994 void World::setConfigPos(eConfigFLoatValues index, char const* fieldname, float defvalue)
1996 setConfig(index, fieldname, defvalue);
1997 if (getConfig(index) < 0.0f)
1999 sLog.outError("%s (%f) can't be negative. Using %f instead.", fieldname, getConfig(index), defvalue);
2000 setConfig(index, defvalue);
2004 void World::setConfigMin(eConfigUint32Values index, char const* fieldname, uint32 defvalue, uint32 minvalue)
2006 setConfig(index, fieldname, defvalue);
2007 if (getConfig(index) < minvalue)
2009 sLog.outError("%s (%u) must be >= %u. Using %u instead.", fieldname, getConfig(index), minvalue, minvalue);
2010 setConfig(index, minvalue);
2014 void World::setConfigMin(eConfigInt32Values index, char const* fieldname, int32 defvalue, int32 minvalue)
2016 setConfig(index, fieldname, defvalue);
2017 if (getConfig(index) < minvalue)
2019 sLog.outError("%s (%i) must be >= %i. Using %i instead.", fieldname, getConfig(index), minvalue, minvalue);
2020 setConfig(index, minvalue);
2024 void World::setConfigMin(eConfigFLoatValues index, char const* fieldname, float defvalue, float minvalue)
2026 setConfig(index, fieldname, defvalue);
2027 if (getConfig(index) < minvalue)
2029 sLog.outError("%s (%f) must be >= %f. Using %f instead.", fieldname, getConfig(index), minvalue, minvalue);
2030 setConfig(index, minvalue);
2034 void World::setConfigMinMax(eConfigUint32Values index, char const* fieldname, uint32 defvalue, uint32 minvalue, uint32 maxvalue)
2036 setConfig(index, fieldname, defvalue);
2037 if (getConfig(index) < minvalue)
2039 sLog.outError("%s (%u) must be in range %u...%u. Using %u instead.", fieldname, getConfig(index), minvalue, maxvalue, minvalue);
2040 setConfig(index, minvalue);
2042 else if (getConfig(index) > maxvalue)
2044 sLog.outError("%s (%u) must be in range %u...%u. Using %u instead.", fieldname, getConfig(index), minvalue, maxvalue, maxvalue);
2045 setConfig(index, maxvalue);
2049 void World::setConfigMinMax(eConfigInt32Values index, char const* fieldname, int32 defvalue, int32 minvalue, int32 maxvalue)
2051 setConfig(index, fieldname, defvalue);
2052 if (getConfig(index) < minvalue)
2054 sLog.outError("%s (%i) must be in range %i...%i. Using %i instead.", fieldname, getConfig(index), minvalue, maxvalue, minvalue);
2055 setConfig(index, minvalue);
2057 else if (getConfig(index) > maxvalue)
2059 sLog.outError("%s (%i) must be in range %i...%i. Using %i instead.", fieldname, getConfig(index), minvalue, maxvalue, maxvalue);
2060 setConfig(index, maxvalue);
2064 void World::setConfigMinMax(eConfigFLoatValues index, char const* fieldname, float defvalue, float minvalue, float maxvalue)
2066 setConfig(index, fieldname, defvalue);
2067 if (getConfig(index) < minvalue)
2069 sLog.outError("%s (%f) must be in range %f...%f. Using %f instead.", fieldname, getConfig(index), minvalue, maxvalue, minvalue);
2070 setConfig(index, minvalue);
2072 else if (getConfig(index) > maxvalue)
2074 sLog.outError("%s (%f) must be in range %f...%f. Using %f instead.", fieldname, getConfig(index), minvalue, maxvalue, maxvalue);
2075 setConfig(index, maxvalue);
2079 bool World::configNoReload(bool reload, eConfigUint32Values index, char const* fieldname, uint32 defvalue)
2081 if (!reload)
2082 return true;
2084 uint32 val = sConfig.GetIntDefault(fieldname, defvalue);
2085 if (val != getConfig(index))
2086 sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%u).", fieldname, getConfig(index));
2088 return false;
2091 bool World::configNoReload(bool reload, eConfigInt32Values index, char const* fieldname, int32 defvalue)
2093 if (!reload)
2094 return true;
2096 int32 val = sConfig.GetIntDefault(fieldname, defvalue);
2097 if (val != getConfig(index))
2098 sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%i).", fieldname, getConfig(index));
2100 return false;
2103 bool World::configNoReload(bool reload, eConfigFLoatValues index, char const* fieldname, float defvalue)
2105 if (!reload)
2106 return true;
2108 float val = sConfig.GetFloatDefault(fieldname, defvalue);
2109 if (val != getConfig(index))
2110 sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%f).", fieldname, getConfig(index));
2112 return false;
2115 bool World::configNoReload(bool reload, eConfigBoolValues index, char const* fieldname, bool defvalue)
2117 if (!reload)
2118 return true;
2120 bool val = sConfig.GetBoolDefault(fieldname, defvalue);
2121 if (val != getConfig(index))
2122 sLog.outError("%s option can't be changed at mangosd.conf reload, using current value (%s).", fieldname, getConfig(index) ? "'true'" : "'false'");
2124 return false;