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
24 #include "Database/DatabaseEnv.h"
25 #include "Config/ConfigEnv.h"
26 #include "SystemConfig.h"
29 #include "WorldSession.h"
30 #include "WorldPacket.h"
34 #include "SkillExtraItems.h"
35 #include "SkillDiscovery.h"
37 #include "AccountMgr.h"
38 #include "AchievementMgr.h"
39 #include "AuctionHouseMgr.h"
40 #include "ObjectMgr.h"
41 #include "CreatureEventAIMgr.h"
44 #include "DBCStores.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"
60 #include "InstanceSaveMgr.h"
61 #include "WaypointManager.h"
62 #include "GMTicketMgr.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;
84 m_allowMovement
= true;
87 m_gameTime
=time(NULL
);
88 m_startTime
=m_gameTime
;
89 m_maxActiveSessionCount
= 0;
90 m_maxQueuedSessionCount
= 0;
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;
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
)
128 CliCommandHolder
* command
;
129 while (cliCmdQueue
.next(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
)
148 Player
*player
= itr
->second
->GetPlayer();
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.
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
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())
181 itr
->second
->KickPlayer();
187 void World::AddSession(WorldSession
* s
)
193 World::AddSession_ (WorldSession
* 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 ()))
204 delete s
; // session not added yet in session list, so not listed in queue
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
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
237 if (pLimit
> 0 && Sessions
>= pLimit
&& s
->GetSecurity () == SEC_PLAYER
)
240 UpdateMaxSessionCounters ();
241 sLog
.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s
->GetAccountId (), ++QueueSize
);
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
);
255 WorldPacket
pkt(SMSG_CLIENTCACHE_VERSION
, 4);
256 pkt
<< uint32(getConfig(CONFIG_UINT32_CLIENTCACHE_VERSION
));
259 s
->SendTutorialsData();
261 UpdateMaxSessionCounters ();
263 // Updates the population
266 float popu
= float(GetActiveSessionCount()); // updated number of users on the server
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
)
278 for(Queue::const_iterator iter
= m_QueuedPlayer
.begin(); iter
!= m_QueuedPlayer
.end(); ++iter
, ++position
)
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();
308 Queue::iterator iter
= m_QueuedPlayer
.begin();
310 // search to remove and count skipped positions
313 for(;iter
!= m_QueuedPlayer
.end(); ++iter
, ++position
)
317 sess
->SetInQueue(false);
318 iter
= m_QueuedPlayer
.erase(iter
);
319 found
= true; // removing queued session
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
)
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();
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
);
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())
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())
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
394 Weather
* w
= new Weather(zone_id
,weatherChances
);
395 m_weathers
[w
->GetZone()] = w
;
401 /// Initialize config values
402 void World::LoadConfigSettings(bool reload
)
406 if(!sConfig
.Reload())
408 sLog
.outError("World settings reload fail: can't read settings from %s.",sConfig
.GetFilename().c_str());
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);
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())
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())
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
);
524 sMapMgr
.SetGridCleanUpDelay(getConfig(CONFIG_UINT32_INTERVAL_GRIDCLEAN
));
526 setConfigMin(CONFIG_UINT32_INTERVAL_MAPUPDATE
, "MapUpdateInterval", 100, MIN_MAP_UPDATE_DELAY
);
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);
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);
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
);
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("/");
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());
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());
883 ///- Loading strings. Getting no records means core load has to be canceled because no error message can be output.
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
);
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();
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" );
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..." );
1012 sObjectMgr
.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
1013 sLog
.outString( ">>> Creature Addon Data loaded" );
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...");
1030 sGameEventMgr
.LoadFromDB();
1031 sLog
.outString( ">>> Game Event Data loaded" );
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..." );
1045 sObjectMgr
.LoadQuestRelations(); // must be after quest load
1046 sLog
.outString( ">>> Quests Relations loaded" );
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..." );
1078 sObjectMgr
.LoadPlayerInfo();
1079 sLog
.outString( ">>> Player Create Info & Level Stats loaded" );
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..." );
1103 sLog
.outString( ">>> Loot Tables loaded" );
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..." );
1117 sAchievementMgr
.LoadAchievementReferenceList();
1118 sAchievementMgr
.LoadAchievementCriteriaList();
1119 sAchievementMgr
.LoadAchievementCriteriaRequirements();
1120 sAchievementMgr
.LoadRewards();
1121 sAchievementMgr
.LoadRewardLocales();
1122 sAchievementMgr
.LoadCompletedAchievements();
1123 sLog
.outString( ">>> Achievements loaded" );
1126 ///- Load dynamic data tables from the database
1127 sLog
.outString( "Loading Auctions..." );
1129 sAuctionMgr
.LoadAuctionItems();
1130 sAuctionMgr
.LoadAuctions();
1131 sLog
.outString( ">>> Auctions loaded" );
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..." );
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..." );
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" );
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())
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
;
1222 local
=*(localtime(&curr
)); // dereference and assign
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() );
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
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?)");
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());
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
1339 /// Handle daily quests reset time
1340 if(m_gameTime
> m_NextDailyQuestReset
)
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
)
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
)
1383 ///- and remove Weather objects for zones with no player
1384 //As interval > WorldTick
1385 if(!itr
->second
->Update(m_timers
[WUPDATE_WEATHERS
].GetInterval()))
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();
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();
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
)
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
);
1462 class WorldWorldTextBuilder
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
);
1473 // we need copy va_list before use or original va_list will corrupted
1475 va_copy(ap
,*i_args
);
1478 vsnprintf(str
,2048,text
, ap
);
1481 do_helper(data_list
,&str
[0]);
1484 do_helper(data_list
,(char*)text
);
1487 char* lineFromMessage(char*& pos
) { char* start
= strtok(pos
,"\n"); pos
= NULL
; return start
; }
1488 void do_helper(WorldPacketList
& data_list
, char* 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
);
1502 *data
<< uint32(0); // can be chat msg group or something
1504 *data
<< uint32(lineLength
);
1508 data_list
.push_back(data
);
1515 } // namespace MaNGOS
1517 /// Send a System Message to all players (except self if mentioned)
1518 void World::SendWorldText(int32 string_id
, ...)
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() )
1530 wt_do(itr
->second
->GetPlayer());
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
)
1541 // need copy to prevent corruption by strtok call in LineFromMessage original string
1542 char* buf
= mangos_strdup(text
);
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
);
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
)
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
)
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
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());
1619 //No SQL injection as string is escaped
1620 resultAccounts
= loginDatabase
.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP
.c_str());
1623 //No SQL injection as string is escaped
1624 resultAccounts
= CharacterDatabase
.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP
.c_str());
1627 return BAN_SYNTAX_ERROR
;
1633 return BAN_SUCCESS
; // ip correctly banned but nobody affected (yet)
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();
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
)
1655 while( resultAccounts
->NextRow() );
1657 delete resultAccounts
;
1661 /// Remove a ban from an account or IP address
1662 bool World::RemoveBanAccount(BanMode mode
, std::string nameOrIP
)
1666 loginDatabase
.escape_string(nameOrIP
);
1667 loginDatabase
.PExecute("DELETE FROM ip_banned WHERE ip = '%s'",nameOrIP
.c_str());
1672 if (mode
== BAN_ACCOUNT
)
1673 account
= sAccountMgr
.GetId (nameOrIP
);
1674 else if (mode
== BAN_CHARACTER
)
1675 account
= sObjectMgr
.GetPlayerAccountIdByPlayerName (nameOrIP
);
1680 //NO SQL injection as account is uint32
1681 loginDatabase
.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'",account
);
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
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
1708 m_ShutdownTimer
-= elapsed
;
1715 /// Shutdown the server
1716 void World::ShutdownServ(uint32 time
, uint32 options
, uint8 exitcode
)
1718 // ignore if server shutdown at next tick
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)
1728 if(!(options
& SHUTDOWN_MASK_IDLE
) || GetActiveAndQueuedSessionCount()==0)
1729 m_stopEvent
= true; // exist code already set
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
1736 m_ShutdownTimer
= time
;
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
)
1748 ///- Display a message every 12 hours, hours, 5 minutes, minute, 5 seconds and finally seconds
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
)
1778 ServerMessageType msgid
= (m_ShutdownMask
& SHUTDOWN_MASK_RESTART
) ? SERVER_MSG_RESTART_CANCELLED
: SERVER_MSG_SHUTDOWN_CANCELLED
;
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
)
1797 player
->GetSession()->SendPacket(&data
);
1799 SendGlobalMessage( &data
);
1802 void World::UpdateSessions( uint32 diff
)
1804 ///- Add new sessions
1806 while(addSessQueue
.next(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
)
1814 ///- and remove not active sessions from the list
1815 if(!itr
->second
->Update(diff
)) // As interval = 0
1817 RemoveQueuedPlayer (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());
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");
1881 Field
*fields
= result
->Fetch();
1883 mostRecentQuestTime
= (time_t)fields
[0].GetUInt64();
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;
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
;
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
;
1928 bool db_update_need
= needUpdate
|| (limit
< 0) != (m_playerLimit
< 0) || (limit
< 0 && m_playerLimit
< 0 && limit
!= m_playerLimit
);
1930 m_playerLimit
= limit
;
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");
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());
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
)
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
));
2091 bool World::configNoReload(bool reload
, eConfigInt32Values index
, char const* fieldname
, int32 defvalue
)
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
));
2103 bool World::configNoReload(bool reload
, eConfigFLoatValues index
, char const* fieldname
, float defvalue
)
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
));
2115 bool World::configNoReload(bool reload
, eConfigBoolValues index
, char const* fieldname
, bool defvalue
)
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'");