2008-10-11 14:16:25 -05:00
/*
2009-02-04 12:42:26 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2010-01-16 20:19:18 +03:00
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
2008-10-11 14:16:25 -05:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2008-11-20 16:16:57 -06:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-11 14:16:25 -05:00
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
2008-11-20 16:16:57 -06:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Database/SQLStorage.h"
2008-11-20 16:16:57 -06:00
#include "Database/SQLStorageImpl.h"
2009-02-13 19:50:20 -06:00
#include "Policies/SingletonImp.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Log.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "UpdateMask.h"
#include "World.h"
#include "Group.h"
#include "Guild.h"
#include "ArenaTeam.h"
#include "Transports.h"
#include "ProgressBar.h"
#include "Language.h"
2009-03-06 19:36:47 -06:00
#include "GameEventMgr.h"
2008-10-11 14:16:25 -05:00
#include "Spell.h"
#include "Chat.h"
2008-10-20 12:59:45 -05:00
#include "AccountMgr.h"
2008-10-11 14:16:25 -05:00
#include "InstanceSaveMgr.h"
#include "SpellAuras.h"
#include "Util.h"
2008-11-22 09:51:35 -06:00
#include "WaypointManager.h"
2008-12-02 18:12:39 -06:00
#include "InstanceData.h" //for condition_instance_data
2009-12-20 13:35:08 +02:00
#include "GossipDef.h"
2010-03-12 18:19:50 +01:00
#include "Vehicle.h"
2010-03-15 04:37:28 +01:00
#include "AchievementMgr.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
INSTANTIATE_SINGLETON_1 ( ObjectMgr );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ScriptMapMap sQuestEndScripts ;
ScriptMapMap sQuestStartScripts ;
ScriptMapMap sSpellScripts ;
ScriptMapMap sGameObjectScripts ;
ScriptMapMap sEventScripts ;
2009-12-20 13:35:08 +02:00
ScriptMapMap sGossipScripts ;
2008-12-10 06:34:35 +02:00
ScriptMapMap sWaypointScripts ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool normalizePlayerName ( std :: string & name )
{
if ( name . empty ())
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
wchar_t wstr_buf [ MAX_INTERNAL_PLAYER_NAME + 1 ];
size_t wstr_len = MAX_INTERNAL_PLAYER_NAME ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! Utf8toWStr ( name , & wstr_buf [ 0 ], wstr_len ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
wstr_buf [ 0 ] = wcharToUpper ( wstr_buf [ 0 ]);
2009-10-17 16:20:24 -07:00
for ( size_t i = 1 ; i < wstr_len ; ++ i )
2008-10-11 14:16:25 -05:00
wstr_buf [ i ] = wcharToLower ( wstr_buf [ i ]);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! WStrToUtf8 ( wstr_buf , wstr_len , name ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
LanguageDesc lang_description [ LANGUAGES_COUNT ] =
{
{ LANG_ADDON , 0 , 0 },
{ LANG_UNIVERSAL , 0 , 0 },
{ LANG_ORCISH , 669 , SKILL_LANG_ORCISH },
{ LANG_DARNASSIAN , 671 , SKILL_LANG_DARNASSIAN },
{ LANG_TAURAHE , 670 , SKILL_LANG_TAURAHE },
{ LANG_DWARVISH , 672 , SKILL_LANG_DWARVEN },
{ LANG_COMMON , 668 , SKILL_LANG_COMMON },
{ LANG_DEMONIC , 815 , SKILL_LANG_DEMON_TONGUE },
{ LANG_TITAN , 816 , SKILL_LANG_TITAN },
{ LANG_THALASSIAN , 813 , SKILL_LANG_THALASSIAN },
{ LANG_DRACONIC , 814 , SKILL_LANG_DRACONIC },
{ LANG_KALIMAG , 817 , SKILL_LANG_OLD_TONGUE },
{ LANG_GNOMISH , 7340 , SKILL_LANG_GNOMISH },
{ LANG_TROLL , 7341 , SKILL_LANG_TROLL },
{ LANG_GUTTERSPEAK , 17737 , SKILL_LANG_GUTTERSPEAK },
{ LANG_DRAENEI , 29932 , SKILL_LANG_DRAENEI },
{ LANG_ZOMBIE , 0 , 0 },
{ LANG_GNOMISH_BINARY , 0 , 0 },
{ LANG_GOBLIN_BINARY , 0 , 0 }
};
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
LanguageDesc const * GetLanguageDescByID ( uint32 lang )
{
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; i < LANGUAGES_COUNT ; ++ i )
2008-10-11 14:16:25 -05:00
{
if ( uint32 ( lang_description [ i ]. lang_id ) == lang )
return & lang_description [ i ];
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
bool SpellClickInfo :: IsFitToRequirements ( Player const * player , Creature const * clickNpc ) const
2009-06-15 23:07:43 -05:00
{
if ( questStart )
{
// not in expected required quest state
2009-09-18 14:10:37 -07:00
if ( ! player || (( ! questStartCanActive || ! player -> IsActiveQuest ( questStart )) && ! player -> GetQuestRewardStatus ( questStart )))
2009-06-15 23:07:43 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
if ( questEnd )
{
// not in expected forbidden quest state
if ( ! player || player -> GetQuestRewardStatus ( questEnd ))
return false ;
}
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
if ( auraRequired )
if ( ! player -> HasAura ( auraRequired ))
return false ;
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
if ( auraForbidden )
if ( player -> HasAura ( auraForbidden ))
return false ;
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
Unit const * summoner = NULL ;
// Check summoners for party
if ( clickNpc -> isSummon ())
summoner = (( TempSummon * ) clickNpc ) -> GetSummoner ();
if ( ! summoner )
summoner = clickNpc ;
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
switch ( userType )
{
case SPELL_CLICK_USER_FRIEND :
if ( ! player -> IsFriendlyTo ( summoner ))
return false ;
break ;
case SPELL_CLICK_USER_RAID :
if ( ! player -> IsInRaidWith ( summoner ))
return false ;
break ;
case SPELL_CLICK_USER_PARTY :
if ( ! player -> IsInPartyWith ( summoner ))
return false ;
break ;
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ObjectMgr :: ObjectMgr ()
{
m_hiCharGuid = 1 ;
m_hiCreatureGuid = 1 ;
m_hiPetGuid = 1 ;
2008-12-24 09:58:26 -06:00
m_hiVehicleGuid = 1 ;
2008-10-11 14:16:25 -05:00
m_hiItemGuid = 1 ;
m_hiGoGuid = 1 ;
m_hiDoGuid = 1 ;
m_hiCorpseGuid = 1 ;
m_hiPetNumber = 1 ;
2008-11-20 16:16:57 -06:00
m_ItemTextId = 1 ;
m_mailid = 1 ;
2009-06-11 00:45:59 -05:00
m_equipmentSetGuid = 1 ;
2008-11-20 16:16:57 -06:00
m_guildId = 1 ;
m_arenaTeamId = 1 ;
2009-02-13 19:50:20 -06:00
m_auctionid = 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Only zero condition left, others will be added while loading DB tables
mConditions . resize ( 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ObjectMgr ::~ ObjectMgr ()
{
2009-10-17 16:20:24 -07:00
for ( QuestMap :: iterator i = mQuestTemplates . begin ( ); i != mQuestTemplates . end ( ); ++ i )
2008-10-11 14:16:25 -05:00
delete i -> second ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( PetLevelInfoMap :: iterator i = petInfo . begin ( ); i != petInfo . end ( ); ++ i )
2008-10-11 14:16:25 -05:00
delete [] i -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// free only if loaded
for ( int class_ = 0 ; class_ < MAX_CLASSES ; ++ class_ )
delete [] playerClassInfo [ class_ ]. levelInfo ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
for ( int race = 0 ; race < MAX_RACES ; ++ race )
for ( int class_ = 0 ; class_ < MAX_CLASSES ; ++ class_ )
delete [] playerInfo [ race ][ class_ ]. levelInfo ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// free group and guild objects
for ( GroupSet :: iterator itr = mGroupSet . begin (); itr != mGroupSet . end (); ++ itr )
delete ( * itr );
2009-10-17 15:51:44 -07:00
2009-02-15 12:14:14 -06:00
for ( GuildMap :: iterator itr = mGuildMap . begin (); itr != mGuildMap . end (); ++ itr )
delete itr -> second ;
2009-10-17 15:51:44 -07:00
2009-08-06 17:45:37 -05:00
for ( ArenaTeamMap :: iterator itr = mArenaTeamMap . begin (); itr != mArenaTeamMap . end (); ++ itr )
delete itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
for ( CacheVendorItemMap :: iterator itr = m_mCacheVendorItemMap . begin (); itr != m_mCacheVendorItemMap . end (); ++ itr )
itr -> second . Clear ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
for ( CacheTrainerSpellMap :: iterator itr = m_mCacheTrainerSpellMap . begin (); itr != m_mCacheTrainerSpellMap . end (); ++ itr )
itr -> second . Clear ();
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Group * ObjectMgr :: GetGroupByLeader ( const uint64 & guid ) const
{
2009-10-17 16:20:24 -07:00
for ( GroupSet :: const_iterator itr = mGroupSet . begin (); itr != mGroupSet . end (); ++ itr )
2008-10-11 14:16:25 -05:00
if (( * itr ) -> GetLeaderGUID () == guid )
return * itr ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-02-15 12:14:14 -06:00
Guild * ObjectMgr :: GetGuildById ( uint32 GuildId ) const
2008-10-11 14:16:25 -05:00
{
2009-02-15 12:14:14 -06:00
GuildMap :: const_iterator itr = mGuildMap . find ( GuildId );
if ( itr != mGuildMap . end ())
return itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
Guild * ObjectMgr :: GetGuildByName ( const std :: string & guildname ) const
2008-10-11 14:16:25 -05:00
{
2009-10-17 16:20:24 -07:00
for ( GuildMap :: const_iterator itr = mGuildMap . begin (); itr != mGuildMap . end (); ++ itr )
2009-02-15 12:14:14 -06:00
if ( itr -> second -> GetName () == guildname )
return itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-02-15 12:14:14 -06:00
std :: string ObjectMgr :: GetGuildNameById ( uint32 GuildId ) const
2008-10-11 14:16:25 -05:00
{
2009-02-15 12:14:14 -06:00
GuildMap :: const_iterator itr = mGuildMap . find ( GuildId );
if ( itr != mGuildMap . end ())
return itr -> second -> GetName ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return "" ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Guild * ObjectMgr :: GetGuildByLeader ( const uint64 & guid ) const
{
2009-10-17 16:20:24 -07:00
for ( GuildMap :: const_iterator itr = mGuildMap . begin (); itr != mGuildMap . end (); ++ itr )
2009-02-15 12:14:14 -06:00
if ( itr -> second -> GetLeader () == guid )
return itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-02-15 12:14:14 -06:00
void ObjectMgr :: AddGuild ( Guild * guild )
{
mGuildMap [ guild -> GetId ()] = guild ;
}
2009-10-17 15:51:44 -07:00
2009-02-15 12:14:14 -06:00
void ObjectMgr :: RemoveGuild ( uint32 Id )
{
mGuildMap . erase ( Id );
}
2009-10-17 15:51:44 -07:00
2009-02-15 12:14:14 -06:00
ArenaTeam * ObjectMgr :: GetArenaTeamById ( uint32 arenateamid ) const
2008-10-11 14:16:25 -05:00
{
2008-12-19 16:05:13 -06:00
ArenaTeamMap :: const_iterator itr = mArenaTeamMap . find ( arenateamid );
if ( itr != mArenaTeamMap . end ())
return itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
ArenaTeam * ObjectMgr :: GetArenaTeamByName ( const std :: string & arenateamname ) const
2008-10-11 14:16:25 -05:00
{
2009-10-17 16:20:24 -07:00
for ( ArenaTeamMap :: const_iterator itr = mArenaTeamMap . begin (); itr != mArenaTeamMap . end (); ++ itr )
2008-12-19 16:05:13 -06:00
if ( itr -> second -> GetName () == arenateamname )
return itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-12-19 16:05:13 -06:00
ArenaTeam * ObjectMgr :: GetArenaTeamByCaptain ( uint64 const & guid ) const
2008-10-11 14:16:25 -05:00
{
2009-10-17 16:20:24 -07:00
for ( ArenaTeamMap :: const_iterator itr = mArenaTeamMap . begin (); itr != mArenaTeamMap . end (); ++ itr )
2008-12-19 16:05:13 -06:00
if ( itr -> second -> GetCaptain () == guid )
return itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-12-19 16:05:13 -06:00
void ObjectMgr :: AddArenaTeam ( ArenaTeam * arenaTeam )
{
mArenaTeamMap [ arenaTeam -> GetId ()] = arenaTeam ;
}
2009-10-17 15:51:44 -07:00
2009-02-15 12:14:14 -06:00
void ObjectMgr :: RemoveArenaTeam ( uint32 Id )
2008-12-19 16:05:13 -06:00
{
2009-02-15 12:14:14 -06:00
mArenaTeamMap . erase ( Id );
2008-12-19 16:05:13 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CreatureInfo const * ObjectMgr :: GetCreatureTemplate ( uint32 id )
{
return sCreatureStorage . LookupEntry < CreatureInfo > ( id );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCreatureLocales ()
{
2008-11-20 16:16:57 -06:00
mCreatureLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,name_loc1,subname_loc1,name_loc2,subname_loc2,name_loc3,subname_loc3,name_loc4,subname_loc4,name_loc5,subname_loc5,name_loc6,subname_loc6,name_loc7,subname_loc7,name_loc8,subname_loc8 FROM locales_creature" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CreatureLocale & data = mCreatureLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
std :: string str = fields [ 1 + 2 * ( i - 1 )]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Name . size () <= idx )
data . Name . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Name [ idx ] = str ;
}
}
str = fields [ 1 + 2 * ( i - 1 ) + 1 ]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . SubName . size () <= idx )
data . SubName . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . SubName [ idx ] = str ;
}
}
}
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu creature locale strings" , ( unsigned long ) mCreatureLocaleMap . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
void ObjectMgr :: LoadNpcOptionLocales ()
{
2009-12-20 13:35:08 +02:00
mGossipMenuItemsLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT menu_id,id,"
2008-11-05 09:22:56 -06:00
"option_text_loc1,box_text_loc1,option_text_loc2,box_text_loc2,"
"option_text_loc3,box_text_loc3,option_text_loc4,box_text_loc4,"
"option_text_loc5,box_text_loc5,option_text_loc6,box_text_loc6,"
"option_text_loc7,box_text_loc7,option_text_loc8,box_text_loc8 "
2009-12-20 13:35:08 +02:00
"FROM locales_gossip_menu_option" );
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-12-20 13:35:08 +02:00
uint16 menuId = fields [ 0 ]. GetUInt16 ();
uint16 id = fields [ 1 ]. GetUInt16 ();
2009-10-17 15:51:44 -07:00
2009-12-20 13:35:08 +02:00
GossipMenuItemsLocale & data = mGossipMenuItemsLocaleMap [ MAKE_PAIR32 ( menuId , id )];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-11-05 09:22:56 -06:00
{
std :: string str = fields [ 1 + 2 * ( i - 1 )]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . OptionText . size () <= idx )
data . OptionText . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
data . OptionText [ idx ] = str ;
}
}
str = fields [ 1 + 2 * ( i - 1 ) + 1 ]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . BoxText . size () <= idx )
data . BoxText . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
data . BoxText [ idx ] = str ;
}
}
}
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-12-20 13:35:08 +02:00
sLog . outString ( ">> Loaded %lu gossip_menu_option locale strings" , ( unsigned long ) mGossipMenuItemsLocaleMap . size () );
2008-11-05 09:22:56 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
void ObjectMgr :: LoadPointOfInterestLocales ()
{
mPointOfInterestLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,icon_name_loc1,icon_name_loc2,icon_name_loc3,icon_name_loc4,icon_name_loc5,icon_name_loc6,icon_name_loc7,icon_name_loc8 FROM locales_points_of_interest" );
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
PointOfInterestLocale & data = mPointOfInterestLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2009-02-17 17:40:03 -06:00
{
std :: string str = fields [ i ]. GetCppString ();
if ( str . empty ())
continue ;
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . IconName . size () <= idx )
data . IconName . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
data . IconName [ idx ] = str ;
}
}
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu points_of_interest locale strings" , ( unsigned long ) mPointOfInterestLocaleMap . size () );
2009-02-17 17:40:03 -06:00
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
struct SQLCreatureLoader : public SQLStorageLoaderBase < SQLCreatureLoader >
{
template < class D >
2009-04-29 00:31:03 -05:00
void convert_from_str ( uint32 /*field_pos*/ , char * src , D & dst )
2008-11-20 16:16:57 -06:00
{
dst = D ( objmgr . GetScriptId ( src ));
}
};
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCreatureTemplates ()
{
2008-11-20 16:16:57 -06:00
SQLCreatureLoader loader ;
loader . Load ( sCreatureStorage );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u creature definitions" , sCreatureStorage . RecordCount );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
std :: set < uint32 > difficultyEntries [ MAX_DIFFICULTY - 1 ]; // already loaded difficulty 1 value in creatures
std :: set < uint32 > hasDifficultyEntries [ MAX_DIFFICULTY - 1 ]; // already loaded creatures with difficulty 1 values
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check data correctness
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sCreatureStorage . MaxEntry ; ++ i )
2008-10-11 14:16:25 -05:00
{
CreatureInfo const * cInfo = sCreatureStorage . LookupEntry < CreatureInfo > ( i );
2009-06-14 10:01:44 -05:00
if ( ! cInfo )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
bool ok = true ; // bool to allow continue outside this loop
for ( uint32 diff = 0 ; diff < MAX_DIFFICULTY - 1 && ok ; ++ diff )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
if ( ! cInfo -> DifficultyEntry [ diff ])
2008-10-11 14:16:25 -05:00
continue ;
2009-12-17 14:06:20 +01:00
ok = false ; // will be set to true at the end of this loop again
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
CreatureInfo const * difficultyInfo = GetCreatureTemplate ( cInfo -> DifficultyEntry [ diff ]);
if ( ! difficultyInfo )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u not exist." ,
i , diff + 1 , cInfo -> DifficultyEntry [ diff ], cInfo -> DifficultyEntry [ diff ]);
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( difficultyEntries [ diff ]. find ( i ) != difficultyEntries [ diff ]. end ())
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u) listed as difficulty %u but have value in `difficulty_entry_1`." , i , diff + 1 );
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
bool ok2 = true ;
for ( uint32 diff2 = 0 ; diff2 < MAX_DIFFICULTY - 1 && ok2 ; ++ diff2 )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
ok2 = false ;
if ( difficultyEntries [ diff2 ]. find ( cInfo -> DifficultyEntry [ diff ]) != difficultyEntries [ diff2 ]. end ())
{
sLog . outErrorDb ( "Creature (Entry: %u) already listed as difficulty %u for another entry." , cInfo -> DifficultyEntry [ diff ], diff2 + 1 );
continue ;
}
if ( hasDifficultyEntries [ diff2 ]. find ( cInfo -> DifficultyEntry [ diff ]) != hasDifficultyEntries [ diff2 ]. end ())
{
sLog . outErrorDb ( "Creature (Entry: %u) have `difficulty_entry_%u`=%u but creature entry %u have difficulty %u entry also." ,
i , diff + 1 , cInfo -> DifficultyEntry [ diff ], cInfo -> DifficultyEntry [ diff ], diff2 + 1 );
continue ;
}
ok2 = true ;
2008-10-11 14:16:25 -05:00
}
2009-12-17 14:06:20 +01:00
if ( ! ok2 )
continue ;
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( cInfo -> unit_class != difficultyInfo -> unit_class )
2009-05-29 21:24:23 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u, class %u) has different `unit_class` in difficulty %u mode (Entry: %u, class %u)." ,
i , cInfo -> unit_class , diff + 1 , cInfo -> DifficultyEntry [ diff ], difficultyInfo -> unit_class );
2009-05-29 21:24:23 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( cInfo -> npcflag != difficultyInfo -> npcflag )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u) has different `npcflag` in difficulty %u mode (Entry: %u)." , i , diff + 1 , cInfo -> DifficultyEntry [ diff ]);
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( cInfo -> trainer_class != difficultyInfo -> trainer_class )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u) has different `trainer_class` in difficulty %u mode (Entry: %u)." , i , diff + 1 , cInfo -> DifficultyEntry [ diff ]);
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( cInfo -> trainer_race != difficultyInfo -> trainer_race )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u) has different `trainer_race` in difficulty %u mode (Entry: %u)." , i , diff + 1 , cInfo -> DifficultyEntry [ diff ]);
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( cInfo -> trainer_type != difficultyInfo -> trainer_type )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u) has different `trainer_type` in difficulty %u mode (Entry: %u)." , i , diff + 1 , cInfo -> DifficultyEntry [ diff ]);
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( cInfo -> trainer_spell != difficultyInfo -> trainer_spell )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Creature (Entry: %u) has different `trainer_spell` in difficulty %u mode (Entry: %u)." , i , diff + 1 , cInfo -> DifficultyEntry [ diff ]);
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( difficultyInfo -> AIName && * difficultyInfo -> AIName )
2009-04-14 18:31:31 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Difficulty %u mode creature (Entry: %u) has `AIName`, but in any case will used difficulty 0 mode creature (Entry: %u) AIName." ,
diff , cInfo -> DifficultyEntry [ diff ], i );
2009-04-14 18:31:31 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( difficultyInfo -> ScriptID )
2009-04-14 18:31:31 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Difficulty %u mode creature (Entry: %u) has `ScriptName`, but in any case will used difficulty 0 mode creature (Entry: %u) ScriptName." ,
diff , cInfo -> DifficultyEntry [ diff ], i );
2009-04-14 18:31:31 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
hasDifficultyEntries [ diff ]. insert ( i );
difficultyEntries [ diff ]. insert ( cInfo -> DifficultyEntry [ diff ]);
ok = true ;
2008-10-11 14:16:25 -05:00
}
2009-12-17 14:06:20 +01:00
if ( ! ok )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
FactionTemplateEntry const * factionTemplate = sFactionTemplateStore . LookupEntry ( cInfo -> faction_A );
2009-06-14 10:01:44 -05:00
if ( ! factionTemplate )
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing faction_A template (%u)" , cInfo -> Entry , cInfo -> faction_A );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
factionTemplate = sFactionTemplateStore . LookupEntry ( cInfo -> faction_H );
2009-06-14 10:01:44 -05:00
if ( ! factionTemplate )
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing faction_H template (%u)" , cInfo -> Entry , cInfo -> faction_H );
2009-10-17 15:51:44 -07:00
2009-06-13 09:40:44 -05:00
// used later for scale
2009-06-15 18:02:12 -05:00
CreatureDisplayInfoEntry const * displayScaleEntry = NULL ;
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
if ( cInfo -> Modelid1 )
2008-10-27 11:48:45 -05:00
{
2009-09-21 07:52:16 +02:00
CreatureDisplayInfoEntry const * displayEntry = sCreatureDisplayInfoStore . LookupEntry ( cInfo -> Modelid1 );
2009-06-15 18:02:12 -05:00
if ( ! displayEntry )
2009-06-13 09:40:44 -05:00
{
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing Modelid1 id (%u), can crash client" , cInfo -> Entry , cInfo -> Modelid1 );
const_cast < CreatureInfo *> ( cInfo ) -> Modelid1 = 0 ;
2009-06-13 09:40:44 -05:00
}
2009-06-15 18:02:12 -05:00
else if ( ! displayScaleEntry )
displayScaleEntry = displayEntry ;
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
CreatureModelInfo const * minfo = sCreatureModelStorage . LookupEntry < CreatureModelInfo > ( cInfo -> Modelid1 );
2009-06-15 18:02:12 -05:00
if ( ! minfo )
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) not has model data for Modelid1 (%u)" , cInfo -> Entry , cInfo -> Modelid1 );
2009-06-15 18:02:12 -05:00
}
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
if ( cInfo -> Modelid2 )
2008-10-27 11:48:45 -05:00
{
2009-09-21 07:52:16 +02:00
CreatureDisplayInfoEntry const * displayEntry = sCreatureDisplayInfoStore . LookupEntry ( cInfo -> Modelid2 );
2009-06-15 18:02:12 -05:00
if ( ! displayEntry )
2009-06-13 09:40:44 -05:00
{
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing Modelid2 id (%u), can crash client" , cInfo -> Entry , cInfo -> Modelid2 );
const_cast < CreatureInfo *> ( cInfo ) -> Modelid2 = 0 ;
2009-06-13 09:40:44 -05:00
}
2009-06-15 18:02:12 -05:00
else if ( ! displayScaleEntry )
displayScaleEntry = displayEntry ;
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
CreatureModelInfo const * minfo = sCreatureModelStorage . LookupEntry < CreatureModelInfo > ( cInfo -> Modelid2 );
2009-06-15 18:02:12 -05:00
if ( ! minfo )
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) not has model data for Modelid2 (%u)" , cInfo -> Entry , cInfo -> Modelid2 );
2009-06-15 18:02:12 -05:00
}
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
if ( cInfo -> Modelid3 )
2009-06-14 10:01:44 -05:00
{
2009-09-21 07:52:16 +02:00
CreatureDisplayInfoEntry const * displayEntry = sCreatureDisplayInfoStore . LookupEntry ( cInfo -> Modelid3 );
2009-06-15 18:02:12 -05:00
if ( ! displayEntry )
{
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing Modelid3 id (%u), can crash client" , cInfo -> Entry , cInfo -> Modelid3 );
const_cast < CreatureInfo *> ( cInfo ) -> Modelid3 = 0 ;
2009-06-15 18:02:12 -05:00
}
else if ( ! displayScaleEntry )
displayScaleEntry = displayEntry ;
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
CreatureModelInfo const * minfo = sCreatureModelStorage . LookupEntry < CreatureModelInfo > ( cInfo -> Modelid3 );
2009-06-14 10:01:44 -05:00
if ( ! minfo )
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) not has model data for Modelid3 (%u)" , cInfo -> Entry , cInfo -> Modelid3 );
2009-06-14 10:01:44 -05:00
}
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
if ( cInfo -> Modelid4 )
2009-06-14 10:01:44 -05:00
{
2009-09-21 07:52:16 +02:00
CreatureDisplayInfoEntry const * displayEntry = sCreatureDisplayInfoStore . LookupEntry ( cInfo -> Modelid4 );
2009-06-15 18:02:12 -05:00
if ( ! displayEntry )
{
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing Modelid4 id (%u), can crash client" , cInfo -> Entry , cInfo -> Modelid4 );
const_cast < CreatureInfo *> ( cInfo ) -> Modelid4 = 0 ;
2009-06-15 18:02:12 -05:00
}
else if ( ! displayScaleEntry )
displayScaleEntry = displayEntry ;
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
CreatureModelInfo const * minfo = sCreatureModelStorage . LookupEntry < CreatureModelInfo > ( cInfo -> Modelid4 );
2009-06-14 10:01:44 -05:00
if ( ! minfo )
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) not has model data for Modelid4 (%u)" , cInfo -> Entry , cInfo -> Modelid4 );
2009-06-14 10:01:44 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
if ( ! displayScaleEntry )
2009-09-21 07:52:16 +02:00
sLog . outErrorDb ( "Creature (Entry: %u) not has any existed display id in Modelid1/Modelid2/Modelid3/Modelid4" , cInfo -> Entry );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( int k = 0 ; k < MAX_KILL_CREDIT ; ++ k )
2009-07-20 12:30:37 +08:00
{
if ( cInfo -> KillCredit [ k ])
{
if ( ! GetCreatureTemplate ( cInfo -> KillCredit [ k ]))
{
sLog . outErrorDb ( "Creature (Entry: %u) has not existed creature entry in `KillCredit%d` (%u)" , cInfo -> Entry , k + 1 , cInfo -> KillCredit [ k ]);
const_cast < CreatureInfo *> ( cInfo ) -> KillCredit [ k ] = 0 ;
}
}
}
2009-10-17 15:51:44 -07:00
2010-01-14 18:08:42 +01:00
if ( ! cInfo -> unit_class || (( 1 << ( cInfo -> unit_class - 1 )) & CLASSMASK_ALL_CREATURES ) == 0 )
2010-01-14 19:20:11 +01:00
{
sLog . outErrorDb ( "Creature (Entry: %u) has invalid unit_class(%u) for creature_template. Set to 1 (UNIT_CLASS_WARRIOR)." , cInfo -> Entry , cInfo -> unit_class );
const_cast < CreatureInfo *> ( cInfo ) -> unit_class = UNIT_CLASS_WARRIOR ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( cInfo -> dmgschool >= MAX_SPELL_SCHOOL )
{
sLog . outErrorDb ( "Creature (Entry: %u) has invalid spell school value (%u) in `dmgschool`" , cInfo -> Entry , cInfo -> dmgschool );
const_cast < CreatureInfo *> ( cInfo ) -> dmgschool = SPELL_SCHOOL_NORMAL ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( cInfo -> baseattacktime == 0 )
const_cast < CreatureInfo *> ( cInfo ) -> baseattacktime = BASE_ATTACK_TIME ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( cInfo -> rangeattacktime == 0 )
const_cast < CreatureInfo *> ( cInfo ) -> rangeattacktime = BASE_ATTACK_TIME ;
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
if ( cInfo -> npcflag & UNIT_NPC_FLAG_SPELLCLICK )
{
sLog . outErrorDb ( "Creature (Entry: %u) has dynamic flag UNIT_NPC_FLAG_SPELLCLICK (%u) set, it expect to be set by code base at `npc_spellclick_spells` content." , cInfo -> Entry , UNIT_NPC_FLAG_SPELLCLICK );
const_cast < CreatureInfo *> ( cInfo ) -> npcflag &= ~ UNIT_NPC_FLAG_SPELLCLICK ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if (( cInfo -> npcflag & UNIT_NPC_FLAG_TRAINER ) && cInfo -> trainer_type >= MAX_TRAINER_TYPE )
sLog . outErrorDb ( "Creature (Entry: %u) has wrong trainer type %u" , cInfo -> Entry , cInfo -> trainer_type );
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
if ( cInfo -> type && ! sCreatureTypeStore . LookupEntry ( cInfo -> type ))
{
sLog . outErrorDb ( "Creature (Entry: %u) has invalid creature type (%u) in `type`" , cInfo -> Entry , cInfo -> type );
const_cast < CreatureInfo *> ( cInfo ) -> type = CREATURE_TYPE_HUMANOID ;
}
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
// must exist or used hidden but used in data horse case
if ( cInfo -> family && ! sCreatureFamilyStore . LookupEntry ( cInfo -> family ) && cInfo -> family != CREATURE_FAMILY_HORSE_CUSTOM )
{
sLog . outErrorDb ( "Creature (Entry: %u) has invalid creature family (%u) in `family`" , cInfo -> Entry , cInfo -> family );
const_cast < CreatureInfo *> ( cInfo ) -> family = 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( cInfo -> InhabitType <= 0 || cInfo -> InhabitType > INHABIT_ANYWHERE )
{
sLog . outErrorDb ( "Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly" , cInfo -> Entry , cInfo -> InhabitType );
const_cast < CreatureInfo *> ( cInfo ) -> InhabitType = INHABIT_ANYWHERE ;
}
2009-10-17 15:51:44 -07:00
2010-02-17 00:51:19 -07:00
if ( cInfo -> VehicleId )
{
2010-02-18 02:07:20 -07:00
VehicleEntry const * vehId = sVehicleStore . LookupEntry ( cInfo -> VehicleId );
2010-02-17 00:51:19 -07:00
if ( ! vehId )
sLog . outErrorDb ( "Creature (Entry: %u) has a non-existing VehicleId (%u). This *WILL* cause the client to freeze!" , cInfo -> Entry , cInfo -> VehicleId );
}
2008-10-11 14:16:25 -05:00
if ( cInfo -> PetSpellDataId )
{
CreatureSpellDataEntry const * spellDataId = sCreatureSpellDataStore . LookupEntry ( cInfo -> PetSpellDataId );
if ( ! spellDataId )
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing PetSpellDataId (%u)" , cInfo -> Entry , cInfo -> PetSpellDataId );
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < CREATURE_MAX_SPELLS ; ++ j )
2009-02-02 09:53:01 -06:00
{
2009-04-27 18:42:35 -05:00
if ( cInfo -> spells [ j ] && ! sSpellStore . LookupEntry ( cInfo -> spells [ j ]))
2009-02-02 09:53:01 -06:00
{
2009-04-27 18:42:35 -05:00
sLog . outErrorDb ( "Creature (Entry: %u) has non-existing Spell%d (%u), set to 0" , cInfo -> Entry , j + 1 , cInfo -> spells [ j ]);
const_cast < CreatureInfo *> ( cInfo ) -> spells [ j ] = 0 ;
2009-02-02 09:53:01 -06:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( cInfo -> MovementType >= MAX_DB_MOTION_TYPE )
{
sLog . outErrorDb ( "Creature (Entry: %u) has wrong movement generator type (%u), ignore and set to IDLE." , cInfo -> Entry , cInfo -> MovementType );
const_cast < CreatureInfo *> ( cInfo ) -> MovementType = IDLE_MOTION_TYPE ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( cInfo -> equipmentId > 0 ) // 0 no equipment
{
if ( ! GetEquipmentInfo ( cInfo -> equipmentId ))
{
sLog . outErrorDb ( "Table `creature_template` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment." , cInfo -> Entry , cInfo -> equipmentId );
const_cast < CreatureInfo *> ( cInfo ) -> equipmentId = 0 ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
if ( cInfo -> scale <= 0.0f )
{
2009-06-15 18:02:12 -05:00
if ( displayScaleEntry )
const_cast < CreatureInfo *> ( cInfo ) -> scale = displayScaleEntry -> scale ;
else
const_cast < CreatureInfo *> ( cInfo ) -> scale = 1.0f ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-03-03 03:29:03 +02:00
if ( cInfo -> expansion > ( MAX_CREATURE_BASE_HP - 1 ))
{
sLog . outErrorDb ( "Table `creature_template` have creature (Entry: %u) with expansion %u ignore and set to NULL." , cInfo -> expansion );
const_cast < CreatureInfo *> ( cInfo ) -> expansion = 0 ;
}
2009-08-06 10:38:46 -05:00
const_cast < CreatureInfo *> ( cInfo ) -> dmg_multiplier *= Creature :: _GetDamageMod ( cInfo -> rank );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: ConvertCreatureAddonAuras ( CreatureDataAddon * addon , char const * table , char const * guidEntryStr )
{
// Now add the auras, format "spellid effectindex spellid effectindex..."
char * p , * s ;
2010-01-10 01:23:15 +01:00
std :: map < uint32 , uint32 > val ;
2008-10-11 14:16:25 -05:00
s = p = ( char * ) reinterpret_cast < char const *> ( addon -> auras );
if ( p )
{
2010-01-10 01:23:15 +01:00
uint32 currSpellId = 0 ;
bool spell = true ;
2008-10-11 14:16:25 -05:00
while ( p [ 0 ] != 0 )
{
++ p ;
2010-01-10 01:23:15 +01:00
if ( p [ 0 ] == ' ' || p [ 0 ] == 0 )
2008-10-11 14:16:25 -05:00
{
2010-01-10 01:23:15 +01:00
if ( spell )
currSpellId = atoi ( s );
else
{
uint8 eff = atoi ( s );
if ( eff >= 3 )
{
sLog . outErrorDb ( "Creature (%s: %u) has wrong `auras` data in `%s`(too high aura effect: %d for spell: %d)" , guidEntryStr , addon -> guidOrEntry , table , eff , currSpellId );
}
val [ currSpellId ] |= 1 << eff ;
}
spell = ! spell ;
if ( p [ 0 ] == 0 )
break ;
2008-10-11 14:16:25 -05:00
s =++ p ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// free char* loaded memory
delete [] ( char * ) reinterpret_cast < char const *> ( addon -> auras );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// wrong list
2010-01-10 01:23:15 +01:00
if ( ! spell )
2008-10-11 14:16:25 -05:00
{
addon -> auras = NULL ;
sLog . outErrorDb ( "Creature (%s: %u) has wrong `auras` data in `%s`." , guidEntryStr , addon -> guidOrEntry , table );
return ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// empty list
if ( val . empty ())
{
addon -> auras = NULL ;
return ;
}
2009-10-17 15:51:44 -07:00
2008-11-14 16:28:45 -06:00
// replace by new structures array
2010-01-10 01:23:15 +01:00
const_cast < CreatureDataAddonAura *&> ( addon -> auras ) = new CreatureDataAddonAura [ val . size () + 1 ];
2009-10-17 15:51:44 -07:00
2009-09-18 14:10:37 -07:00
uint32 i = 0 ;
2010-01-10 01:23:15 +01:00
for ( std :: map < uint32 , uint32 >:: iterator itr = val . begin (); itr != val . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
CreatureDataAddonAura & cAura = const_cast < CreatureDataAddonAura &> ( addon -> auras [ i ]);
2010-01-10 01:23:15 +01:00
cAura . spell_id = itr -> first ;
cAura . effectMask = itr -> second ;
if ( cAura . effectMask > 7 || ! cAura . effectMask )
2008-10-11 14:16:25 -05:00
{
2010-01-10 01:23:15 +01:00
sLog . outErrorDb ( "Creature (%s: %u) has wrong effect for spell %u in `auras` field in `%s`." , guidEntryStr , addon -> guidOrEntry , cAura . spell_id , table );
2008-10-11 14:16:25 -05:00
continue ;
}
SpellEntry const * AdditionalSpellInfo = sSpellStore . LookupEntry ( cAura . spell_id );
if ( ! AdditionalSpellInfo )
{
sLog . outErrorDb ( "Creature (%s: %u) has wrong spell %u defined in `auras` field in `%s`." , guidEntryStr , addon -> guidOrEntry , cAura . spell_id , table );
continue ;
}
2010-01-10 01:23:15 +01:00
for ( uint8 eff = 0 ; eff < MAX_SPELL_EFFECTS ; ++ eff )
2008-10-11 14:16:25 -05:00
{
2010-01-10 01:23:15 +01:00
if (( 1 << eff ) & cAura . effectMask )
{
if ( ! AdditionalSpellInfo -> Effect [ eff ] || ! AdditionalSpellInfo -> EffectApplyAuraName [ eff ])
{
sLog . outErrorDb ( "Creature (%s: %u) has not aura effect %u of spell %u defined in `auras` field in `%s`." , guidEntryStr , addon -> guidOrEntry , eff , cAura . spell_id , table );
continue ;
}
else if ( AdditionalSpellInfo -> Effect [ eff ] == SPELL_EFFECT_PERSISTENT_AREA_AURA )
{
sLog . outErrorDb ( "Creature (%s: %u) has persistent area aura effect %u of spell %u defined in `auras` field in `%s`." , guidEntryStr , addon -> guidOrEntry , eff , cAura . spell_id , table );
continue ;
}
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ i ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fill terminator element (after last added)
CreatureDataAddonAura & endAura = const_cast < CreatureDataAddonAura &> ( addon -> auras [ i ]);
endAura . spell_id = 0 ;
2010-01-10 01:23:15 +01:00
endAura . effectMask = 0 ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-07-16 10:47:44 +08:00
void ObjectMgr :: LoadCreatureAddons ( SQLStorage & creatureaddons , char const * entryName , char const * comment )
2008-10-11 14:16:25 -05:00
{
2009-07-16 10:47:44 +08:00
creatureaddons . Load ();
2009-10-17 15:51:44 -07:00
2009-07-16 10:47:44 +08:00
sLog . outString ( ">> Loaded %u %s" , creatureaddons . RecordCount , comment );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check data correctness and convert 'auras'
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < creatureaddons . MaxEntry ; ++ i )
2008-10-11 14:16:25 -05:00
{
2009-07-16 10:47:44 +08:00
CreatureDataAddon const * addon = creatureaddons . LookupEntry < CreatureDataAddon > ( i );
2008-10-11 14:16:25 -05:00
if ( ! addon )
continue ;
2009-10-17 15:51:44 -07:00
2009-05-31 15:58:58 -05:00
if ( addon -> mount )
{
if ( ! sCreatureDisplayInfoStore . LookupEntry ( addon -> mount ))
2009-06-13 09:40:44 -05:00
{
2009-07-16 10:47:44 +08:00
sLog . outErrorDb ( "Creature (%s %u) have invalid displayInfoId for mount (%u) defined in `%s`." , entryName , addon -> guidOrEntry , addon -> mount , creatureaddons . GetTableName ());
2009-06-13 09:40:44 -05:00
const_cast < CreatureDataAddon *> ( addon ) -> mount = 0 ;
}
2009-05-31 15:58:58 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-31 15:58:58 -05:00
if ( ! sEmotesStore . LookupEntry ( addon -> emote ))
2009-07-16 10:47:44 +08:00
sLog . outErrorDb ( "Creature (%s %u) have invalid emote (%u) defined in `%s`." , entryName , addon -> guidOrEntry , addon -> emote , creatureaddons . GetTableName ());
2009-10-17 15:51:44 -07:00
2009-07-16 10:47:44 +08:00
/*if (addon->move_flags & (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4))
{
sLog.outErrorDb("Creature (%s %u) movement flags mask defined in `%s` include forbidden flags (" I32FMT ") that can crash client, cleanup at load.", entryName, addon->guidOrEntry, creatureaddons.GetTableName(), (MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4));
const_cast<CreatureDataAddon*>(addon)->move_flags &= ~(MONSTER_MOVE_UNK1|MONSTER_MOVE_UNK4);
}*/
2009-10-17 15:51:44 -07:00
2009-07-16 10:47:44 +08:00
ConvertCreatureAddonAuras ( const_cast < CreatureDataAddon *> ( addon ), creatureaddons . GetTableName (), entryName );
2008-10-11 14:16:25 -05:00
}
2009-07-16 10:47:44 +08:00
}
2009-10-17 15:51:44 -07:00
2009-07-16 10:47:44 +08:00
void ObjectMgr :: LoadCreatureAddons ()
{
LoadCreatureAddons ( sCreatureInfoAddonStorage , "Entry" , "creature template addons" );
2009-10-17 15:51:44 -07:00
2009-07-16 10:47:44 +08:00
// check entry ids
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sCreatureInfoAddonStorage . MaxEntry ; ++ i )
2009-07-16 10:47:44 +08:00
if ( CreatureDataAddon const * addon = sCreatureInfoAddonStorage . LookupEntry < CreatureDataAddon > ( i ))
if ( ! sCreatureStorage . LookupEntry < CreatureInfo > ( addon -> guidOrEntry ))
sLog . outErrorDb ( "Creature (Entry: %u) does not exist but has a record in `%s`" , addon -> guidOrEntry , sCreatureInfoAddonStorage . GetTableName ());
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
sLog . outString ( "Loading Creature Addon Data..." );
2009-07-16 10:47:44 +08:00
LoadCreatureAddons ( sCreatureDataAddonStorage , "GUID" , "creature addons" );
2009-10-17 15:51:44 -07:00
2009-07-16 10:47:44 +08:00
// check entry ids
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sCreatureDataAddonStorage . MaxEntry ; ++ i )
2009-07-16 10:47:44 +08:00
if ( CreatureDataAddon const * addon = sCreatureDataAddonStorage . LookupEntry < CreatureDataAddon > ( i ))
if ( mCreatureDataMap . find ( addon -> guidOrEntry ) == mCreatureDataMap . end ())
sLog . outErrorDb ( "Creature (GUID: %u) does not exist but has a record in `creature_addon`" , addon -> guidOrEntry );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
EquipmentInfo const * ObjectMgr :: GetEquipmentInfo ( uint32 entry )
{
return sEquipmentStorage . LookupEntry < EquipmentInfo > ( entry );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadEquipmentTemplates ()
{
sEquipmentStorage . Load ();
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < sEquipmentStorage . MaxEntry ; ++ i )
2008-12-24 09:58:26 -06:00
{
EquipmentInfo const * eqInfo = sEquipmentStorage . LookupEntry < EquipmentInfo > ( i );
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
if ( ! eqInfo )
continue ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < 3 ; j ++ )
2008-12-24 09:58:26 -06:00
{
if ( ! eqInfo -> equipentry [ j ])
continue ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
ItemEntry const * dbcitem = sItemStore . LookupEntry ( eqInfo -> equipentry [ j ]);
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
if ( ! dbcitem )
{
sLog . outErrorDb ( "Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0." , eqInfo -> equipentry [ j ], j + 1 , i );
const_cast < EquipmentInfo *> ( eqInfo ) -> equipentry [ j ] = 0 ;
continue ;
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
if ( dbcitem -> InventoryType != INVTYPE_WEAPON &&
dbcitem -> InventoryType != INVTYPE_SHIELD &&
dbcitem -> InventoryType != INVTYPE_RANGED &&
dbcitem -> InventoryType != INVTYPE_2HWEAPON &&
dbcitem -> InventoryType != INVTYPE_WEAPONMAINHAND &&
dbcitem -> InventoryType != INVTYPE_WEAPONOFFHAND &&
dbcitem -> InventoryType != INVTYPE_HOLDABLE &&
dbcitem -> InventoryType != INVTYPE_THROWN &&
dbcitem -> InventoryType != INVTYPE_RANGEDRIGHT )
{
sLog . outErrorDb ( "Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0." , eqInfo -> equipentry [ j ], j + 1 , i );
const_cast < EquipmentInfo *> ( eqInfo ) -> equipentry [ j ] = 0 ;
}
}
}
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u equipment template" , sEquipmentStorage . RecordCount );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CreatureModelInfo const * ObjectMgr :: GetCreatureModelInfo ( uint32 modelid )
{
return sCreatureModelStorage . LookupEntry < CreatureModelInfo > ( modelid );
}
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
uint32 ObjectMgr :: ChooseDisplayId ( uint32 team , const CreatureInfo * cinfo , const CreatureData * data /*= NULL*/ )
2008-10-11 14:16:25 -05:00
{
// Load creature model (display id)
2009-09-21 07:52:16 +02:00
uint32 display_id = 0 ;
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
if ( ! data || data -> displayid == 0 )
{
display_id = cinfo -> GetRandomValidModelId ();
}
else
2009-06-15 18:02:12 -05:00
return data -> displayid ;
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
/*if(!team)
2009-08-25 23:55:37 -05:00
{
switch(cinfo->Entry)
{
case 28511: // Eye of Acherus
case 33114: // Flame Leviathan Seat (model 24914 chair)
case 33167: // Salvaged Demolisher Mechanic Seat
2009-08-28 11:26:20 -05:00
case 33189: // Liquid Pryite
2009-09-21 07:52:16 +02:00
return cinfo->Modelid1;
2009-08-26 16:54:59 -05:00
case 33218: // Pyrite Safety Container
2009-09-21 07:52:16 +02:00
return cinfo->Modelid2;
2009-08-26 22:56:20 -05:00
case 33143: // Overload Control Device
2009-09-21 07:52:16 +02:00
return cinfo->Modelid3;
2009-08-25 23:55:37 -05:00
default:
return cinfo->GetRandomValidModelId();
}
2009-09-21 07:52:16 +02:00
}*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return display_id ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CreatureModelInfo const * ObjectMgr :: GetCreatureModelRandomGender ( uint32 display_id )
{
CreatureModelInfo const * minfo = GetCreatureModelInfo ( display_id );
if ( ! minfo )
return NULL ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// If a model for another gender exists, 50% chance to use it
if ( minfo -> modelid_other_gender != 0 && urand ( 0 , 1 ) == 0 )
{
CreatureModelInfo const * minfo_tmp = GetCreatureModelInfo ( minfo -> modelid_other_gender );
if ( ! minfo_tmp )
{
sLog . outErrorDb ( "Model (Entry: %u) has modelid_other_gender %u not found in table `creature_model_info`. " , minfo -> modelid , minfo -> modelid_other_gender );
return minfo ; // not fatal, just use the previous one
}
else
return minfo_tmp ;
}
else
return minfo ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCreatureModelInfo ()
{
sCreatureModelStorage . Load ();
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
// post processing
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sCreatureModelStorage . MaxEntry ; ++ i )
2009-06-15 18:02:12 -05:00
{
CreatureModelInfo const * minfo = sCreatureModelStorage . LookupEntry < CreatureModelInfo > ( i );
if ( ! minfo )
continue ;
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
if ( ! sCreatureDisplayInfoStore . LookupEntry ( minfo -> modelid ))
sLog . outErrorDb ( "Table `creature_model_info` has model for not existed display id (%u)." , minfo -> modelid );
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
if ( minfo -> gender > GENDER_NONE )
{
sLog . outErrorDb ( "Table `creature_model_info` has wrong gender (%u) for display id (%u)." , uint32 ( minfo -> gender ), minfo -> modelid );
const_cast < CreatureModelInfo *> ( minfo ) -> gender = GENDER_MALE ;
}
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
if ( minfo -> modelid_other_gender && ! sCreatureDisplayInfoStore . LookupEntry ( minfo -> modelid_other_gender ))
{
sLog . outErrorDb ( "Table `creature_model_info` has not existed alt.gender model (%u) for existed display id (%u)." , minfo -> modelid_other_gender , minfo -> modelid );
const_cast < CreatureModelInfo *> ( minfo ) -> modelid_other_gender = 0 ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u creature model based info" , sCreatureModelStorage . RecordCount );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-10-17 15:51:44 -07:00
2008-11-01 16:53:16 -05:00
// check if combat_reach is valid
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sCreatureModelStorage . MaxEntry ; ++ i )
2008-11-01 16:53:16 -05:00
{
CreatureModelInfo const * mInfo = sCreatureModelStorage . LookupEntry < CreatureModelInfo > ( i );
if ( ! mInfo )
continue ;
2009-10-17 15:51:44 -07:00
2008-12-04 23:00:35 -06:00
if ( mInfo -> combat_reach < 0.1f )
2008-11-01 16:53:16 -05:00
{
2008-11-01 18:52:59 -05:00
//sLog.outErrorDb("Creature model (Entry: %u) has invalid combat reach (%f), setting it to 0.5", mInfo->modelid, mInfo->combat_reach);
2008-12-04 23:00:35 -06:00
const_cast < CreatureModelInfo *> ( mInfo ) -> combat_reach = DEFAULT_COMBAT_REACH ;
2008-11-01 16:53:16 -05:00
}
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
bool ObjectMgr :: CheckCreatureLinkedRespawn ( uint32 guid , uint32 linkedGuid ) const
{
const CreatureData * const slave = GetCreatureData ( guid );
const CreatureData * const master = GetCreatureData ( linkedGuid );
2009-10-17 16:20:24 -07:00
2009-04-14 14:33:48 +02:00
if ( ! slave || ! master ) // they must have a corresponding entry in db
{
sLog . outError ( "LinkedRespawn: Creature '%u' linking to '%u' which doesn't exist" , guid , linkedGuid );
return false ;
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
const MapEntry * const map = sMapStore . LookupEntry ( master -> mapid );
2009-10-17 16:20:24 -07:00
2009-04-14 14:33:48 +02:00
if ( master -> mapid != slave -> mapid // link only to same map
&& ( ! map || map -> Instanceable ())) // or to unistanced world
{
sLog . outError ( "LinkedRespawn: Creature '%u' linking to '%u' on an unpermitted map" , guid , linkedGuid );
return false ;
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
if ( ! ( master -> spawnMask & slave -> spawnMask ) // they must have a possibility to meet (normal/heroic difficulty)
&& ( ! map || map -> Instanceable ()))
{
sLog . outError ( "LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask" , guid , linkedGuid );
return false ;
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
return true ;
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
void ObjectMgr :: LoadCreatureLinkedRespawn ()
{
mCreatureLinkedRespawnMap . clear ();
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT guid, linkedGuid FROM creature_linked_respawn ORDER BY guid ASC" );
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
sLog . outString ( "" );
sLog . outErrorDb ( ">> Loaded 0 linked respawns. DB table `creature_linked_respawn` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
uint32 guid = fields [ 0 ]. GetUInt32 ();
uint32 linkedGuid = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
if ( CheckCreatureLinkedRespawn ( guid , linkedGuid ))
mCreatureLinkedRespawnMap [ guid ] = linkedGuid ;
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
sLog . outString ();
sLog . outString ( ">> Loaded %u linked respawns" , mCreatureLinkedRespawnMap . size () );
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
bool ObjectMgr :: SetCreatureLinkedRespawn ( uint32 guid , uint32 linkedGuid )
{
if ( ! guid )
return false ;
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
if ( ! linkedGuid ) // we're removing the linking
{
mCreatureLinkedRespawnMap . erase ( guid );
2009-09-10 22:40:40 +02:00
WorldDatabase . DirectPExecute ( "DELETE FROM creature_linked_respawn WHERE guid = '%u'" , guid );
2009-04-14 14:33:48 +02:00
return true ;
}
2009-10-17 15:51:44 -07:00
2009-04-14 14:33:48 +02:00
if ( CheckCreatureLinkedRespawn ( guid , linkedGuid )) // we add/change linking
{
mCreatureLinkedRespawnMap [ guid ] = linkedGuid ;
2009-09-10 22:40:40 +02:00
WorldDatabase . DirectPExecute ( "REPLACE INTO creature_linked_respawn (guid,linkedGuid) VALUES ('%u','%u')" , guid , linkedGuid );
2009-04-14 14:33:48 +02:00
return true ;
}
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCreatures ()
{
uint32 count = 0 ;
// 0 1 2 3
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT creature.guid, id, map, modelid,"
2008-10-11 14:16:25 -05:00
// 4 5 6 7 8 9 10 11
"equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint,"
2009-02-19 18:44:20 -06:00
// 12 13 14 15 16 17 18 19
"curhealth, curmana, DeathState, MovementType, spawnMask, phaseMask, event, pool_entry "
"FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid "
"LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded 0 creature. DB table `creature` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// build single time for check creature data
2009-12-17 14:06:20 +01:00
std :: set < uint32 > difficultyCreatures [ MAX_DIFFICULTY - 1 ];
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < sCreatureStorage . MaxEntry ; ++ i )
2009-12-17 14:06:20 +01:00
if ( CreatureInfo const * cInfo = sCreatureStorage . LookupEntry < CreatureInfo > ( i ))
for ( uint32 diff = 0 ; diff < MAX_DIFFICULTY - 1 ; ++ diff )
if ( cInfo -> DifficultyEntry [ diff ])
difficultyCreatures [ diff ]. insert ( cInfo -> DifficultyEntry [ diff ]);
// build single time for check spawnmask
std :: map < uint32 , uint32 > spawnMasks ;
for ( uint32 i = 0 ; i < sMapStore . GetNumRows (); ++ i )
if ( sMapStore . LookupEntry ( i ))
for ( int k = 0 ; k < MAX_DIFFICULTY ; ++ k )
if ( GetMapDifficultyData ( i , Difficulty ( k )))
spawnMasks [ i ] |= ( 1 << k );
2009-10-17 15:51:44 -07:00
2009-05-30 15:05:54 -05:00
//TODO: remove this
2009-05-30 22:15:05 -05:00
//gameeventmgr.mGameEventCreatureGuids.resize(52*2-1);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
uint32 guid = fields [ 0 ]. GetUInt32 ();
uint32 entry = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
CreatureInfo const * cInfo = GetCreatureTemplate ( entry );
if ( ! cInfo )
{
sLog . outErrorDb ( "Table `creature` has creature (GUID: %u) with non existing creature entry %u, skipped." , guid , entry );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CreatureData & data = mCreatureDataMap [ guid ];
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
data . id = entry ;
2008-10-11 14:16:25 -05:00
data . mapid = fields [ 2 ]. GetUInt32 ();
data . displayid = fields [ 3 ]. GetUInt32 ();
data . equipmentId = fields [ 4 ]. GetUInt32 ();
data . posX = fields [ 5 ]. GetFloat ();
data . posY = fields [ 6 ]. GetFloat ();
data . posZ = fields [ 7 ]. GetFloat ();
data . orientation = fields [ 8 ]. GetFloat ();
data . spawntimesecs = fields [ 9 ]. GetUInt32 ();
data . spawndist = fields [ 10 ]. GetFloat ();
data . currentwaypoint = fields [ 11 ]. GetUInt32 ();
data . curhealth = fields [ 12 ]. GetUInt32 ();
data . curmana = fields [ 13 ]. GetUInt32 ();
data . is_dead = fields [ 14 ]. GetBool ();
data . movementType = fields [ 15 ]. GetUInt8 ();
data . spawnMask = fields [ 16 ]. GetUInt8 ();
2009-01-31 16:38:50 -06:00
data . phaseMask = fields [ 17 ]. GetUInt16 ();
int16 gameEvent = fields [ 18 ]. GetInt16 ();
2009-02-19 18:44:20 -06:00
int16 PoolId = fields [ 19 ]. GetInt16 ();
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
MapEntry const * mapEntry = sMapStore . LookupEntry ( data . mapid );
if ( ! mapEntry )
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u) that spawned at not existed map (Id: %u), skipped." , guid , data . mapid );
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( data . spawnMask & ~ spawnMasks [ data . mapid ])
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u)." , guid , data . spawnMask , data . mapid );
bool ok = true ;
for ( uint32 diff = 0 ; diff < MAX_DIFFICULTY - 1 && ok ; ++ diff )
{
if ( difficultyCreatures [ diff ]. find ( data . id ) != difficultyCreatures [ diff ]. end ())
{
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u) that listed as difficulty %u template (entry: %u) in `creature_template`, skipped." ,
guid , diff + 1 , data . id );
ok = false ;
}
}
if ( ! ok )
continue ;
2009-05-30 22:15:05 -05:00
// I do not know why but in db most display id are not zero
2009-06-03 21:47:38 -05:00
/*if(data.displayid == 11686 || data.displayid == 24719)
2009-06-03 00:36:44 -05:00
{
(const_cast<CreatureInfo*>(cInfo))->flags_extra |= CREATURE_FLAG_EXTRA_TRIGGER;
}
2009-06-13 09:40:44 -05:00
else if(data.displayid == cInfo->DisplayID_A || data.displayid == cInfo->DisplayID_A2
|| data.displayid == cInfo->DisplayID_H || data.displayid == cInfo->DisplayID_H2)
2009-05-30 22:15:05 -05:00
data.displayid = 0;
2009-06-03 21:47:38 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( data . equipmentId > 0 ) // -1 no equipment, 0 use default
{
if ( ! GetEquipmentInfo ( data . equipmentId ))
{
sLog . outErrorDb ( "Table `creature` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment." , data . id , data . equipmentId );
data . equipmentId = - 1 ;
}
}
2009-10-17 15:51:44 -07:00
2009-02-27 12:21:28 -06:00
if ( cInfo -> flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND )
{
2009-12-17 14:06:20 +01:00
if ( ! mapEntry || ! mapEntry -> IsDungeon ())
2009-02-27 12:21:28 -06:00
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND but creature are not in instance." , guid , data . id );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( data . spawndist < 0.0f )
{
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u Entry: %u) with `spawndist`< 0, set to 0." , guid , data . id );
data . spawndist = 0.0f ;
}
else if ( data . movementType == RANDOM_MOTION_TYPE )
{
if ( data . spawndist == 0.0f )
{
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=1 (random movement) but with `spawndist`=0, replace by idle movement type (0)." , guid , data . id );
data . movementType = IDLE_MOTION_TYPE ;
}
2009-06-03 00:36:44 -05:00
else if ( cInfo -> flags_extra & CREATURE_FLAG_EXTRA_TRIGGER )
data . movementType = IDLE_MOTION_TYPE ;
2008-10-11 14:16:25 -05:00
}
else if ( data . movementType == IDLE_MOTION_TYPE )
{
if ( data . spawndist != 0.0f )
{
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u Entry: %u) with `MovementType`=0 (idle) have `spawndist`<>0, set to 0." , guid , data . id );
data . spawndist = 0.0f ;
}
}
2009-10-17 15:51:44 -07:00
2009-01-31 16:38:50 -06:00
if ( data . phaseMask == 0 )
{
sLog . outErrorDb ( "Table `creature` have creature (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1." , guid , data . id );
data . phaseMask = 1 ;
}
2009-10-17 15:51:44 -07:00
2009-05-30 15:05:54 -05:00
//if(entry == 32307 || entry == 32308)
2009-05-30 22:15:05 -05:00
/*if(entry == 30739 || entry == 30740)
2009-05-30 15:05:54 -05:00
{
gameEvent = 51;
uint32 guid2 = objmgr.GenerateLowGuid(HIGHGUID_UNIT);
CreatureData& data2 = mCreatureDataMap[guid2];
data2 = data;
// data2.id = (entry == 32307 ? 32308 : 32307);
data2.id = (entry == 30739 ? 30740 : 30739);
data2.displayid = 0;
gameeventmgr.mGameEventCreatureGuids[51+51].push_back(guid);
gameeventmgr.mGameEventCreatureGuids[51+50].push_back(guid2);
2009-05-30 22:15:05 -05:00
}*/
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
if ( gameEvent == 0 && PoolId == 0 ) // if not this is to be managed by GameEvent System or Pool system
2008-10-11 14:16:25 -05:00
AddCreatureToGrid ( guid , & data );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu creatures" , ( unsigned long ) mCreatureDataMap . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: AddCreatureToGrid ( uint32 guid , CreatureData const * data )
{
uint8 mask = data -> spawnMask ;
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; mask != 0 ; i ++ , mask >>= 1 )
2008-10-11 14:16:25 -05:00
{
if ( mask & 1 )
{
2008-10-14 11:57:03 -05:00
CellPair cell_pair = Trinity :: ComputeCellPair ( data -> posX , data -> posY );
2008-10-11 14:16:25 -05:00
uint32 cell_id = ( cell_pair . y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP ) + cell_pair . x_coord ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CellObjectGuids & cell_guids = mMapObjectGuids [ MAKE_PAIR32 ( data -> mapid , i )][ cell_id ];
cell_guids . creatures . insert ( guid );
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: RemoveCreatureFromGrid ( uint32 guid , CreatureData const * data )
{
uint8 mask = data -> spawnMask ;
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; mask != 0 ; i ++ , mask >>= 1 )
2008-10-11 14:16:25 -05:00
{
if ( mask & 1 )
{
2008-10-14 11:57:03 -05:00
CellPair cell_pair = Trinity :: ComputeCellPair ( data -> posX , data -> posY );
2008-10-11 14:16:25 -05:00
uint32 cell_id = ( cell_pair . y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP ) + cell_pair . x_coord ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CellObjectGuids & cell_guids = mMapObjectGuids [ MAKE_PAIR32 ( data -> mapid , i )][ cell_id ];
cell_guids . creatures . erase ( guid );
}
}
}
2009-10-17 15:51:44 -07:00
2009-08-10 23:38:51 -05:00
uint32 ObjectMgr :: AddGOData ( uint32 entry , uint32 mapId , float x , float y , float z , float o , uint32 spawntimedelay , float rotation0 , float rotation1 , float rotation2 , float rotation3 )
2009-05-31 14:26:57 -05:00
{
GameObjectInfo const * goinfo = GetGameObjectInfo ( entry );
if ( ! goinfo )
return 0 ;
2009-10-17 15:51:44 -07:00
2009-08-12 08:51:51 -05:00
Map * map = const_cast < Map *> ( MapManager :: Instance (). CreateBaseMap ( mapId ));
if ( ! map )
return 0 ;
2009-10-17 15:51:44 -07:00
2009-05-31 14:26:57 -05:00
uint32 guid = GenerateLowGuid ( HIGHGUID_GAMEOBJECT );
GameObjectData & data = NewGOData ( guid );
data . id = entry ;
data . mapid = mapId ;
data . posX = x ;
data . posY = y ;
data . posZ = z ;
data . orientation = o ;
data . rotation0 = rotation0 ;
data . rotation1 = rotation1 ;
data . rotation2 = rotation2 ;
data . rotation3 = rotation3 ;
data . spawntimesecs = spawntimedelay ;
data . animprogress = 100 ;
data . spawnMask = 1 ;
data . go_state = GO_STATE_READY ;
data . phaseMask = PHASEMASK_NORMAL ;
2009-08-21 12:31:52 -05:00
data . artKit = goinfo -> type == GAMEOBJECT_TYPE_CAPTURE_POINT ? 21 : 0 ;
2009-05-31 14:26:57 -05:00
data . dbData = false ;
2009-10-17 15:51:44 -07:00
2009-05-31 14:26:57 -05:00
AddGameobjectToGrid ( guid , & data );
2009-10-17 15:51:44 -07:00
2009-05-31 14:26:57 -05:00
// Spawn if necessary (loaded grids only)
2009-08-12 08:51:51 -05:00
// We use spawn coords to spawn
2009-10-31 17:34:35 -07:00
if ( ! map -> Instanceable () && map -> IsLoaded ( x , y ))
2009-05-31 14:26:57 -05:00
{
2009-08-12 08:51:51 -05:00
GameObject * go = new GameObject ;
2009-10-31 17:34:35 -07:00
if ( ! go -> LoadFromDB ( guid , map ))
2009-05-31 14:26:57 -05:00
{
2009-08-12 08:51:51 -05:00
sLog . outError ( "AddGOData: cannot add gameobject entry %u to map" , entry );
delete go ;
return 0 ;
2009-05-31 14:26:57 -05:00
}
2009-08-12 08:51:51 -05:00
map -> Add ( go );
2009-05-31 14:26:57 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-12 08:51:51 -05:00
sLog . outDebug ( "AddGOData: dbguid %u entry %u map %u x %f y %f z %f o %f" , guid , entry , mapId , x , y , z , o );
2009-10-17 15:51:44 -07:00
2009-05-31 14:26:57 -05:00
return guid ;
}
2009-10-17 15:51:44 -07:00
2009-11-07 15:54:33 +01:00
bool ObjectMgr :: MoveCreData ( uint32 guid , uint32 mapId , Position pos )
{
CreatureData & data = NewOrExistCreatureData ( guid );
if ( ! data . id )
return false ;
RemoveCreatureFromGrid ( guid , & data );
if ( data . posX == pos . GetPositionX () && data . posY == pos . GetPositionY () && data . posZ == pos . GetPositionZ ())
return true ;
data . posX = pos . GetPositionX ();
data . posY = pos . GetPositionY ();
data . posZ = pos . GetPositionZ ();
data . orientation = pos . GetOrientation ();
AddCreatureToGrid ( guid , & data );
// Spawn if necessary (loaded grids only)
if ( Map * map = const_cast < Map *> ( MapManager :: Instance (). CreateBaseMap ( mapId )))
{
// We use spawn coords to spawn
if ( ! map -> Instanceable () && map -> IsLoaded ( data . posX , data . posY ))
{
Creature * creature = new Creature ;
if ( ! creature -> LoadFromDB ( guid , map ))
{
sLog . outError ( "AddCreature: cannot add creature entry %u to map" , guid );
delete creature ;
return false ;
}
map -> Add ( creature );
}
}
return true ;
}
2009-08-10 23:38:51 -05:00
uint32 ObjectMgr :: AddCreData ( uint32 entry , uint32 team , uint32 mapId , float x , float y , float z , float o , uint32 spawntimedelay )
2009-05-31 14:26:57 -05:00
{
CreatureInfo const * cInfo = GetCreatureTemplate ( entry );
if ( ! cInfo )
return 0 ;
2009-10-17 15:51:44 -07:00
2009-12-20 20:23:18 -07:00
uint32 level = cInfo -> minlevel == cInfo -> maxlevel ? cInfo -> minlevel : urand ( cInfo -> minlevel , cInfo -> maxlevel ); // Only used for extracting creature base stats
2010-01-10 22:02:03 +01:00
CreatureBaseStats const * stats = objmgr . GetCreatureBaseStats ( level , cInfo -> unit_class );
2009-12-20 20:23:18 -07:00
2009-05-31 14:26:57 -05:00
uint32 guid = GenerateLowGuid ( HIGHGUID_UNIT );
CreatureData & data = NewOrExistCreatureData ( guid );
data . id = entry ;
data . mapid = mapId ;
data . displayid = 0 ;
data . equipmentId = cInfo -> equipmentId ;
data . posX = x ;
data . posY = y ;
data . posZ = z ;
data . orientation = o ;
data . spawntimesecs = spawntimedelay ;
data . spawndist = 0 ;
data . currentwaypoint = 0 ;
2010-01-10 22:02:03 +01:00
data . curhealth = stats -> GenerateHealth ( cInfo );
data . curmana = stats -> GenerateMana ( cInfo );
2009-05-31 14:26:57 -05:00
data . is_dead = false ;
data . movementType = cInfo -> MovementType ;
data . spawnMask = 1 ;
data . phaseMask = PHASEMASK_NORMAL ;
data . dbData = false ;
2009-10-17 15:51:44 -07:00
2009-05-31 14:26:57 -05:00
AddCreatureToGrid ( guid , & data );
2009-10-17 15:51:44 -07:00
2009-05-31 14:26:57 -05:00
// Spawn if necessary (loaded grids only)
2009-06-16 11:19:59 -05:00
if ( Map * map = const_cast < Map *> ( MapManager :: Instance (). CreateBaseMap ( mapId )))
2009-05-31 14:26:57 -05:00
{
// We use spawn coords to spawn
if ( ! map -> Instanceable () && ! map -> IsRemovalGrid ( x , y ))
{
Creature * creature = new Creature ;
if ( ! creature -> LoadFromDB ( guid , map ))
{
sLog . outError ( "AddCreature: cannot add creature entry %u to map" , entry );
delete creature ;
return 0 ;
}
map -> Add ( creature );
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
return guid ;
2009-05-31 14:26:57 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameobjects ()
{
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0 1 2 3 4 5 6
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation,"
2009-02-19 18:44:20 -06:00
// 7 8 9 10 11 12 13 14 15 16 17
"rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, event, pool_entry "
"FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid "
"LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded 0 gameobjects. DB table `gameobject` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:55:19 +01:00
// build single time for check spawnmask
std :: map < uint32 , uint32 > spawnMasks ;
for ( uint32 i = 0 ; i < sMapStore . GetNumRows (); ++ i )
if ( sMapStore . LookupEntry ( i ))
for ( int k = 0 ; k < MAX_DIFFICULTY ; ++ k )
if ( GetMapDifficultyData ( i , Difficulty ( k )))
spawnMasks [ i ] |= ( 1 << k );
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
uint32 guid = fields [ 0 ]. GetUInt32 ();
uint32 entry = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
GameObjectInfo const * gInfo = GetGameObjectInfo ( entry );
2009-12-17 14:55:19 +01:00
if ( ! gInfo )
2009-02-19 18:44:20 -06:00
{
sLog . outErrorDb ( "Table `gameobject` has gameobject (GUID: %u) with non existing gameobject entry %u, skipped." , guid , entry );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-22 00:36:02 +01:00
if ( ! gInfo -> displayId )
2009-12-17 14:55:19 +01:00
{
2009-12-22 00:36:02 +01:00
switch ( gInfo -> type )
{
case GAMEOBJECT_TYPE_TRAP :
case GAMEOBJECT_TYPE_SPELL_FOCUS :
break ;
default :
sLog . outErrorDb ( "Gameobject (GUID: %u Entry %u GoType: %u) doesn't have displayId (%u), not loaded." , guid , entry , gInfo -> type , gInfo -> displayId );
2009-12-22 02:39:39 +01:00
break ;
2009-12-22 00:36:02 +01:00
}
2009-12-17 14:55:19 +01:00
}
2009-09-02 15:42:40 -05:00
if ( gInfo -> displayId && ! sGameObjectDisplayInfoStore . LookupEntry ( gInfo -> displayId ))
2009-06-13 09:40:44 -05:00
{
sLog . outErrorDb ( "Gameobject (GUID: %u Entry %u GoType: %u) have invalid displayId (%u), not loaded." , guid , entry , gInfo -> type , gInfo -> displayId );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
GameObjectData & data = mGameObjectDataMap [ guid ];
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
data . id = entry ;
2008-10-11 14:16:25 -05:00
data . mapid = fields [ 2 ]. GetUInt32 ();
data . posX = fields [ 3 ]. GetFloat ();
data . posY = fields [ 4 ]. GetFloat ();
data . posZ = fields [ 5 ]. GetFloat ();
data . orientation = fields [ 6 ]. GetFloat ();
data . rotation0 = fields [ 7 ]. GetFloat ();
data . rotation1 = fields [ 8 ]. GetFloat ();
data . rotation2 = fields [ 9 ]. GetFloat ();
data . rotation3 = fields [ 10 ]. GetFloat ();
data . spawntimesecs = fields [ 11 ]. GetInt32 ();
2009-10-17 15:51:44 -07:00
2009-12-17 14:55:19 +01:00
MapEntry const * mapEntry = sMapStore . LookupEntry ( data . mapid );
if ( ! mapEntry )
{
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) that spawned at not existed map (Id: %u), skip" , guid , data . id , data . mapid );
continue ;
}
2009-07-16 12:06:07 +08:00
if ( data . spawntimesecs == 0 && gInfo -> IsDespawnAtAction ())
{
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) with `spawntimesecs` (0) value, but gameobejct marked as despawnable at action." , guid , data . id );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . animprogress = fields [ 12 ]. GetUInt32 ();
2009-08-21 12:31:52 -05:00
data . artKit = 0 ;
2009-10-17 15:51:44 -07:00
2009-04-27 18:36:10 -05:00
uint32 go_state = fields [ 13 ]. GetUInt32 ();
if ( go_state >= MAX_GO_STATE )
{
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid `state` (%u) value, skip" , guid , data . id , go_state );
continue ;
}
data . go_state = GOState ( go_state );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . spawnMask = fields [ 14 ]. GetUInt8 ();
2009-12-17 14:55:19 +01:00
if ( data . spawnMask & ~ spawnMasks [ data . mapid ])
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip" , guid , data . id , data . spawnMask , data . mapid );
2009-01-31 16:38:50 -06:00
data . phaseMask = fields [ 15 ]. GetUInt16 ();
int16 gameEvent = fields [ 16 ]. GetInt16 ();
2009-02-19 18:44:20 -06:00
int16 PoolId = fields [ 17 ]. GetInt16 ();
2009-10-17 15:51:44 -07:00
2009-09-02 15:42:40 -05:00
if ( data . rotation2 < - 1.0f || data . rotation2 > 1.0f )
2009-03-18 20:46:21 -06:00
{
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation2 (%f) value, skip" , guid , data . id , data . rotation2 );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-09-02 15:42:40 -05:00
if ( data . rotation3 < - 1.0f || data . rotation3 > 1.0f )
2009-03-18 20:46:21 -06:00
{
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid rotation3 (%f) value, skip" , guid , data . id , data . rotation3 );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-09-02 15:42:40 -05:00
if ( ! MapManager :: IsValidMapCoord ( data . mapid , data . posX , data . posY , data . posZ , data . orientation ))
2009-03-18 20:46:21 -06:00
{
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid coordinates, skip" , guid , data . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-09-02 15:42:40 -05:00
if ( data . phaseMask == 0 )
2009-01-31 16:38:50 -06:00
{
sLog . outErrorDb ( "Table `gameobject` have gameobject (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1." , guid , data . id );
data . phaseMask = 1 ;
}
2009-10-17 15:51:44 -07:00
2009-02-19 18:44:20 -06:00
if ( gameEvent == 0 && PoolId == 0 ) // if not this is to be managed by GameEvent System or Pool system
2008-10-11 14:16:25 -05:00
AddGameobjectToGrid ( guid , & data );
++ count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu gameobjects" , ( unsigned long ) mGameObjectDataMap . size ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: AddGameobjectToGrid ( uint32 guid , GameObjectData const * data )
{
uint8 mask = data -> spawnMask ;
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; mask != 0 ; i ++ , mask >>= 1 )
2008-10-11 14:16:25 -05:00
{
if ( mask & 1 )
{
2008-10-14 11:57:03 -05:00
CellPair cell_pair = Trinity :: ComputeCellPair ( data -> posX , data -> posY );
2008-10-11 14:16:25 -05:00
uint32 cell_id = ( cell_pair . y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP ) + cell_pair . x_coord ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CellObjectGuids & cell_guids = mMapObjectGuids [ MAKE_PAIR32 ( data -> mapid , i )][ cell_id ];
cell_guids . gameobjects . insert ( guid );
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: RemoveGameobjectFromGrid ( uint32 guid , GameObjectData const * data )
{
uint8 mask = data -> spawnMask ;
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; mask != 0 ; i ++ , mask >>= 1 )
2008-10-11 14:16:25 -05:00
{
if ( mask & 1 )
{
2008-10-14 11:57:03 -05:00
CellPair cell_pair = Trinity :: ComputeCellPair ( data -> posX , data -> posY );
2008-10-11 14:16:25 -05:00
uint32 cell_id = ( cell_pair . y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP ) + cell_pair . x_coord ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CellObjectGuids & cell_guids = mMapObjectGuids [ MAKE_PAIR32 ( data -> mapid , i )][ cell_id ];
cell_guids . gameobjects . erase ( guid );
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCreatureRespawnTimes ()
{
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT guid,respawntime,instance FROM creature_respawn" );
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded 0 creature respawn time." );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 loguid = fields [ 0 ]. GetUInt32 ();
uint64 respawn_time = fields [ 1 ]. GetUInt64 ();
uint32 instance = fields [ 2 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mCreatureRespawnTimes [ MAKE_PAIR64 ( loguid , instance )] = time_t ( respawn_time );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2010-01-01 14:19:29 -06:00
sLog . outString ( ">> Loaded %lu creature respawn times" , ( unsigned long ) mCreatureRespawnTimes . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameobjectRespawnTimes ()
{
// remove outdated data
WorldDatabase . DirectExecute ( "DELETE FROM gameobject_respawn WHERE respawntime <= UNIX_TIMESTAMP(NOW())" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT guid,respawntime,instance FROM gameobject_respawn" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded 0 gameobject respawn time." );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 loguid = fields [ 0 ]. GetUInt32 ();
uint64 respawn_time = fields [ 1 ]. GetUInt64 ();
uint32 instance = fields [ 2 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mGORespawnTimes [ MAKE_PAIR64 ( loguid , instance )] = time_t ( respawn_time );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu gameobject respawn times" , ( unsigned long ) mGORespawnTimes . size () );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// name must be checked to correctness (if received) before call this function
uint64 ObjectMgr :: GetPlayerGUIDByName ( std :: string name ) const
{
uint64 guid = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CharacterDatabase . escape_string ( name );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Player name safe to sending to DB (checked at login) and this function using
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . PQuery ( "SELECT guid FROM characters WHERE name = '%s'" , name . c_str ());
2008-10-11 14:16:25 -05:00
if ( result )
guid = MAKE_NEW_GUID (( * result )[ 0 ]. GetUInt32 (), 0 , HIGHGUID_PLAYER );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return guid ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool ObjectMgr :: GetPlayerNameByGUID ( const uint64 & guid , std :: string & name ) const
{
// prevent DB access for online player
if ( Player * player = GetPlayer ( guid ))
{
name = player -> GetName ();
return true ;
}
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . PQuery ( "SELECT name FROM characters WHERE guid = '%u'" , GUID_LOPART ( guid ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( result )
{
name = ( * result )[ 0 ]. GetCppString ();
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 ObjectMgr :: GetPlayerTeamByGUID ( const uint64 & guid ) const
{
2009-12-17 14:55:19 +01:00
// prevent DB access for online player
if ( Player * player = GetPlayer ( guid ))
{
return Player :: TeamForRace ( player -> getRace ());
}
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . PQuery ( "SELECT race FROM characters WHERE guid = '%u'" , GUID_LOPART ( guid ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( result )
{
uint8 race = ( * result )[ 0 ]. GetUInt8 ();
return Player :: TeamForRace ( race );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 ObjectMgr :: GetPlayerAccountIdByGUID ( const uint64 & guid ) const
{
2009-12-17 14:55:19 +01:00
// prevent DB access for online player
if ( Player * player = GetPlayer ( guid ))
{
return player -> GetSession () -> GetAccountId ();
}
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . PQuery ( "SELECT account FROM characters WHERE guid = '%u'" , GUID_LOPART ( guid ));
2008-10-11 14:16:25 -05:00
if ( result )
{
uint32 acc = ( * result )[ 0 ]. GetUInt32 ();
return acc ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return 0 ;
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
uint32 ObjectMgr :: GetPlayerAccountIdByPlayerName ( const std :: string & name ) const
2008-10-21 19:07:16 -05:00
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . PQuery ( "SELECT account FROM characters WHERE name = '%s'" , name . c_str ());
2008-10-21 19:07:16 -05:00
if ( result )
{
uint32 acc = ( * result )[ 0 ]. GetUInt32 ();
return acc ;
}
2009-10-17 15:51:44 -07:00
2008-10-21 19:07:16 -05:00
return 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadItemLocales ()
{
2008-11-20 16:16:57 -06:00
mItemLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,name_loc1,description_loc1,name_loc2,description_loc2,name_loc3,description_loc3,name_loc4,description_loc4,name_loc5,description_loc5,name_loc6,description_loc6,name_loc7,description_loc7,name_loc8,description_loc8 FROM locales_item" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ItemLocale & data = mItemLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
std :: string str = fields [ 1 + 2 * ( i - 1 )]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Name . size () <= idx )
data . Name . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Name [ idx ] = str ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
str = fields [ 1 + 2 * ( i - 1 ) + 1 ]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Description . size () <= idx )
data . Description . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Description [ idx ] = str ;
}
}
}
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu Item locale strings" , ( unsigned long ) mItemLocaleMap . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
struct SQLItemLoader : public SQLStorageLoaderBase < SQLItemLoader >
{
template < class D >
2009-04-29 00:31:03 -05:00
void convert_from_str ( uint32 /*field_pos*/ , char * src , D & dst )
2008-11-20 16:16:57 -06:00
{
dst = D ( objmgr . GetScriptId ( src ));
}
};
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadItemPrototypes ()
{
2008-11-20 16:16:57 -06:00
SQLItemLoader loader ;
loader . Load ( sItemStorage );
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u item prototypes" , sItemStorage . RecordCount );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check data correctness
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sItemStorage . MaxEntry ; ++ i )
2008-10-11 14:16:25 -05:00
{
ItemPrototype const * proto = sItemStorage . LookupEntry < ItemPrototype > ( i );
ItemEntry const * dbcitem = sItemStore . LookupEntry ( i );
2009-11-01 17:53:07 -08:00
if ( ! proto )
2008-10-11 14:16:25 -05:00
{
/* to many errors, and possible not all items really used in game
if (dbcitem)
sLog.outErrorDb("Item (Entry: %u) doesn't exists in DB, but must exist.",i);
*/
continue ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( dbcitem )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( proto -> Class != dbcitem -> Class )
2009-01-14 18:42:53 -06:00
{
2009-01-16 14:17:24 -06:00
sLog . outErrorDb ( "Item (Entry: %u) not correct class %u, must be %u (still using DB value)." , i , proto -> Class , dbcitem -> Class );
2009-01-14 18:42:53 -06:00
// It safe let use Class from DB
}
/* disabled: have some strange wrong cases for Subclass values.
for enable also uncomment Subclass field in ItemEntry structure and in Itemfmt[]
if(proto->SubClass != dbcitem->SubClass)
2009-01-14 00:35:13 -06:00
{
sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass);
2009-01-14 18:42:53 -06:00
// It safe let use Subclass from DB
2009-01-14 00:35:13 -06:00
}
2009-01-14 18:42:53 -06:00
*/
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Unk0 != dbcitem -> Unk0 )
2009-01-14 00:35:13 -06:00
{
2009-01-14 18:42:53 -06:00
sLog . outErrorDb ( "Item (Entry: %u) not correct %i Unk0, must be %i (still using DB value)." , i , proto -> Unk0 , dbcitem -> Unk0 );
2009-01-14 00:35:13 -06:00
// It safe let use Unk0 from DB
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Material != dbcitem -> Material )
2009-01-14 00:35:13 -06:00
{
2009-01-14 18:42:53 -06:00
sLog . outErrorDb ( "Item (Entry: %u) not correct %i material, must be %i (still using DB value)." , i , proto -> Material , dbcitem -> Material );
2009-01-14 00:35:13 -06:00
// It safe let use Material from DB
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> InventoryType != dbcitem -> InventoryType )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value)." , i , proto -> InventoryType , dbcitem -> InventoryType );
// It safe let use InventoryType from DB
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> DisplayInfoID != dbcitem -> DisplayId )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) not correct %u display id, must be %u (using it)." , i , proto -> DisplayInfoID , dbcitem -> DisplayId );
const_cast < ItemPrototype *> ( proto ) -> DisplayInfoID = dbcitem -> DisplayId ;
}
2009-11-01 17:53:07 -08:00
if ( proto -> Sheath != dbcitem -> Sheath )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) not correct %u sheath, must be %u (using it)." , i , proto -> Sheath , dbcitem -> Sheath );
const_cast < ItemPrototype *> ( proto ) -> Sheath = dbcitem -> Sheath ;
}
}
else
sLog . outErrorDb ( "Item (Entry: %u) not correct (not listed in list of existed items)." , i );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Class >= MAX_ITEM_CLASS )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong Class value (%u)" , i , proto -> Class );
2008-12-24 09:58:26 -06:00
const_cast < ItemPrototype *> ( proto ) -> Class = ITEM_CLASS_MISC ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> SubClass >= MaxItemSubclassValues [ proto -> Class ])
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong Subclass value (%u) for class %u" , i , proto -> SubClass , proto -> Class );
const_cast < ItemPrototype *> ( proto ) -> SubClass = 0 ; // exist for all item classes
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Quality >= MAX_ITEM_QUALITY )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong Quality value (%u)" , i , proto -> Quality );
const_cast < ItemPrototype *> ( proto ) -> Quality = ITEM_QUALITY_NORMAL ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> BuyCount <= 0 )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong BuyCount value (%u), set to default(1)." , i , proto -> BuyCount );
const_cast < ItemPrototype *> ( proto ) -> BuyCount = 1 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> InventoryType >= MAX_INVTYPE )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong InventoryType value (%u)" , i , proto -> InventoryType );
const_cast < ItemPrototype *> ( proto ) -> InventoryType = INVTYPE_NON_EQUIP ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> RequiredSkill >= MAX_SKILL_TYPE )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong RequiredSkill value (%u)" , i , proto -> RequiredSkill );
const_cast < ItemPrototype *> ( proto ) -> RequiredSkill = 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
{
2009-01-04 16:37:14 -06:00
// can be used in equip slot, as page read use in inventory, or spell casting at use
2009-11-01 17:53:07 -08:00
bool req = proto -> InventoryType != INVTYPE_NON_EQUIP || proto -> PageText ;
if ( ! req )
for ( uint8 j = 0 ; j < MAX_ITEM_PROTO_SPELLS ; ++ j )
2009-01-04 16:37:14 -06:00
{
2009-11-01 17:53:07 -08:00
if ( proto -> Spells [ j ]. SpellId )
2009-01-04 16:37:14 -06:00
{
req = true ;
break ;
}
}
2009-12-18 13:41:30 -08:00
2009-11-01 17:53:07 -08:00
if ( req )
2009-01-04 16:37:14 -06:00
{
if ( ! ( proto -> AllowableClass & CLASSMASK_ALL_PLAYABLE ))
sLog . outErrorDb ( "Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped or use." , i , proto -> AllowableClass );
2009-10-17 15:51:44 -07:00
2009-01-04 16:37:14 -06:00
if ( ! ( proto -> AllowableRace & RACEMASK_ALL_PLAYABLE ))
sLog . outErrorDb ( "Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped or use." , i , proto -> AllowableRace );
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> RequiredSpell && ! sSpellStore . LookupEntry ( proto -> RequiredSpell ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) have wrong (non-existed) spell in RequiredSpell (%u)" , i , proto -> RequiredSpell );
const_cast < ItemPrototype *> ( proto ) -> RequiredSpell = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> RequiredReputationRank >= MAX_REPUTATION_RANK )
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong reputation rank in RequiredReputationRank (%u), item can't be used." , i , proto -> RequiredReputationRank );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> RequiredReputationFaction )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( ! sFactionStore . LookupEntry ( proto -> RequiredReputationFaction ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong (not existing) faction in RequiredReputationFaction (%u)" , i , proto -> RequiredReputationFaction );
const_cast < ItemPrototype *> ( proto ) -> RequiredReputationFaction = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> RequiredReputationRank == MIN_REPUTATION_RANK )
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has min. reputation rank in RequiredReputationRank (0) but RequiredReputationFaction > 0, faction setting is useless." , i );
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> MaxCount < - 1 )
2009-01-03 11:06:51 -06:00
{
sLog . outErrorDb ( "Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits." , i , proto -> MaxCount );
const_cast < ItemPrototype *> ( proto ) -> MaxCount = - 1 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Stackable == 0 )
2008-10-11 14:16:25 -05:00
{
2009-01-03 11:06:51 -06:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong value in stackable (%i), replace by default 1." , i , proto -> Stackable );
2008-10-11 14:16:25 -05:00
const_cast < ItemPrototype *> ( proto ) -> Stackable = 1 ;
}
2009-11-01 17:53:07 -08:00
else if ( proto -> Stackable < - 1 )
2009-01-03 11:06:51 -06:00
{
sLog . outErrorDb ( "Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits." , i , proto -> Stackable );
const_cast < ItemPrototype *> ( proto ) -> Stackable = - 1 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> ContainerSlots > MAX_BAG_SIZE )
2009-07-01 17:38:38 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has too large value in ContainerSlots (%u), replace by hardcoded limit (%u)." , i , proto -> ContainerSlots , MAX_BAG_SIZE );
const_cast < ItemPrototype *> ( proto ) -> ContainerSlots = MAX_BAG_SIZE ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> StatsCount > MAX_ITEM_PROTO_STATS )
2009-03-02 16:47:20 -06:00
{
sLog . outErrorDb ( "Item (Entry: %u) has too large value in statscount (%u), replace by hardcoded limit (%u)." , i , proto -> StatsCount , MAX_ITEM_PROTO_STATS );
const_cast < ItemPrototype *> ( proto ) -> StatsCount = MAX_ITEM_PROTO_STATS ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
for ( uint8 j = 0 ; j < MAX_ITEM_PROTO_STATS ; ++ j )
2008-10-11 14:16:25 -05:00
{
// for ItemStatValue != 0
2009-11-01 17:53:07 -08:00
if ( proto -> ItemStat [ j ]. ItemStatValue && proto -> ItemStat [ j ]. ItemStatType >= MAX_ITEM_MOD )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong stat_type%d (%u)" , i , j + 1 , proto -> ItemStat [ j ]. ItemStatType );
const_cast < ItemPrototype *> ( proto ) -> ItemStat [ j ]. ItemStatType = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
switch ( proto -> ItemStat [ j ]. ItemStatType )
2009-09-02 18:11:11 -05:00
{
case ITEM_MOD_SPELL_HEALING_DONE :
case ITEM_MOD_SPELL_DAMAGE_DONE :
sLog . outErrorDb ( "Item (Entry: %u) has deprecated stat_type%d (%u)" , i , j + 1 , proto -> ItemStat [ j ]. ItemStatType );
break ;
default :
break ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
for ( uint8 j = 0 ; j < MAX_ITEM_PROTO_DAMAGES ; ++ j )
2008-10-11 14:16:25 -05:00
{
if ( proto -> Damage [ j ]. DamageType >= MAX_SPELL_SCHOOL )
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong dmg_type%d (%u)" , i , j + 1 , proto -> Damage [ j ]. DamageType );
const_cast < ItemPrototype *> ( proto ) -> Damage [ j ]. DamageType = 0 ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// special format
2010-02-15 18:23:39 +01:00
if (( proto -> Spells [ 0 ]. SpellId == 483 ) || ( proto -> Spells [ 0 ]. SpellId == 55884 ))
2008-10-11 14:16:25 -05:00
{
// spell_1
2009-11-01 17:53:07 -08:00
if ( proto -> Spells [ 0 ]. SpellTrigger != ITEM_SPELLTRIGGER_ON_USE )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format" , i , 0 + 1 , proto -> Spells [ 0 ]. SpellTrigger );
const_cast < ItemPrototype *> ( proto ) -> Spells [ 0 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 0 ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// spell_2 have learning spell
2009-11-01 17:53:07 -08:00
if ( proto -> Spells [ 1 ]. SpellTrigger != ITEM_SPELLTRIGGER_LEARN_SPELL_ID )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u) for special learning format." , i , 1 + 1 , proto -> Spells [ 1 ]. SpellTrigger );
const_cast < ItemPrototype *> ( proto ) -> Spells [ 0 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
}
2009-11-01 17:53:07 -08:00
else if ( ! proto -> Spells [ 1 ]. SpellId )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) not has expected spell in spellid_%d in special learning format." , i , 1 + 1 );
const_cast < ItemPrototype *> ( proto ) -> Spells [ 0 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
}
else
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( proto -> Spells [ 1 ]. SpellId );
2009-11-01 17:53:07 -08:00
if ( ! spellInfo )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%u)" , i , 1 + 1 , proto -> Spells [ 1 ]. SpellId );
const_cast < ItemPrototype *> ( proto ) -> Spells [ 0 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
}
// allowed only in special format
2010-02-15 18:23:39 +01:00
else if (( proto -> Spells [ 1 ]. SpellId == 483 ) || ( proto -> Spells [ 1 ]. SpellId == 55884 ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has broken spell in spellid_%d (%u)" , i , 1 + 1 , proto -> Spells [ 1 ]. SpellId );
const_cast < ItemPrototype *> ( proto ) -> Spells [ 0 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ 1 ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// spell_3*,spell_4*,spell_5* is empty
2009-11-01 17:53:07 -08:00
for ( uint8 j = 2 ; j < MAX_ITEM_PROTO_SPELLS ; ++ j )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( proto -> Spells [ j ]. SpellTrigger != ITEM_SPELLTRIGGER_ON_USE )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)" , i , j + 1 , proto -> Spells [ j ]. SpellTrigger );
const_cast < ItemPrototype *> ( proto ) -> Spells [ j ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ j ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
}
2009-11-01 17:53:07 -08:00
else if ( proto -> Spells [ j ]. SpellId != 0 )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong spell in spellid_%d (%u) for learning special format" , i , j + 1 , proto -> Spells [ j ]. SpellId );
const_cast < ItemPrototype *> ( proto ) -> Spells [ j ]. SpellId = 0 ;
}
}
}
// normal spell list
else
{
2009-11-01 17:53:07 -08:00
for ( uint8 j = 0 ; j < MAX_ITEM_PROTO_SPELLS ; ++ j )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( proto -> Spells [ j ]. SpellTrigger >= MAX_ITEM_SPELLTRIGGER || proto -> Spells [ j ]. SpellTrigger == ITEM_SPELLTRIGGER_LEARN_SPELL_ID )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong item spell trigger value in spelltrigger_%d (%u)" , i , j + 1 , proto -> Spells [ j ]. SpellTrigger );
const_cast < ItemPrototype *> ( proto ) -> Spells [ j ]. SpellId = 0 ;
const_cast < ItemPrototype *> ( proto ) -> Spells [ j ]. SpellTrigger = ITEM_SPELLTRIGGER_ON_USE ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( proto -> Spells [ j ]. SpellId )
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( proto -> Spells [ j ]. SpellId );
2009-11-01 17:53:07 -08:00
if ( ! spellInfo )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong (not existing) spell in spellid_%d (%u)" , i , j + 1 , proto -> Spells [ j ]. SpellId );
const_cast < ItemPrototype *> ( proto ) -> Spells [ j ]. SpellId = 0 ;
}
// allowed only in special format
2010-02-15 18:23:39 +01:00
else if (( proto -> Spells [ j ]. SpellId == 483 ) || ( proto -> Spells [ j ]. SpellId == 55884 ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has broken spell in spellid_%d (%u)" , i , j + 1 , proto -> Spells [ j ]. SpellId );
const_cast < ItemPrototype *> ( proto ) -> Spells [ j ]. SpellId = 0 ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Bonding >= MAX_BIND_TYPE )
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong Bonding value (%u)" , i , proto -> Bonding );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> PageText && ! sPageTextStore . LookupEntry < PageText > ( proto -> PageText ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has non existing first page (Id:%u)" , i , proto -> PageText );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> LockID && ! sLockStore . LookupEntry ( proto -> LockID ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong LockID (%u)" , i , proto -> LockID );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Sheath >= MAX_SHEATHETYPE )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong Sheath (%u)" , i , proto -> Sheath );
const_cast < ItemPrototype *> ( proto ) -> Sheath = SHEATHETYPE_NONE ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> RandomProperty && ! sItemRandomPropertiesStore . LookupEntry ( GetItemEnchantMod ( proto -> RandomProperty )))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has unknown (wrong or not listed in `item_enchantment_template`) RandomProperty (%u)" , i , proto -> RandomProperty );
const_cast < ItemPrototype *> ( proto ) -> RandomProperty = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> RandomSuffix && ! sItemRandomSuffixStore . LookupEntry ( GetItemEnchantMod ( proto -> RandomSuffix )))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong RandomSuffix (%u)" , i , proto -> RandomSuffix );
const_cast < ItemPrototype *> ( proto ) -> RandomSuffix = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> ItemSet && ! sItemSetStore . LookupEntry ( proto -> ItemSet ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) have wrong ItemSet (%u)" , i , proto -> ItemSet );
const_cast < ItemPrototype *> ( proto ) -> ItemSet = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Area && ! GetAreaEntryByAreaID ( proto -> Area ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong Area (%u)" , i , proto -> Area );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> Map && ! sMapStore . LookupEntry ( proto -> Map ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong Map (%u)" , i , proto -> Map );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> BagFamily )
2009-03-21 22:43:47 -06:00
{
// check bits
2009-10-17 16:20:24 -07:00
for ( uint32 j = 0 ; j < sizeof ( proto -> BagFamily ) * 8 ; ++ j )
2009-03-21 22:43:47 -06:00
{
2009-03-24 09:45:03 -06:00
uint32 mask = 1 << j ;
2009-11-01 17:53:07 -08:00
if (( proto -> BagFamily & mask ) == 0 )
2009-03-21 22:43:47 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2009-03-24 09:45:03 -06:00
ItemBagFamilyEntry const * bf = sItemBagFamilyStore . LookupEntry ( j + 1 );
2009-11-01 17:53:07 -08:00
if ( ! bf )
2009-03-21 22:43:47 -06:00
{
sLog . outErrorDb ( "Item (Entry: %u) has bag family bit set not listed in ItemBagFamily.dbc, remove bit" , i );
const_cast < ItemPrototype *> ( proto ) -> BagFamily &= ~ mask ;
2009-03-21 22:44:59 -06:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( BAG_FAMILY_MASK_CURRENCY_TOKENS & mask )
2009-03-21 22:44:59 -06:00
{
CurrencyTypesEntry const * ctEntry = sCurrencyTypesStore . LookupEntry ( proto -> ItemId );
2009-11-01 17:53:07 -08:00
if ( ! ctEntry )
2009-03-21 22:44:59 -06:00
{
sLog . outErrorDb ( "Item (Entry: %u) has currency bag family bit set in BagFamily but not listed in CurrencyTypes.dbc, remove bit" , i );
const_cast < ItemPrototype *> ( proto ) -> BagFamily &= ~ mask ;
}
2009-03-21 22:43:47 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> TotemCategory && ! sTotemCategoryStore . LookupEntry ( proto -> TotemCategory ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong TotemCategory (%u)" , i , proto -> TotemCategory );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
for ( uint8 j = 0 ; j < MAX_ITEM_PROTO_SOCKETS ; ++ j )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( proto -> Socket [ j ]. Color && ( proto -> Socket [ j ]. Color & SOCKET_COLOR_ALL ) != proto -> Socket [ j ]. Color )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong socketColor_%d (%u)" , i , j + 1 , proto -> Socket [ j ]. Color );
const_cast < ItemPrototype *> ( proto ) -> Socket [ j ]. Color = 0 ;
}
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> GemProperties && ! sGemPropertiesStore . LookupEntry ( proto -> GemProperties ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Item (Entry: %u) has wrong GemProperties (%u)" , i , proto -> GemProperties );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> FoodType >= MAX_PET_DIET )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong FoodType value (%u)" , i , proto -> FoodType );
const_cast < ItemPrototype *> ( proto ) -> FoodType = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> ItemLimitCategory && ! sItemLimitCategoryStore . LookupEntry ( proto -> ItemLimitCategory ))
2009-02-15 11:58:27 -06:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong LimitCategory value (%u)" , i , proto -> ItemLimitCategory );
const_cast < ItemPrototype *> ( proto ) -> ItemLimitCategory = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( proto -> HolidayId && ! sHolidaysStore . LookupEntry ( proto -> HolidayId ))
2009-06-13 09:42:46 -05:00
{
sLog . outErrorDb ( "Item (Entry: %u) has wrong HolidayId value (%u)" , i , proto -> HolidayId );
const_cast < ItemPrototype *> ( proto ) -> HolidayId = 0 ;
}
2008-10-11 14:16:25 -05:00
}
2010-02-14 19:13:14 -07:00
// check some dbc referecned items (avoid duplicate reports)
std :: set < uint32 > notFoundOutfit ;
for ( uint32 i = 1 ; i < sCharStartOutfitStore . GetNumRows (); ++ i )
{
CharStartOutfitEntry const * entry = sCharStartOutfitStore . LookupEntry ( i );
if ( ! entry )
continue ;
for ( int j = 0 ; j < MAX_OUTFIT_ITEMS ; ++ j )
{
if ( entry -> ItemId [ j ] <= 0 )
continue ;
uint32 item_id = entry -> ItemId [ j ];
if ( ! GetItemPrototype ( item_id ))
notFoundOutfit . insert ( item_id );
}
}
for ( std :: set < uint32 >:: const_iterator itr = notFoundOutfit . begin (); itr != notFoundOutfit . end (); ++ itr )
sLog . outErrorDb ( "Item (Entry: %u) not exist in `item_template` but referenced in `CharStartOutfit.dnc`" , * itr );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-03-12 18:19:50 +01:00
void ObjectMgr :: LoadVehicleAccessories ()
{
m_VehicleAccessoryMap . clear (); // needed for reload case
VehicleAccessoryList mVehicleList ;
uint32 count = 0 ;
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT `entry`,`accessory_entry`,`seat_id`,`minion` FROM `vehicle_accessory`" );
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outErrorDb ( ">> Loaded 0 LoadVehicleAccessor. DB table `vehicle_accessory` is empty." );
return ;
}
barGoLink bar ( result -> GetRowCount ());
do
{
Field * fields = result -> Fetch ();
bar . step ();
uint32 uiEntry = fields [ 0 ]. GetUInt32 ();
uint32 uiAccessory = fields [ 1 ]. GetUInt32 ();
int8 uiSeat = int8 ( fields [ 2 ]. GetInt16 ());
bool bMinion = fields [ 3 ]. GetBool ();
if ( ! sCreatureStorage . LookupEntry < CreatureInfo > ( uiEntry ))
{
sLog . outErrorDb ( "Table `vehicle_accessory`: creature template entry %u does not exist." , uiEntry );
continue ;
}
if ( ! sCreatureStorage . LookupEntry < CreatureInfo > ( uiAccessory ))
{
sLog . outErrorDb ( "Table `vehicle_accessory`: Accessory %u does not exist." , uiAccessory );
continue ;
}
mVehicleList = GetVehicleAccessoryList ( uiEntry );
mVehicleList . push_back ( VehicleAccessory ( uiAccessory , uiSeat , bMinion ));
m_VehicleAccessoryMap [ uiEntry ] = mVehicleList ;
++ count ;
} while ( result -> NextRow ());
sLog . outString ();
sLog . outString ( ">> Loaded %u Vehicle Accessories" , count );
}
2009-06-08 17:25:02 -05:00
void ObjectMgr :: LoadItemRequiredTarget ()
{
m_ItemRequiredTarget . clear (); // needed for reload case
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,type,targetEntry FROM item_required_target" );
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
sLog . outString ();
sLog . outErrorDb ( ">> Loaded 0 ItemRequiredTarget. DB table `item_required_target` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
uint32 uiItemId = fields [ 0 ]. GetUInt32 ();
uint32 uiType = fields [ 1 ]. GetUInt32 ();
uint32 uiTargetEntry = fields [ 2 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
ItemPrototype const * pItemProto = sItemStorage . LookupEntry < ItemPrototype > ( uiItemId );
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
if ( ! pItemProto )
{
sLog . outErrorDb ( "Table `item_required_target`: Entry %u listed for TargetEntry %u does not exist in `item_template`." , uiItemId , uiTargetEntry );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
bool bIsItemSpellValid = false ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; i < MAX_ITEM_PROTO_SPELLS ; ++ i )
2009-06-08 17:25:02 -05:00
{
if ( SpellEntry const * pSpellInfo = sSpellStore . LookupEntry ( pItemProto -> Spells [ i ]. SpellId ))
{
if ( pItemProto -> Spells [ i ]. SpellTrigger == ITEM_SPELLTRIGGER_ON_USE ||
pItemProto -> Spells [ i ]. SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE )
{
2009-08-27 20:27:55 -05:00
SpellScriptTargetBounds bounds = spellmgr . GetSpellScriptTargetBounds ( pSpellInfo -> Id );
if ( bounds . first != bounds . second )
2009-06-08 17:25:02 -05:00
break ;
2009-10-17 15:51:44 -07:00
2009-06-11 19:44:42 -05:00
for ( int j = 0 ; j < 3 ; ++ j )
2009-06-08 17:25:02 -05:00
{
2009-06-11 19:44:42 -05:00
if ( pSpellInfo -> EffectImplicitTargetA [ i ] == TARGET_UNIT_TARGET_ENEMY ||
pSpellInfo -> EffectImplicitTargetB [ i ] == TARGET_UNIT_TARGET_ENEMY ||
pSpellInfo -> EffectImplicitTargetA [ i ] == TARGET_UNIT_TARGET_ANY ||
pSpellInfo -> EffectImplicitTargetB [ i ] == TARGET_UNIT_TARGET_ANY )
{
bIsItemSpellValid = true ;
break ;
}
2009-06-08 17:25:02 -05:00
}
2009-06-11 19:44:42 -05:00
if ( bIsItemSpellValid )
break ;
2009-06-08 17:25:02 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
if ( ! bIsItemSpellValid )
{
sLog . outErrorDb ( "Table `item_required_target`: Spell used by item %u does not have implicit target TARGET_CHAIN_DAMAGE(6), TARGET_DUELVSPLAYER(25), already listed in `spell_script_target` or doesn't have item spelltrigger." , uiItemId );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
if ( ! uiType || uiType > MAX_ITEM_REQ_TARGET_TYPE )
{
sLog . outErrorDb ( "Table `item_required_target`: Type %u for TargetEntry %u is incorrect." , uiType , uiTargetEntry );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
if ( ! uiTargetEntry )
{
sLog . outErrorDb ( "Table `item_required_target`: TargetEntry == 0 for Type (%u)." , uiType );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
if ( ! sCreatureStorage . LookupEntry < CreatureInfo > ( uiTargetEntry ))
{
sLog . outErrorDb ( "Table `item_required_target`: creature template entry %u does not exist." , uiTargetEntry );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
m_ItemRequiredTarget . insert ( ItemRequiredTargetMap :: value_type ( uiItemId , ItemRequiredTarget ( ItemRequiredTargetType ( uiType ), uiTargetEntry )));
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-06-08 17:25:02 -05:00
sLog . outString ();
sLog . outString ( ">> Loaded %u Item required targets" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadPetLevelInfo ()
{
// Loading levels data
{
// 0 1 2 3 4 5 6 7 8 9
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT creature_entry, level, hp, mana, str, agi, sta, inte, spi, armor FROM pet_levelstats" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u level pet stats definitions" , count );
sLog . outErrorDb ( "Error loading `pet_levelstats` table or empty table." );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 creature_id = fields [ 0 ]. GetUInt32 ();
if ( ! sCreatureStorage . LookupEntry < CreatureInfo > ( creature_id ))
{
sLog . outErrorDb ( "Wrong creature id %u in `pet_levelstats` table, ignoring." , creature_id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_level = fields [ 1 ]. GetUInt32 ();
if ( current_level > sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ))
{
2008-12-19 16:05:13 -06:00
if ( current_level > STRONG_MAX_LEVEL ) // hardcoded level maximum
sLog . outErrorDb ( "Wrong (> %u) level %u in `pet_levelstats` table, ignoring." , STRONG_MAX_LEVEL , current_level );
2008-10-11 14:16:25 -05:00
else
2009-03-09 16:38:53 -06:00
{
2008-10-14 11:57:03 -05:00
sLog . outDetail ( "Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `pet_levelstats` table, ignoring." , current_level );
2009-03-09 16:38:53 -06:00
++ count ; // make result loading percent "expected" correct in case disabled detail mode for example.
}
2008-10-11 14:16:25 -05:00
continue ;
}
else if ( current_level < 1 )
{
sLog . outErrorDb ( "Wrong (<1) level %u in `pet_levelstats` table, ignoring." , current_level );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PetLevelInfo *& pInfoMapEntry = petInfo [ creature_id ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( pInfoMapEntry == NULL )
pInfoMapEntry = new PetLevelInfo [ sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL )];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// data for level 1 stored in [0] array element, ...
PetLevelInfo * pLevelInfo = & pInfoMapEntry [ current_level - 1 ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pLevelInfo -> health = fields [ 2 ]. GetUInt16 ();
pLevelInfo -> mana = fields [ 3 ]. GetUInt16 ();
pLevelInfo -> armor = fields [ 9 ]. GetUInt16 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
for ( int i = 0 ; i < MAX_STATS ; i ++ )
{
pLevelInfo -> stats [ i ] = fields [ i + 4 ]. GetUInt16 ();
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u level pet stats definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Fill gaps and check integrity
for ( PetLevelInfoMap :: iterator itr = petInfo . begin (); itr != petInfo . end (); ++ itr )
{
PetLevelInfo * pInfo = itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fatal error if no level 1 data
if ( ! pInfo || pInfo [ 0 ]. health == 0 )
{
sLog . outErrorDb ( "Creature %u does not have pet stats data for Level 1!" , itr -> first );
exit ( 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fill level gaps
2009-11-01 17:53:07 -08:00
for ( uint8 level = 1 ; level < sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ); ++ level )
2008-10-11 14:16:25 -05:00
{
if ( pInfo [ level ]. health == 0 )
{
sLog . outErrorDb ( "Creature %u has no data for Level %i pet stats data, using data of Level %i." , itr -> first , level + 1 , level );
pInfo [ level ] = pInfo [ level - 1 ];
}
}
}
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
PetLevelInfo const * ObjectMgr :: GetPetLevelInfo ( uint32 creature_id , uint8 level ) const
2008-10-11 14:16:25 -05:00
{
if ( level > sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ))
level = sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PetLevelInfoMap :: const_iterator itr = petInfo . find ( creature_id );
if ( itr == petInfo . end ())
return NULL ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return & itr -> second [ level - 1 ]; // data for level 1 stored in [0] array element, ...
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadPlayerInfo ()
{
// Load playercreate
{
// 0 1 2 3 4 5 6
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT race, class, map, zone, position_x, position_y, position_z FROM playercreateinfo" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u player create definitions" , count );
sLog . outErrorDb ( "Error loading `playercreateinfo` table or empty table." );
exit ( 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_race = fields [ 0 ]. GetUInt32 ();
uint32 current_class = fields [ 1 ]. GetUInt32 ();
uint32 mapId = fields [ 2 ]. GetUInt32 ();
uint32 zoneId = fields [ 3 ]. GetUInt32 ();
float positionX = fields [ 4 ]. GetFloat ();
float positionY = fields [ 5 ]. GetFloat ();
float positionZ = fields [ 6 ]. GetFloat ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( current_race >= MAX_RACES )
{
sLog . outErrorDb ( "Wrong race %u in `playercreateinfo` table, ignoring." , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ChrRacesEntry const * rEntry = sChrRacesStore . LookupEntry ( current_race );
if ( ! rEntry )
{
sLog . outErrorDb ( "Wrong race %u in `playercreateinfo` table, ignoring." , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( current_class >= MAX_CLASSES )
{
sLog . outErrorDb ( "Wrong class %u in `playercreateinfo` table, ignoring." , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! sChrClassesStore . LookupEntry ( current_class ))
{
sLog . outErrorDb ( "Wrong class %u in `playercreateinfo` table, ignoring." , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// accept DB data only for valid position (and non instanceable)
if ( ! MapManager :: IsValidMapCoord ( mapId , positionX , positionY , positionZ ) )
{
sLog . outErrorDb ( "Wrong home position for class %u race %u pair in `playercreateinfo` table, ignoring." , current_class , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( sMapStore . LookupEntry ( mapId ) -> Instanceable () )
{
sLog . outErrorDb ( "Home position in instanceable map for class %u race %u pair in `playercreateinfo` table, ignoring." , current_class , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerInfo * pInfo = & playerInfo [ current_race ][ current_class ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pInfo -> mapId = mapId ;
pInfo -> zoneId = zoneId ;
pInfo -> positionX = positionX ;
pInfo -> positionY = positionY ;
pInfo -> positionZ = positionZ ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pInfo -> displayId_m = rEntry -> model_m ;
pInfo -> displayId_f = rEntry -> model_f ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u player create definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Load playercreate items
2010-01-01 14:19:29 -06:00
sLog . outString ( "Loading Player Create Items Data..." );
2008-10-11 14:16:25 -05:00
{
// 0 1 2 3
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT race, class, itemid, amount FROM playercreateinfo_item" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-12-22 10:59:38 -06:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-11-28 11:38:28 -06:00
sLog . outString ( ">> Loaded %u custom player create items" , count );
2008-10-11 14:16:25 -05:00
}
else
{
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_race = fields [ 0 ]. GetUInt32 ();
if ( current_race >= MAX_RACES )
{
sLog . outErrorDb ( "Wrong race %u in `playercreateinfo_item` table, ignoring." , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_class = fields [ 1 ]. GetUInt32 ();
if ( current_class >= MAX_CLASSES )
{
sLog . outErrorDb ( "Wrong class %u in `playercreateinfo_item` table, ignoring." , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerInfo * pInfo = & playerInfo [ current_race ][ current_class ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 item_id = fields [ 2 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! GetItemPrototype ( item_id ))
{
sLog . outErrorDb ( "Item id %u (race %u class %u) in `playercreateinfo_item` table but not listed in `item_template`, ignoring." , item_id , current_race , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 amount = fields [ 3 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! amount )
{
sLog . outErrorDb ( "Item id %u (class %u race %u) have amount==0 in `playercreateinfo_item` table, ignoring." , item_id , current_race , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pInfo -> item . push_back ( PlayerCreateInfoItem ( item_id , amount ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-11-28 11:38:28 -06:00
sLog . outString ( ">> Loaded %u custom player create items" , count );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Load playercreate spells
2010-01-01 14:19:29 -06:00
sLog . outString ( "Loading Player Create Spell Data..." );
2008-10-11 14:16:25 -05:00
{
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = QueryResult_AutoPtr ( NULL );
2008-10-14 11:57:03 -05:00
if ( sWorld . getConfig ( CONFIG_START_ALL_SPELLS ))
result = WorldDatabase . Query ( "SELECT race, class, Spell, Active FROM playercreateinfo_spell_custom" );
else
2009-01-12 10:53:53 -06:00
result = WorldDatabase . Query ( "SELECT race, class, Spell FROM playercreateinfo_spell" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u player create spells" , count );
sLog . outErrorDb ( "Error loading player starting spells or empty table." );
}
else
{
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_race = fields [ 0 ]. GetUInt32 ();
if ( current_race >= MAX_RACES )
{
sLog . outErrorDb ( "Wrong race %u in `playercreateinfo_spell` table, ignoring." , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_class = fields [ 1 ]. GetUInt32 ();
if ( current_class >= MAX_CLASSES )
{
sLog . outErrorDb ( "Wrong class %u in `playercreateinfo_spell` table, ignoring." , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-05-30 00:09:50 -05:00
if ( ! current_race || ! current_class )
{
uint32 min_race = current_race ? current_race : 1 ;
uint32 max_race = current_race ? current_race + 1 : MAX_RACES ;
uint32 min_class = current_class ? current_class : 1 ;
uint32 max_class = current_class ? current_class + 1 : MAX_CLASSES ;
2009-10-17 16:20:24 -07:00
for ( uint32 r = min_race ; r < max_race ; ++ r )
for ( uint32 c = min_class ; c < max_class ; ++ c )
2009-05-30 00:09:50 -05:00
playerInfo [ r ][ c ]. spell . push_back ( fields [ 2 ]. GetUInt32 ());
}
else
playerInfo [ current_race ][ current_class ]. spell . push_back ( fields [ 2 ]. GetUInt32 ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
}
while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u player create spells" , count );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Load playercreate actions
2010-01-01 14:19:29 -06:00
sLog . outString ( "Loading Player Create Action Data..." );
2008-10-11 14:16:25 -05:00
{
2009-07-01 18:07:20 -05:00
// 0 1 2 3 4
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT race, class, button, action, type FROM playercreateinfo_action" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u player create actions" , count );
sLog . outErrorDb ( "Error loading `playercreateinfo_action` table or empty table." );
}
else
{
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_race = fields [ 0 ]. GetUInt32 ();
if ( current_race >= MAX_RACES )
{
sLog . outErrorDb ( "Wrong race %u in `playercreateinfo_action` table, ignoring." , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_class = fields [ 1 ]. GetUInt32 ();
if ( current_class >= MAX_CLASSES )
{
sLog . outErrorDb ( "Wrong class %u in `playercreateinfo_action` table, ignoring." , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerInfo * pInfo = & playerInfo [ current_race ][ current_class ];
2009-07-01 18:07:20 -05:00
pInfo -> action . push_back ( PlayerCreateInfoAction ( fields [ 2 ]. GetUInt8 (), fields [ 3 ]. GetUInt32 (), fields [ 4 ]. GetUInt8 ()));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
}
while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u player create actions" , count );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Loading levels data (class only dependent)
2010-01-01 14:19:29 -06:00
sLog . outString ( "Loading Player Create Level HP/Mana Data..." );
2008-10-11 14:16:25 -05:00
{
// 0 1 2 3
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT class, level, basehp, basemana FROM player_classlevelstats" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u level health/mana definitions" , count );
sLog . outErrorDb ( "Error loading `player_classlevelstats` table or empty table." );
exit ( 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_class = fields [ 0 ]. GetUInt32 ();
if ( current_class >= MAX_CLASSES )
{
sLog . outErrorDb ( "Wrong class %u in `player_classlevelstats` table, ignoring." , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
uint8 current_level = fields [ 1 ]. GetUInt8 ();
2008-10-11 14:16:25 -05:00
if ( current_level > sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ))
{
2008-12-19 16:05:13 -06:00
if ( current_level > STRONG_MAX_LEVEL ) // hardcoded level maximum
sLog . outErrorDb ( "Wrong (> %u) level %u in `player_classlevelstats` table, ignoring." , STRONG_MAX_LEVEL , current_level );
2008-10-11 14:16:25 -05:00
else
2009-03-09 16:38:53 -06:00
{
2008-10-14 11:57:03 -05:00
sLog . outDetail ( "Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_classlevelstats` table, ignoring." , current_level );
2009-03-09 16:38:53 -06:00
++ count ; // make result loading percent "expected" correct in case disabled detail mode for example.
}
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerClassInfo * pClassInfo = & playerClassInfo [ current_class ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! pClassInfo -> levelInfo )
pClassInfo -> levelInfo = new PlayerClassLevelInfo [ sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL )];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerClassLevelInfo * pClassLevelInfo = & pClassInfo -> levelInfo [ current_level - 1 ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pClassLevelInfo -> basehealth = fields [ 2 ]. GetUInt16 ();
pClassLevelInfo -> basemana = fields [ 3 ]. GetUInt16 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u level health/mana definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Fill gaps and check integrity
for ( int class_ = 0 ; class_ < MAX_CLASSES ; ++ class_ )
{
// skip non existed classes
if ( ! sChrClassesStore . LookupEntry ( class_ ))
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerClassInfo * pClassInfo = & playerClassInfo [ class_ ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fatal error if no level 1 data
if ( ! pClassInfo -> levelInfo || pClassInfo -> levelInfo [ 0 ]. basehealth == 0 )
{
sLog . outErrorDb ( "Class %i Level 1 does not have health/mana data!" , class_ );
exit ( 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fill level gaps
2009-11-01 17:53:07 -08:00
for ( uint8 level = 1 ; level < sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ); ++ level )
2008-10-11 14:16:25 -05:00
{
if ( pClassInfo -> levelInfo [ level ]. basehealth == 0 )
{
sLog . outErrorDb ( "Class %i Level %i does not have health/mana data. Using stats data of level %i." , class_ , level + 1 , level );
pClassInfo -> levelInfo [ level ] = pClassInfo -> levelInfo [ level - 1 ];
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Loading levels data (class/race dependent)
2010-01-01 14:19:29 -06:00
sLog . outString ( "Loading Player Create Level Stats Data..." );
2008-10-11 14:16:25 -05:00
{
// 0 1 2 3 4 5 6 7
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT race, class, level, str, agi, sta, inte, spi FROM player_levelstats" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u level stats definitions" , count );
sLog . outErrorDb ( "Error loading `player_levelstats` table or empty table." );
exit ( 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_race = fields [ 0 ]. GetUInt32 ();
if ( current_race >= MAX_RACES )
{
sLog . outErrorDb ( "Wrong race %u in `player_levelstats` table, ignoring." , current_race );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_class = fields [ 1 ]. GetUInt32 ();
if ( current_class >= MAX_CLASSES )
{
sLog . outErrorDb ( "Wrong class %u in `player_levelstats` table, ignoring." , current_class );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 current_level = fields [ 2 ]. GetUInt32 ();
if ( current_level > sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ))
{
2008-12-19 16:05:13 -06:00
if ( current_level > STRONG_MAX_LEVEL ) // hardcoded level maximum
sLog . outErrorDb ( "Wrong (> %u) level %u in `player_levelstats` table, ignoring." , STRONG_MAX_LEVEL , current_level );
2008-10-11 14:16:25 -05:00
else
2009-03-09 16:38:53 -06:00
{
2008-10-14 11:57:03 -05:00
sLog . outDetail ( "Unused (> MaxPlayerLevel in Trinityd.conf) level %u in `player_levelstats` table, ignoring." , current_level );
2009-03-09 16:38:53 -06:00
++ count ; // make result loading percent "expected" correct in case disabled detail mode for example.
}
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerInfo * pInfo = & playerInfo [ current_race ][ current_class ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! pInfo -> levelInfo )
pInfo -> levelInfo = new PlayerLevelInfo [ sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL )];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerLevelInfo * pLevelInfo = & pInfo -> levelInfo [ current_level - 1 ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
for ( int i = 0 ; i < MAX_STATS ; i ++ )
{
pLevelInfo -> stats [ i ] = fields [ i + 3 ]. GetUInt8 ();
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u level stats definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Fill gaps and check integrity
for ( int race = 0 ; race < MAX_RACES ; ++ race )
{
// skip non existed races
if ( ! sChrRacesStore . LookupEntry ( race ))
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
for ( int class_ = 0 ; class_ < MAX_CLASSES ; ++ class_ )
{
// skip non existed classes
if ( ! sChrClassesStore . LookupEntry ( class_ ))
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerInfo * pInfo = & playerInfo [ race ][ class_ ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// skip non loaded combinations
if ( ! pInfo -> displayId_m || ! pInfo -> displayId_f )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// skip expansion races if not playing with expansion
if ( sWorld . getConfig ( CONFIG_EXPANSION ) < 1 && ( race == RACE_BLOODELF || race == RACE_DRAENEI ))
continue ;
2009-10-17 15:51:44 -07:00
2008-10-20 12:23:56 -05:00
// skip expansion classes if not playing with expansion
if ( sWorld . getConfig ( CONFIG_EXPANSION ) < 2 && class_ == CLASS_DEATH_KNIGHT )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fatal error if no level 1 data
if ( ! pInfo -> levelInfo || pInfo -> levelInfo [ 0 ]. stats [ 0 ] == 0 )
{
sLog . outErrorDb ( "Race %i Class %i Level 1 does not have stats data!" , race , class_ );
exit ( 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fill level gaps
2009-11-01 17:53:07 -08:00
for ( uint8 level = 1 ; level < sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ); ++ level )
2008-10-11 14:16:25 -05:00
{
if ( pInfo -> levelInfo [ level ]. stats [ 0 ] == 0 )
{
sLog . outErrorDb ( "Race %i Class %i Level %i does not have stats data. Using stats data of level %i." , race , class_ , level + 1 , level );
pInfo -> levelInfo [ level ] = pInfo -> levelInfo [ level - 1 ];
}
}
}
}
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
// Loading xp per level data
2010-01-01 14:19:29 -06:00
sLog . outString ( "Loading Player Create XP Data..." );
2009-01-16 14:17:24 -06:00
{
mPlayerXPperLevel . resize ( sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ));
2009-11-01 17:53:07 -08:00
for ( uint8 level = 0 ; level < sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ); ++ level )
2009-01-16 14:17:24 -06:00
mPlayerXPperLevel [ level ] = 0 ;
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
// 0 1
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT lvl, xp_for_next_level FROM player_xp_for_level" );
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-16 14:17:24 -06:00
sLog . outString ( ">> Loaded %u xp for level definitions" , count );
sLog . outErrorDb ( "Error loading `player_xp_for_level` table or empty table." );
exit ( 1 );
}
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
uint32 current_level = fields [ 0 ]. GetUInt32 ();
uint32 current_xp = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
if ( current_level >= sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ))
{
if ( current_level > STRONG_MAX_LEVEL ) // hardcoded level maximum
sLog . outErrorDb ( "Wrong (> %u) level %u in `player_xp_for_level` table, ignoring." , STRONG_MAX_LEVEL , current_level );
else
2009-03-09 16:38:53 -06:00
{
2010-02-05 00:31:28 +01:00
sLog . outDetail ( "Unused (> MaxPlayerLevel in TrinityCore.conf) level %u in `player_xp_for_levels` table, ignoring." , current_level );
2009-03-09 16:38:53 -06:00
++ count ; // make result loading percent "expected" correct in case disabled detail mode for example.
}
2009-01-16 14:17:24 -06:00
continue ;
}
//PlayerXPperLevel
mPlayerXPperLevel [ current_level ] = current_xp ;
bar . step ();
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-16 14:17:24 -06:00
sLog . outString ( ">> Loaded %u xp for level definitions" , count );
}
2009-10-17 15:51:44 -07:00
2009-01-16 14:17:24 -06:00
// fill level gaps
2009-11-01 17:53:07 -08:00
for ( uint8 level = 1 ; level < sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ); ++ level )
2009-01-16 14:17:24 -06:00
{
2009-11-01 17:53:07 -08:00
if ( mPlayerXPperLevel [ level ] == 0 )
2009-01-16 14:17:24 -06:00
{
sLog . outErrorDb ( "Level %i does not have XP for level data. Using data of level [%i] + 100." , level + 1 , level );
mPlayerXPperLevel [ level ] = mPlayerXPperLevel [ level - 1 ] + 100 ;
}
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
void ObjectMgr :: GetPlayerClassLevelInfo ( uint32 class_ , uint8 level , PlayerClassLevelInfo * info ) const
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( level < 1 || class_ >= MAX_CLASSES )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerClassInfo const * pInfo = & playerClassInfo [ class_ ];
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( level > sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ))
2008-10-11 14:16:25 -05:00
level = sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* info = pInfo -> levelInfo [ level - 1 ];
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
void ObjectMgr :: GetPlayerLevelInfo ( uint32 race , uint32 class_ , uint8 level , PlayerLevelInfo * info ) const
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
if ( level < 1 || race >= MAX_RACES || class_ >= MAX_CLASSES )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PlayerInfo const * pInfo = & playerInfo [ race ][ class_ ];
2009-11-01 17:53:07 -08:00
if ( pInfo -> displayId_m == 0 || pInfo -> displayId_f == 0 )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( level <= sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ))
2008-10-11 14:16:25 -05:00
* info = pInfo -> levelInfo [ level - 1 ];
else
BuildPlayerLevelInfo ( race , class_ , level , info );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: BuildPlayerLevelInfo ( uint8 race , uint8 _class , uint8 level , PlayerLevelInfo * info ) const
{
// base data (last known level)
* info = playerInfo [ race ][ _class ]. levelInfo [ sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ) - 1 ];
2009-10-17 15:51:44 -07:00
2009-06-18 18:29:28 +02:00
// if conversion from uint32 to uint8 causes unexpected behaviour, change lvl to uint32
2009-10-17 16:20:24 -07:00
for ( uint8 lvl = sWorld . getConfig ( CONFIG_MAX_PLAYER_LEVEL ) - 1 ; lvl < level ; ++ lvl )
2008-10-11 14:16:25 -05:00
{
switch ( _class )
{
case CLASS_WARRIOR :
info -> stats [ STAT_STRENGTH ] += ( lvl > 23 ? 2 : ( lvl > 1 ? 1 : 0 ));
info -> stats [ STAT_STAMINA ] += ( lvl > 23 ? 2 : ( lvl > 1 ? 1 : 0 ));
info -> stats [ STAT_AGILITY ] += ( lvl > 36 ? 1 : ( lvl > 6 && ( lvl % 2 ) ? 1 : 0 ));
info -> stats [ STAT_INTELLECT ] += ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_SPIRIT ] += ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 );
break ;
case CLASS_PALADIN :
info -> stats [ STAT_STRENGTH ] += ( lvl > 3 ? 1 : 0 );
info -> stats [ STAT_STAMINA ] += ( lvl > 33 ? 2 : ( lvl > 1 ? 1 : 0 ));
info -> stats [ STAT_AGILITY ] += ( lvl > 38 ? 1 : ( lvl > 7 && ! ( lvl % 2 ) ? 1 : 0 ));
info -> stats [ STAT_INTELLECT ] += ( lvl > 6 && ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_SPIRIT ] += ( lvl > 7 ? 1 : 0 );
break ;
case CLASS_HUNTER :
info -> stats [ STAT_STRENGTH ] += ( lvl > 4 ? 1 : 0 );
info -> stats [ STAT_STAMINA ] += ( lvl > 4 ? 1 : 0 );
info -> stats [ STAT_AGILITY ] += ( lvl > 33 ? 2 : ( lvl > 1 ? 1 : 0 ));
info -> stats [ STAT_INTELLECT ] += ( lvl > 8 && ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_SPIRIT ] += ( lvl > 38 ? 1 : ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 ));
break ;
case CLASS_ROGUE :
info -> stats [ STAT_STRENGTH ] += ( lvl > 5 ? 1 : 0 );
info -> stats [ STAT_STAMINA ] += ( lvl > 4 ? 1 : 0 );
info -> stats [ STAT_AGILITY ] += ( lvl > 16 ? 2 : ( lvl > 1 ? 1 : 0 ));
info -> stats [ STAT_INTELLECT ] += ( lvl > 8 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_SPIRIT ] += ( lvl > 38 ? 1 : ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 ));
break ;
case CLASS_PRIEST :
info -> stats [ STAT_STRENGTH ] += ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_STAMINA ] += ( lvl > 5 ? 1 : 0 );
info -> stats [ STAT_AGILITY ] += ( lvl > 38 ? 1 : ( lvl > 8 && ( lvl % 2 ) ? 1 : 0 ));
info -> stats [ STAT_INTELLECT ] += ( lvl > 22 ? 2 : ( lvl > 1 ? 1 : 0 ));
info -> stats [ STAT_SPIRIT ] += ( lvl > 3 ? 1 : 0 );
break ;
case CLASS_SHAMAN :
info -> stats [ STAT_STRENGTH ] += ( lvl > 34 ? 1 : ( lvl > 6 && ( lvl % 2 ) ? 1 : 0 ));
info -> stats [ STAT_STAMINA ] += ( lvl > 4 ? 1 : 0 );
info -> stats [ STAT_AGILITY ] += ( lvl > 7 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_INTELLECT ] += ( lvl > 5 ? 1 : 0 );
info -> stats [ STAT_SPIRIT ] += ( lvl > 4 ? 1 : 0 );
break ;
case CLASS_MAGE :
info -> stats [ STAT_STRENGTH ] += ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_STAMINA ] += ( lvl > 5 ? 1 : 0 );
info -> stats [ STAT_AGILITY ] += ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_INTELLECT ] += ( lvl > 24 ? 2 : ( lvl > 1 ? 1 : 0 ));
info -> stats [ STAT_SPIRIT ] += ( lvl > 33 ? 2 : ( lvl > 2 ? 1 : 0 ));
break ;
case CLASS_WARLOCK :
info -> stats [ STAT_STRENGTH ] += ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_STAMINA ] += ( lvl > 38 ? 2 : ( lvl > 3 ? 1 : 0 ));
info -> stats [ STAT_AGILITY ] += ( lvl > 9 && ! ( lvl % 2 ) ? 1 : 0 );
info -> stats [ STAT_INTELLECT ] += ( lvl > 33 ? 2 : ( lvl > 2 ? 1 : 0 ));
info -> stats [ STAT_SPIRIT ] += ( lvl > 38 ? 2 : ( lvl > 3 ? 1 : 0 ));
break ;
case CLASS_DRUID :
info -> stats [ STAT_STRENGTH ] += ( lvl > 38 ? 2 : ( lvl > 6 && ( lvl % 2 ) ? 1 : 0 ));
info -> stats [ STAT_STAMINA ] += ( lvl > 32 ? 2 : ( lvl > 4 ? 1 : 0 ));
info -> stats [ STAT_AGILITY ] += ( lvl > 38 ? 2 : ( lvl > 8 && ( lvl % 2 ) ? 1 : 0 ));
info -> stats [ STAT_INTELLECT ] += ( lvl > 38 ? 3 : ( lvl > 4 ? 1 : 0 ));
info -> stats [ STAT_SPIRIT ] += ( lvl > 38 ? 3 : ( lvl > 5 ? 1 : 0 ));
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGuilds ()
{
2010-02-18 02:42:59 +01:00
Guild * newGuild ;
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2010-02-18 02:42:59 +01:00
// 0 1 2 3 4 5 6
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT guild.guildid,guild.name,leaderguid,EmblemStyle,EmblemColor,BorderStyle,BorderColor,"
// 7 8 9 10 11 12
"BackgroundColor,info,motd,createdate,BankMoney,COUNT(guild_bank_tab.guildid) "
"FROM guild LEFT JOIN guild_bank_tab ON guild.guildid = guild_bank_tab.guildid GROUP BY guild.guildid ORDER BY guildid ASC" );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u guild definitions" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2010-02-18 02:42:59 +01:00
// load guild ranks
// 0 1 2 3 4
QueryResult_AutoPtr guildRanksResult = CharacterDatabase . Query ( "SELECT guildid,rid,rname,rights,BankMoneyPerDay FROM guild_rank ORDER BY guildid ASC, rid ASC" );
// load guild members
// 0 1 2 3 4 5 6
QueryResult_AutoPtr guildMembersResult = CharacterDatabase . Query ( "SELECT guildid,guild_member.guid,rank,pnote,offnote,BankResetTimeMoney,BankRemMoney,"
// 7 8 9 10 11 12
"BankResetTimeTab0,BankRemSlotsTab0,BankResetTimeTab1,BankRemSlotsTab1,BankResetTimeTab2,BankRemSlotsTab2,"
// 13 14 15 16 17 18
"BankResetTimeTab3,BankRemSlotsTab3,BankResetTimeTab4,BankRemSlotsTab4,BankResetTimeTab5,BankRemSlotsTab5,"
// 19 20 21 22 23
"characters.name, characters.level, characters.class, characters.zone, characters.logout_time "
"FROM guild_member LEFT JOIN characters ON characters.guid = guild_member.guid ORDER BY guildid ASC" );
// load guild bank tab rights
// 0 1 2 3 4
QueryResult_AutoPtr guildBankTabRightsResult = CharacterDatabase . Query ( "SELECT guildid,TabId,rid,gbright,SlotPerDay FROM guild_bank_right ORDER BY guildid ASC, TabId ASC" );
2009-11-01 17:53:07 -08:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
2010-02-18 02:42:59 +01:00
//Field *fields = result->Fetch();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
2009-10-17 15:51:44 -07:00
2010-02-18 02:42:59 +01:00
newGuild = new Guild ;
if ( ! newGuild -> LoadGuildFromDB ( result ) ||
! newGuild -> LoadRanksFromDB ( guildRanksResult ) ||
! newGuild -> LoadMembersFromDB ( guildMembersResult ) ||
! newGuild -> LoadBankRightsFromDB ( guildBankTabRightsResult ) ||
! newGuild -> CheckGuildStructure ()
)
{
newGuild -> Disband ();
delete newGuild ;
2008-10-11 14:16:25 -05:00
continue ;
}
2010-02-18 16:54:45 -07:00
newGuild -> LoadGuildEventLogFromDB ();
newGuild -> LoadGuildBankEventLogFromDB ();
2010-02-18 02:42:59 +01:00
newGuild -> LoadGuildBankFromDB ();
AddGuild ( newGuild );
2009-10-17 15:51:44 -07:00
2010-02-15 14:30:12 +01:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-08-24 20:23:54 -05:00
//delete unused LogGuid records in guild_eventlog and guild_bank_eventlog table
//you can comment these lines if you don't plan to change CONFIG_GUILD_EVENT_LOG_COUNT and CONFIG_GUILD_BANK_EVENT_LOG_COUNT
CharacterDatabase . PQuery ( "DELETE FROM guild_eventlog WHERE LogGuid > '%u'" , sWorld . getConfig ( CONFIG_GUILD_EVENT_LOG_COUNT ));
CharacterDatabase . PQuery ( "DELETE FROM guild_bank_eventlog WHERE LogGuid > '%u'" , sWorld . getConfig ( CONFIG_GUILD_BANK_EVENT_LOG_COUNT ));
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u guild definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadArenaTeams ()
{
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2010-02-18 02:42:59 +01:00
// 0 1 2 3 4 5
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT arena_team.arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,"
// 6 7 8 9 10 11 12 13 14
"EmblemColor,BorderStyle,BorderColor, rating,games,wins,played,wins2,rank "
"FROM arena_team LEFT JOIN arena_team_stats ON arena_team.arenateamid = arena_team_stats.arenateamid ORDER BY arena_team.arenateamid ASC" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u arenateam definitions" , count );
return ;
}
2010-02-18 16:54:45 -07:00
// load arena_team members
QueryResult_AutoPtr arenaTeamMembersResult = CharacterDatabase . Query (
// 0 1 2 3 4 5 6 7 8
"SELECT arenateamid,member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class "
"FROM arena_team_member member LEFT JOIN characters chars on member.guid = chars.guid ORDER BY member.arenateamid ASC" );
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
++ count ;
2009-10-17 15:51:44 -07:00
2010-02-18 02:42:59 +01:00
ArenaTeam * newArenaTeam = new ArenaTeam ;
if ( ! newArenaTeam -> LoadArenaTeamFromDB ( result ) ||
! newArenaTeam -> LoadMembersFromDB ( arenaTeamMembersResult ))
2008-10-11 14:16:25 -05:00
{
2010-02-18 02:42:59 +01:00
newArenaTeam -> Disband ( NULL );
delete newArenaTeam ;
2008-10-11 14:16:25 -05:00
continue ;
}
2010-02-18 02:42:59 +01:00
AddArenaTeam ( newArenaTeam );
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u arenateam definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGroups ()
{
// -- loading groups --
Group * group = NULL ;
uint64 leaderGuid = 0 ;
uint32 count = 0 ;
2010-03-10 08:58:22 +01:00
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
2010-03-10 04:42:59 +01:00
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, isRaid, difficulty, raiddifficulty, leaderGuid FROM groups" );
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u group definitions" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
bar . step ();
Field * fields = result -> Fetch ();
++ count ;
2010-03-10 08:58:22 +01:00
leaderGuid = MAKE_NEW_GUID ( fields [ 14 ]. GetUInt32 (), 0 , HIGHGUID_PLAYER );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
group = new Group ;
if ( ! group -> LoadGroupFromDB ( leaderGuid , result , false ))
{
group -> Disband ();
delete group ;
continue ;
}
AddGroup ( group );
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u group definitions" , count );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// -- loading members --
count = 0 ;
group = NULL ;
leaderGuid = 0 ;
2010-03-10 04:42:59 +01:00
// 2 3 4 1 1
2010-03-10 16:00:17 +01:00
result = CharacterDatabase . Query ( "SELECT memberGuid, memberFlags, subgroup, leaderGuid FROM group_member ORDER BY leaderGuid" );
2008-10-11 14:16:25 -05:00
if ( ! result )
{
2009-04-27 18:42:35 -05:00
barGoLink bar2 ( 1 );
bar2 . step ();
2008-10-11 14:16:25 -05:00
}
else
{
2009-04-27 18:42:35 -05:00
barGoLink bar2 ( result -> GetRowCount () );
2008-10-11 14:16:25 -05:00
do
{
2009-04-27 18:42:35 -05:00
bar2 . step ();
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
count ++ ;
leaderGuid = MAKE_NEW_GUID ( fields [ 3 ]. GetUInt32 (), 0 , HIGHGUID_PLAYER );
if ( ! group || group -> GetLeaderGUID () != leaderGuid )
{
group = GetGroupByLeader ( leaderGuid );
if ( ! group )
{
sLog . outErrorDb ( "Incorrect entry in group_member table : no group with leader %d for member %d!" , fields [ 3 ]. GetUInt32 (), fields [ 0 ]. GetUInt32 ());
CharacterDatabase . PExecute ( "DELETE FROM group_member WHERE memberGuid = '%d'" , fields [ 0 ]. GetUInt32 ());
continue ;
}
}
2009-10-17 15:51:44 -07:00
2010-03-10 16:00:17 +01:00
if ( ! group -> LoadMemberFromDB ( fields [ 0 ]. GetUInt32 (), fields [ 1 ]. GetUInt8 (), fields [ 2 ]. GetUInt8 ()))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Incorrect entry in group_member table : member %d cannot be added to player %d's group!" , fields [ 0 ]. GetUInt32 (), fields [ 3 ]. GetUInt32 ());
CharacterDatabase . PExecute ( "DELETE FROM group_member WHERE memberGuid = '%d'" , fields [ 0 ]. GetUInt32 ());
}
} while ( result -> NextRow () );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// clean groups
// TODO: maybe delete from the DB before loading in this case
2009-11-20 19:11:28 -08:00
for ( GroupSet :: iterator itr = mGroupSet . begin (); itr != mGroupSet . end ();)
2008-10-11 14:16:25 -05:00
{
if (( * itr ) -> GetMembersCount () < 2 )
{
( * itr ) -> Disband ();
delete * itr ;
mGroupSet . erase ( itr ++ );
}
else
++ itr ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// -- loading instances --
count = 0 ;
group = NULL ;
leaderGuid = 0 ;
2008-11-05 20:10:19 -06:00
result = CharacterDatabase . Query (
2008-10-11 14:16:25 -05:00
// 0 1 2 3 4 5
"SELECT leaderGuid, map, instance, permanent, difficulty, resettime, "
// 6
"(SELECT COUNT(*) FROM character_instance WHERE guid = leaderGuid AND instance = group_instance.instance AND permanent = 1 LIMIT 1) "
"FROM group_instance LEFT JOIN instance ON instance = id ORDER BY leaderGuid"
);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
2009-04-27 18:42:35 -05:00
barGoLink bar2 ( 1 );
bar2 . step ();
2008-10-11 14:16:25 -05:00
}
else
{
2009-04-27 18:42:35 -05:00
barGoLink bar2 ( result -> GetRowCount () );
2008-10-11 14:16:25 -05:00
do
{
2009-04-27 18:42:35 -05:00
bar2 . step ();
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
count ++ ;
leaderGuid = MAKE_NEW_GUID ( fields [ 0 ]. GetUInt32 (), 0 , HIGHGUID_PLAYER );
if ( ! group || group -> GetLeaderGUID () != leaderGuid )
{
group = GetGroupByLeader ( leaderGuid );
if ( ! group )
{
sLog . outErrorDb ( "Incorrect entry in group_instance table : no group with leader %d" , fields [ 0 ]. GetUInt32 ());
continue ;
}
}
2009-10-17 15:51:44 -07:00
2009-03-18 20:41:49 -06:00
MapEntry const * mapEntry = sMapStore . LookupEntry ( fields [ 1 ]. GetUInt32 ());
if ( ! mapEntry || ! mapEntry -> IsDungeon ())
{
sLog . outErrorDb ( "Incorrect entry in group_instance table : no dungeon map %d" , fields [ 1 ]. GetUInt32 ());
continue ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
uint32 diff = fields [ 4 ]. GetUInt8 ();
if ( diff >= ( mapEntry -> IsRaid () ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY ))
{
sLog . outErrorDb ( "Wrong dungeon difficulty use in group_instance table: %d" , diff + 1 );
diff = 0 ; // default for both difficaly types
}
InstanceSave * save = sInstanceSaveManager . AddInstanceSave ( mapEntry -> MapID , fields [ 2 ]. GetUInt32 (), Difficulty ( diff ), ( time_t ) fields [ 5 ]. GetUInt64 (), ( fields [ 6 ]. GetUInt32 () == 0 ), true );
2008-10-11 14:16:25 -05:00
group -> BindToInstance ( save , fields [ 3 ]. GetBool (), true );
} while ( result -> NextRow () );
}
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u group-instance binds total" , count );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u group members total" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadQuests ()
{
// For reload case
2009-10-17 16:20:24 -07:00
for ( QuestMap :: const_iterator itr = mQuestTemplates . begin (); itr != mQuestTemplates . end (); ++ itr )
2008-10-11 14:16:25 -05:00
delete itr -> second ;
mQuestTemplates . clear ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mExclusiveQuestGroups . clear ();
2009-10-17 15:51:44 -07:00
2010-03-02 09:59:59 -07:00
// 0 1 2 3 4 5 6 7 8
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, Method, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue,"
2009-12-20 16:51:41 -07:00
// 9 10 11 12 13 14 15 16 17 18
"RepObjectiveFaction, RepObjectiveValue, RepObjectiveFaction2, RepObjectiveValue2, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime,"
2010-03-02 09:59:59 -07:00
// 19 20 21 22 23 24 25 26 27 28 29 30 31
2010-02-14 19:13:14 -07:00
"QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, RewXPId, SrcItemId, SrcItemCount, SrcSpell,"
2010-03-02 09:59:59 -07:00
// 32 33 34 35 36 37 38 39 40 41 42
"Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, CompletedText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4,"
// 43 44 45 46 47 48 49 50 51 52 53 54
2009-12-17 14:55:19 +01:00
"ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemId5, ReqItemId6, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4, ReqItemCount5, ReqItemCount6,"
2010-03-02 09:59:59 -07:00
// 55 56 57 58 59 60 61 62
2009-03-02 17:06:41 -06:00
"ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4,"
2010-03-02 09:59:59 -07:00
// 63 64 65 66 67 68 69 70
2008-10-11 14:16:25 -05:00
"ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4,"
2010-03-02 09:59:59 -07:00
// 71 72 73 74
2008-10-11 14:16:25 -05:00
"ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4,"
2010-03-02 09:59:59 -07:00
// 75 76 77 78 79 80
2009-02-17 16:41:45 +01:00
"RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6,"
2010-03-02 09:59:59 -07:00
// 81 82 83 84 85 86
2009-02-17 16:41:45 +01:00
"RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6,"
2010-03-02 09:59:59 -07:00
// 87 88 89 90 91 92 93 94
2008-10-11 14:16:25 -05:00
"RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4,"
2010-03-02 09:59:59 -07:00
// 95 96 97 98 99 100 101 102 103 104
2010-02-14 19:13:14 -07:00
"RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValueId1, RewRepValueId2, RewRepValueId3, RewRepValueId4, RewRepValueId5,"
2010-03-02 09:59:59 -07:00
// 105 106 107 108 109
2010-02-14 19:13:14 -07:00
"RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5,"
2010-03-02 09:59:59 -07:00
// 110 111 112 113 114 115 116 117 118 119 120 121
2010-02-14 19:13:14 -07:00
"RewHonorAddition, RewHonorMultiplier, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt,"
2010-03-02 09:59:59 -07:00
// 122 123 124 125 126 127 128 129
2009-06-03 19:23:49 -05:00
"DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4,"
2010-03-02 09:59:59 -07:00
// 130 131 132 133 134 135
2009-06-03 19:23:49 -05:00
"IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4,"
2010-03-02 09:59:59 -07:00
// 136 137 138 139
2009-06-03 19:23:49 -05:00
"OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4,"
2010-03-02 09:59:59 -07:00
// 140 141
2008-10-11 14:16:25 -05:00
"StartScript, CompleteScript"
" FROM quest_template" );
if ( result == NULL )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded 0 quests definitions" );
sLog . outErrorDb ( "`quest_template` table is empty!" );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// create multimap previous quest for each existed quest
// some quests can have many previous maps set by NextQuestId in previous quest
// for example set of race quests can lead to single not race specific quest
barGoLink bar ( result -> GetRowCount () );
do
{
bar . step ();
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Quest * newQuest = new Quest ( fields );
mQuestTemplates [ newQuest -> GetQuestId ()] = newQuest ;
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-12-18 13:41:30 -08:00
std :: map < uint32 , uint32 > usedMailTemplates ;
2009-12-16 18:58:36 +02:00
2008-10-11 14:16:25 -05:00
// Post processing
2008-12-08 16:34:03 -06:00
for ( QuestMap :: iterator iter = mQuestTemplates . begin (); iter != mQuestTemplates . end (); ++ iter )
2008-10-11 14:16:25 -05:00
{
Quest * qinfo = iter -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// additional quest integrity checks (GO, creature_template and item_template must be loaded already)
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> GetQuestMethod () >= 3 )
{
sLog . outErrorDb ( "Quest %u has `Method` = %u, expected values are 0, 1 or 2." , qinfo -> GetQuestId (), qinfo -> GetQuestMethod ());
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
if ( qinfo -> QuestFlags & ~ QUEST_TRINITY_FLAGS_DB_ALLOWED )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Quest %u has `SpecialFlags` = %u > max allowed value. Correct `SpecialFlags` to value <= %u" ,
2008-10-14 11:57:03 -05:00
qinfo -> GetQuestId (), qinfo -> QuestFlags , QUEST_TRINITY_FLAGS_DB_ALLOWED >> 16 );
qinfo -> QuestFlags &= QUEST_TRINITY_FLAGS_DB_ALLOWED ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-17 21:48:19 -05:00
if ( qinfo -> QuestFlags & ( QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY ))
2008-10-11 14:16:25 -05:00
{
2008-10-14 11:57:03 -05:00
if ( ! ( qinfo -> QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Daily Quest %u not marked as repeatable in `SpecialFlags`, added." , qinfo -> GetQuestId ());
2008-10-14 11:57:03 -05:00
qinfo -> QuestFlags |= QUEST_TRINITY_FLAGS_REPEATABLE ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> QuestFlags & QUEST_FLAGS_AUTO_REWARDED )
{
// at auto-reward can be rewarded only RewChoiceItemId[0]
2009-10-17 16:20:24 -07:00
for ( uint8 j = 1 ; j < QUEST_REWARD_CHOICES_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
if ( uint32 id = qinfo -> RewChoiceItemId [ j ])
{
sLog . outErrorDb ( "Quest %u has `RewChoiceItemId%d` = %u but item from `RewChoiceItemId%d` can't be rewarded with quest flag QUEST_FLAGS_AUTO_REWARDED." ,
qinfo -> GetQuestId (), j + 1 , id , j + 1 );
// no changes, quest ignore this data
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// client quest log visual (area case)
if ( qinfo -> ZoneOrSort > 0 )
{
if ( ! GetAreaEntryByAreaID ( qinfo -> ZoneOrSort ))
{
sLog . outErrorDb ( "Quest %u has `ZoneOrSort` = %u (zone case) but zone with this id does not exist." ,
qinfo -> GetQuestId (), qinfo -> ZoneOrSort );
// no changes, quest not dependent from this value but can have problems at client
}
}
// client quest log visual (sort case)
if ( qinfo -> ZoneOrSort < 0 )
{
QuestSortEntry const * qSort = sQuestSortStore . LookupEntry ( - int32 ( qinfo -> ZoneOrSort ));
if ( ! qSort )
{
sLog . outErrorDb ( "Quest %u has `ZoneOrSort` = %i (sort case) but quest sort with this id does not exist." ,
qinfo -> GetQuestId (), qinfo -> ZoneOrSort );
// no changes, quest not dependent from this value but can have problems at client (note some may be 0, we must allow this so no check)
}
//check SkillOrClass value (class case).
if ( ClassByQuestSort ( - int32 ( qinfo -> ZoneOrSort )) )
{
// SkillOrClass should not have class case when class case already set in ZoneOrSort.
if ( qinfo -> SkillOrClass < 0 )
{
sLog . outErrorDb ( "Quest %u has `ZoneOrSort` = %i (class sort case) and `SkillOrClass` = %i (class case), redundant." ,
qinfo -> GetQuestId (), qinfo -> ZoneOrSort , qinfo -> SkillOrClass );
}
}
//check for proper SkillOrClass value (skill case)
if ( int32 skill_id = SkillByQuestSort ( - int32 ( qinfo -> ZoneOrSort )))
{
// skill is positive value in SkillOrClass
if ( qinfo -> SkillOrClass != skill_id )
{
sLog . outErrorDb ( "Quest %u has `ZoneOrSort` = %i (skill sort case) but `SkillOrClass` does not have a corresponding value (%i)." ,
qinfo -> GetQuestId (), qinfo -> ZoneOrSort , skill_id );
//override, and force proper value here?
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// SkillOrClass (class case)
if ( qinfo -> SkillOrClass < 0 )
{
if ( ! sChrClassesStore . LookupEntry ( - int32 ( qinfo -> SkillOrClass )) )
{
sLog . outErrorDb ( "Quest %u has `SkillOrClass` = %i (class case) but class (%i) does not exist" ,
qinfo -> GetQuestId (), qinfo -> SkillOrClass , - qinfo -> SkillOrClass );
}
}
// SkillOrClass (skill case)
if ( qinfo -> SkillOrClass > 0 )
{
if ( ! sSkillLineStore . LookupEntry ( qinfo -> SkillOrClass ) )
{
sLog . outErrorDb ( "Quest %u has `SkillOrClass` = %u (skill case) but skill (%i) does not exist" ,
qinfo -> GetQuestId (), qinfo -> SkillOrClass , qinfo -> SkillOrClass );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> RequiredSkillValue )
{
if ( qinfo -> RequiredSkillValue > sWorld . GetConfigMaxSkillValue () )
{
sLog . outErrorDb ( "Quest %u has `RequiredSkillValue` = %u but max possible skill is %u, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> RequiredSkillValue , sWorld . GetConfigMaxSkillValue ());
// no changes, quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> SkillOrClass <= 0 )
{
sLog . outErrorDb ( "Quest %u has `RequiredSkillValue` = %u but `SkillOrClass` = %i (class case), value ignored." ,
qinfo -> GetQuestId (), qinfo -> RequiredSkillValue , qinfo -> SkillOrClass );
// no changes, quest can't be done for this requirement (fail at wrong skill id)
}
}
// else Skill quests can have 0 skill level, this is ok
2009-10-17 15:51:44 -07:00
2009-12-20 16:51:41 -07:00
if ( qinfo -> RepObjectiveFaction2 && ! sFactionStore . LookupEntry ( qinfo -> RepObjectiveFaction2 ))
{
sLog . outErrorDb ( "Quest %u has `RepObjectiveFaction2` = %u but faction template %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> RepObjectiveFaction2 , qinfo -> RepObjectiveFaction2 );
// no changes, quest can't be done for this requirement
}
2008-10-11 14:16:25 -05:00
if ( qinfo -> RepObjectiveFaction && ! sFactionStore . LookupEntry ( qinfo -> RepObjectiveFaction ))
{
sLog . outErrorDb ( "Quest %u has `RepObjectiveFaction` = %u but faction template %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> RepObjectiveFaction , qinfo -> RepObjectiveFaction );
// no changes, quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> RequiredMinRepFaction && ! sFactionStore . LookupEntry ( qinfo -> RequiredMinRepFaction ))
{
sLog . outErrorDb ( "Quest %u has `RequiredMinRepFaction` = %u but faction template %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> RequiredMinRepFaction , qinfo -> RequiredMinRepFaction );
// no changes, quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> RequiredMaxRepFaction && ! sFactionStore . LookupEntry ( qinfo -> RequiredMaxRepFaction ))
{
sLog . outErrorDb ( "Quest %u has `RequiredMaxRepFaction` = %u but faction template %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> RequiredMaxRepFaction , qinfo -> RequiredMaxRepFaction );
// no changes, quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2009-03-26 13:53:32 -06:00
if ( qinfo -> RequiredMinRepValue && qinfo -> RequiredMinRepValue > ReputationMgr :: Reputation_Cap )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Quest %u has `RequiredMinRepValue` = %d but max reputation is %u, quest can't be done." ,
2009-03-26 13:53:32 -06:00
qinfo -> GetQuestId (), qinfo -> RequiredMinRepValue , ReputationMgr :: Reputation_Cap );
2008-10-11 14:16:25 -05:00
// no changes, quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> RequiredMinRepValue && qinfo -> RequiredMaxRepValue && qinfo -> RequiredMaxRepValue <= qinfo -> RequiredMinRepValue )
{
sLog . outErrorDb ( "Quest %u has `RequiredMaxRepValue` = %d and `RequiredMinRepValue` = %d, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> RequiredMaxRepValue , qinfo -> RequiredMinRepValue );
// no changes, quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! qinfo -> RepObjectiveFaction && qinfo -> RepObjectiveValue > 0 )
{
sLog . outErrorDb ( "Quest %u has `RepObjectiveValue` = %d but `RepObjectiveFaction` is 0, value has no effect" ,
qinfo -> GetQuestId (), qinfo -> RepObjectiveValue );
// warning
}
2009-10-17 15:51:44 -07:00
2009-12-20 16:51:41 -07:00
if ( ! qinfo -> RepObjectiveFaction2 && qinfo -> RepObjectiveValue2 > 0 )
{
sLog . outErrorDb ( "Quest %u has `RepObjectiveValue2` = %d but `RepObjectiveFaction2` is 0, value has no effect" ,
qinfo -> GetQuestId (), qinfo -> RepObjectiveValue2 );
// warning
}
2008-10-11 14:16:25 -05:00
if ( ! qinfo -> RequiredMinRepFaction && qinfo -> RequiredMinRepValue > 0 )
{
sLog . outErrorDb ( "Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect" ,
qinfo -> GetQuestId (), qinfo -> RequiredMinRepValue );
// warning
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! qinfo -> RequiredMaxRepFaction && qinfo -> RequiredMaxRepValue > 0 )
{
sLog . outErrorDb ( "Quest %u has `RequiredMaxRepValue` = %d but `RequiredMaxRepFaction` is 0, value has no effect" ,
qinfo -> GetQuestId (), qinfo -> RequiredMaxRepValue );
// warning
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> CharTitleId && ! sCharTitlesStore . LookupEntry ( qinfo -> CharTitleId ))
{
sLog . outErrorDb ( "Quest %u has `CharTitleId` = %u but CharTitle Id %u does not exist, quest can't be rewarded with title." ,
qinfo -> GetQuestId (), qinfo -> GetCharTitleId (), qinfo -> GetCharTitleId ());
qinfo -> CharTitleId = 0 ;
// quest can't reward this title
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> SrcItemId )
{
if ( ! sItemStorage . LookupEntry < ItemPrototype > ( qinfo -> SrcItemId ))
{
sLog . outErrorDb ( "Quest %u has `SrcItemId` = %u but item with entry %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> SrcItemId , qinfo -> SrcItemId );
qinfo -> SrcItemId = 0 ; // quest can't be done for this requirement
}
else if ( qinfo -> SrcItemCount == 0 )
{
sLog . outErrorDb ( "Quest %u has `SrcItemId` = %u but `SrcItemCount` = 0, set to 1 but need fix in DB." ,
qinfo -> GetQuestId (), qinfo -> SrcItemId );
2008-11-14 16:28:45 -06:00
qinfo -> SrcItemCount = 1 ; // update to 1 for allow quest work for backward compatibility with DB
2008-10-11 14:16:25 -05:00
}
}
else if ( qinfo -> SrcItemCount > 0 )
{
sLog . outErrorDb ( "Quest %u has `SrcItemId` = 0 but `SrcItemCount` = %u, useless value." ,
qinfo -> GetQuestId (), qinfo -> SrcItemCount );
qinfo -> SrcItemCount = 0 ; // no quest work changes in fact
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> SrcSpell )
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( qinfo -> SrcSpell );
if ( ! spellInfo )
{
sLog . outErrorDb ( "Quest %u has `SrcSpell` = %u but spell %u doesn't exist, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> SrcSpell , qinfo -> SrcSpell );
qinfo -> SrcSpell = 0 ; // quest can't be done for this requirement
}
else if ( ! SpellMgr :: IsSpellValid ( spellInfo ))
{
sLog . outErrorDb ( "Quest %u has `SrcSpell` = %u but spell %u is broken, quest can't be done." ,
qinfo -> GetQuestId (), qinfo -> SrcSpell , qinfo -> SrcSpell );
qinfo -> SrcSpell = 0 ; // quest can't be done for this requirement
}
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:55:19 +01:00
for ( uint8 j = 0 ; j < QUEST_ITEM_OBJECTIVES_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
uint32 id = qinfo -> ReqItemId [ j ];
if ( id )
{
if ( qinfo -> ReqItemCount [ j ] == 0 )
{
sLog . outErrorDb ( "Quest %u has `ReqItemId%d` = %u but `ReqItemCount%d` = 0, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , j + 1 );
// no changes, quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
qinfo -> SetFlag ( QUEST_TRINITY_FLAGS_DELIVER );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! sItemStorage . LookupEntry < ItemPrototype > ( id ))
{
sLog . outErrorDb ( "Quest %u has `ReqItemId%d` = %u but item with entry %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , id );
qinfo -> ReqItemCount [ j ] = 0 ; // prevent incorrect work of quest
}
}
else if ( qinfo -> ReqItemCount [ j ] > 0 )
{
sLog . outErrorDb ( "Quest %u has `ReqItemId%d` = 0 but `ReqItemCount%d` = %u, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , j + 1 , qinfo -> ReqItemCount [ j ]);
qinfo -> ReqItemCount [ j ] = 0 ; // prevent incorrect work of quest
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < QUEST_SOURCE_ITEM_IDS_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
uint32 id = qinfo -> ReqSourceId [ j ];
if ( id )
{
if ( ! sItemStorage . LookupEntry < ItemPrototype > ( id ))
{
sLog . outErrorDb ( "Quest %u has `ReqSourceId%d` = %u but item with entry %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , id );
// no changes, quest can't be done for this requirement
}
}
else
{
if ( qinfo -> ReqSourceCount [ j ] > 0 )
{
sLog . outErrorDb ( "Quest %u has `ReqSourceId%d` = 0 but `ReqSourceCount%d` = %u." ,
qinfo -> GetQuestId (), j + 1 , j + 1 , qinfo -> ReqSourceCount [ j ]);
// no changes, quest ignore this data
}
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < QUEST_OBJECTIVES_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
uint32 id = qinfo -> ReqSpell [ j ];
if ( id )
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( id );
if ( ! spellInfo )
{
sLog . outErrorDb ( "Quest %u has `ReqSpellCast%d` = %u but spell %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , id );
2009-04-27 18:42:35 -05:00
continue ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! qinfo -> ReqCreatureOrGOId [ j ])
{
bool found = false ;
2009-10-17 16:20:24 -07:00
for ( uint8 k = 0 ; k < 3 ; ++ k )
2008-10-11 14:16:25 -05:00
{
2009-09-18 14:10:37 -07:00
if (( spellInfo -> Effect [ k ] == SPELL_EFFECT_QUEST_COMPLETE && uint32 ( spellInfo -> EffectMiscValue [ k ]) == qinfo -> QuestId ) ||
spellInfo -> Effect [ k ] == SPELL_EFFECT_SEND_EVENT )
2008-10-11 14:16:25 -05:00
{
found = true ;
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( found )
{
2008-10-14 11:57:03 -05:00
if ( ! qinfo -> HasFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT ))
2008-10-11 14:16:25 -05:00
{
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and ReqCreatureOrGOId%d = 0, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags or ReqCreatureOrGOId%d must be fixed, quest modified to enable objective." , spellInfo -> Id , qinfo -> QuestId , j + 1 , j + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// this will prevent quest completing without objective
2008-10-14 11:57:03 -05:00
const_cast < Quest *> ( qinfo ) -> SetFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT );
2008-10-11 14:16:25 -05:00
}
}
else
{
sLog . outErrorDb ( "Quest %u has `ReqSpellCast%d` = %u and ReqCreatureOrGOId%d = 0 but spell %u does not have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT effect for this quest, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , j + 1 , id );
// no changes, quest can't be done for this requirement
}
}
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < QUEST_OBJECTIVES_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
int32 id = qinfo -> ReqCreatureOrGOId [ j ];
if ( id < 0 && ! sGOStorage . LookupEntry < GameObjectInfo > ( - id ))
{
sLog . outErrorDb ( "Quest %u has `ReqCreatureOrGOId%d` = %i but gameobject %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , uint32 ( - id ));
qinfo -> ReqCreatureOrGOId [ j ] = 0 ; // quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( id > 0 && ! sCreatureStorage . LookupEntry < CreatureInfo > ( id ))
{
sLog . outErrorDb ( "Quest %u has `ReqCreatureOrGOId%d` = %i but creature with entry %u does not exist, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , uint32 ( id ));
qinfo -> ReqCreatureOrGOId [ j ] = 0 ; // quest can't be done for this requirement
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( id )
{
// In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
qinfo -> SetFlag ( QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! qinfo -> ReqCreatureOrGOCount [ j ])
{
sLog . outErrorDb ( "Quest %u has `ReqCreatureOrGOId%d` = %u but `ReqCreatureOrGOCount%d` = 0, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , j + 1 );
// no changes, quest can be incorrectly done, but we already report this
}
}
else if ( qinfo -> ReqCreatureOrGOCount [ j ] > 0 )
{
sLog . outErrorDb ( "Quest %u has `ReqCreatureOrGOId%d` = 0 but `ReqCreatureOrGOCount%d` = %u." ,
qinfo -> GetQuestId (), j + 1 , j + 1 , qinfo -> ReqCreatureOrGOCount [ j ]);
// no changes, quest ignore this data
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < QUEST_REWARD_CHOICES_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
uint32 id = qinfo -> RewChoiceItemId [ j ];
if ( id )
{
if ( ! sItemStorage . LookupEntry < ItemPrototype > ( id ))
{
sLog . outErrorDb ( "Quest %u has `RewChoiceItemId%d` = %u but item with entry %u does not exist, quest will not reward this item." ,
qinfo -> GetQuestId (), j + 1 , id , id );
qinfo -> RewChoiceItemId [ j ] = 0 ; // no changes, quest will not reward this
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! qinfo -> RewChoiceItemCount [ j ])
{
sLog . outErrorDb ( "Quest %u has `RewChoiceItemId%d` = %u but `RewChoiceItemCount%d` = 0, quest can't be done." ,
qinfo -> GetQuestId (), j + 1 , id , j + 1 );
// no changes, quest can't be done
}
}
else if ( qinfo -> RewChoiceItemCount [ j ] > 0 )
{
sLog . outErrorDb ( "Quest %u has `RewChoiceItemId%d` = 0 but `RewChoiceItemCount%d` = %u." ,
qinfo -> GetQuestId (), j + 1 , j + 1 , qinfo -> RewChoiceItemCount [ j ]);
// no changes, quest ignore this data
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < QUEST_REWARDS_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
uint32 id = qinfo -> RewItemId [ j ];
if ( id )
{
if ( ! sItemStorage . LookupEntry < ItemPrototype > ( id ))
{
sLog . outErrorDb ( "Quest %u has `RewItemId%d` = %u but item with entry %u does not exist, quest will not reward this item." ,
qinfo -> GetQuestId (), j + 1 , id , id );
qinfo -> RewItemId [ j ] = 0 ; // no changes, quest will not reward this item
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! qinfo -> RewItemCount [ j ])
{
sLog . outErrorDb ( "Quest %u has `RewItemId%d` = %u but `RewItemCount%d` = 0, quest will not reward this item." ,
qinfo -> GetQuestId (), j + 1 , id , j + 1 );
// no changes
}
}
else if ( qinfo -> RewItemCount [ j ] > 0 )
{
sLog . outErrorDb ( "Quest %u has `RewItemId%d` = 0 but `RewItemCount%d` = %u." ,
qinfo -> GetQuestId (), j + 1 , j + 1 , qinfo -> RewItemCount [ j ]);
// no changes, quest ignore this data
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < QUEST_REPUTATIONS_COUNT ; ++ j )
2008-10-11 14:16:25 -05:00
{
2010-02-14 19:13:14 -07:00
if ( qinfo -> RewRepFaction [ j ])
2008-10-11 14:16:25 -05:00
{
2010-02-14 19:13:14 -07:00
if ( abs ( qinfo -> RewRepValueId [ j ]) > 9 )
2008-10-11 14:16:25 -05:00
{
2010-02-14 19:13:14 -07:00
sLog . outErrorDb ( "Quest %u has RewRepValueId%d = %i. That is outside the range of valid values (-9 to 9)." , qinfo -> GetQuestId (), j + 1 , qinfo -> RewRepValueId [ j ]);
2008-10-11 14:16:25 -05:00
}
if ( ! sFactionStore . LookupEntry ( qinfo -> RewRepFaction [ j ]))
{
2010-02-14 19:13:14 -07:00
sLog . outErrorDb ( "Quest %u has `RewRepFaction%d` = %u but raw faction (faction.dbc) %u does not exist, quest will not reward reputation for this faction." , qinfo -> GetQuestId (), j + 1 , qinfo -> RewRepFaction [ j ] , qinfo -> RewRepFaction [ j ] );
2008-10-11 14:16:25 -05:00
qinfo -> RewRepFaction [ j ] = 0 ; // quest will not reward this
}
2010-02-14 19:13:14 -07:00
}
2008-10-11 14:16:25 -05:00
else if ( qinfo -> RewRepValue [ j ] != 0 )
{
2010-02-14 19:13:14 -07:00
sLog . outErrorDb ( "Quest %u has `RewRepFaction%d` = 0 but `RewRepValue%d` = %i." ,
2008-10-11 14:16:25 -05:00
qinfo -> GetQuestId (), j + 1 , j + 1 , qinfo -> RewRepValue [ j ]);
// no changes, quest ignore this data
}
}
2009-10-17 15:51:44 -07:00
2010-02-14 19:13:14 -07:00
2008-10-11 14:16:25 -05:00
if ( qinfo -> RewSpell )
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( qinfo -> RewSpell );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! spellInfo )
{
sLog . outErrorDb ( "Quest %u has `RewSpell` = %u but spell %u does not exist, spell removed as display reward." ,
qinfo -> GetQuestId (), qinfo -> RewSpell , qinfo -> RewSpell );
qinfo -> RewSpell = 0 ; // no spell reward will display for this quest
}
2009-10-17 15:51:44 -07:00
2009-09-18 14:10:37 -07:00
else if ( ! SpellMgr :: IsSpellValid ( spellInfo ))
2008-10-11 14:16:25 -05:00
{
2009-07-01 18:07:57 -05:00
sLog . outErrorDb ( "Quest %u has `RewSpell` = %u but spell %u is broken, quest will not have a spell reward." ,
2008-10-11 14:16:25 -05:00
qinfo -> GetQuestId (), qinfo -> RewSpell , qinfo -> RewSpell );
qinfo -> RewSpell = 0 ; // no spell reward will display for this quest
}
2009-10-17 15:51:44 -07:00
2009-09-18 14:10:37 -07:00
else if ( GetTalentSpellCost ( qinfo -> RewSpell ))
2009-07-01 18:07:57 -05:00
{
sLog . outErrorDb ( "Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward." ,
qinfo -> GetQuestId (), qinfo -> RewSpell , qinfo -> RewSpell );
qinfo -> RewSpell = 0 ; // no spell reward will display for this quest
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-01-29 12:54:30 -07:00
if ( qinfo -> RewSpellCast > 0 )
2008-10-11 14:16:25 -05:00
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( qinfo -> RewSpellCast );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! spellInfo )
{
sLog . outErrorDb ( "Quest %u has `RewSpellCast` = %u but spell %u does not exist, quest will not have a spell reward." ,
qinfo -> GetQuestId (), qinfo -> RewSpellCast , qinfo -> RewSpellCast );
qinfo -> RewSpellCast = 0 ; // no spell will be casted on player
}
2009-10-17 15:51:44 -07:00
2009-09-18 14:10:37 -07:00
else if ( ! SpellMgr :: IsSpellValid ( spellInfo ))
2008-10-11 14:16:25 -05:00
{
2009-07-01 18:07:57 -05:00
sLog . outErrorDb ( "Quest %u has `RewSpellCast` = %u but spell %u is broken, quest will not have a spell reward." ,
2008-10-11 14:16:25 -05:00
qinfo -> GetQuestId (), qinfo -> RewSpellCast , qinfo -> RewSpellCast );
qinfo -> RewSpellCast = 0 ; // no spell will be casted on player
}
2009-10-17 15:51:44 -07:00
2009-09-18 14:10:37 -07:00
else if ( GetTalentSpellCost ( qinfo -> RewSpellCast ))
2009-07-01 18:07:57 -05:00
{
sLog . outErrorDb ( "Quest %u has `RewSpell` = %u but spell %u is talent, quest will not have a spell reward." ,
qinfo -> GetQuestId (), qinfo -> RewSpellCast , qinfo -> RewSpellCast );
qinfo -> RewSpellCast = 0 ; // no spell will be casted on player
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
if ( qinfo -> RewMailTemplateId )
2008-10-11 14:16:25 -05:00
{
2009-12-16 18:58:36 +02:00
if ( ! sMailTemplateStore . LookupEntry ( qinfo -> RewMailTemplateId ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Quest %u has `RewMailTemplateId` = %u but mail template %u does not exist, quest will not have a mail reward." ,
qinfo -> GetQuestId (), qinfo -> RewMailTemplateId , qinfo -> RewMailTemplateId );
qinfo -> RewMailTemplateId = 0 ; // no mail will send to player
qinfo -> RewMailDelaySecs = 0 ; // no mail will send to player
}
2009-12-16 18:58:36 +02:00
else if ( usedMailTemplates . find ( qinfo -> RewMailTemplateId ) != usedMailTemplates . end ())
{
std :: map < uint32 , uint32 >:: const_iterator used_mt_itr = usedMailTemplates . find ( qinfo -> RewMailTemplateId );
sLog . outErrorDb ( "Quest %u has `RewMailTemplateId` = %u but mail template %u already used for quest %u, quest will not have a mail reward." ,
qinfo -> GetQuestId (), qinfo -> RewMailTemplateId , qinfo -> RewMailTemplateId , used_mt_itr -> second );
qinfo -> RewMailTemplateId = 0 ; // no mail will send to player
qinfo -> RewMailDelaySecs = 0 ; // no mail will send to player
}
else
usedMailTemplates [ qinfo -> RewMailTemplateId ] = qinfo -> GetQuestId ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
if ( qinfo -> NextQuestInChain )
2008-10-11 14:16:25 -05:00
{
2009-03-09 17:40:40 -06:00
QuestMap :: iterator qNextItr = mQuestTemplates . find ( qinfo -> NextQuestInChain );
2009-12-17 14:55:19 +01:00
if ( qNextItr == mQuestTemplates . end ())
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Quest %u has `NextQuestInChain` = %u but quest %u does not exist, quest chain will not work." ,
qinfo -> GetQuestId (), qinfo -> NextQuestInChain , qinfo -> NextQuestInChain );
qinfo -> NextQuestInChain = 0 ;
}
else
2009-03-09 17:40:40 -06:00
qNextItr -> second -> prevChainQuests . push_back ( qinfo -> GetQuestId ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// fill additional data stores
2009-12-17 14:55:19 +01:00
if ( qinfo -> PrevQuestId )
2008-10-11 14:16:25 -05:00
{
if ( mQuestTemplates . find ( abs ( qinfo -> GetPrevQuestId ())) == mQuestTemplates . end ())
{
sLog . outErrorDb ( "Quest %d has PrevQuestId %i, but no such quest" , qinfo -> GetQuestId (), qinfo -> GetPrevQuestId ());
}
else
{
qinfo -> prevQuests . push_back ( qinfo -> PrevQuestId );
}
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:55:19 +01:00
if ( qinfo -> NextQuestId )
2008-10-11 14:16:25 -05:00
{
2009-03-09 17:40:40 -06:00
QuestMap :: iterator qNextItr = mQuestTemplates . find ( abs ( qinfo -> GetNextQuestId ()));
if ( qNextItr == mQuestTemplates . end ())
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Quest %d has NextQuestId %i, but no such quest" , qinfo -> GetQuestId (), qinfo -> GetNextQuestId ());
}
else
{
int32 signedQuestId = qinfo -> NextQuestId < 0 ? - int32 ( qinfo -> GetQuestId ()) : int32 ( qinfo -> GetQuestId ());
2009-03-09 17:40:40 -06:00
qNextItr -> second -> prevQuests . push_back ( signedQuestId );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-12-17 14:55:19 +01:00
if ( qinfo -> ExclusiveGroup )
2008-10-11 14:16:25 -05:00
mExclusiveQuestGroups . insert ( std :: pair < int32 , uint32 > ( qinfo -> ExclusiveGroup , qinfo -> GetQuestId ()));
2009-12-17 14:55:19 +01:00
if ( qinfo -> LimitTime )
2008-10-14 11:57:03 -05:00
qinfo -> SetFlag ( QUEST_TRINITY_FLAGS_TIMED );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
// check QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
2008-10-11 14:16:25 -05:00
for ( uint32 i = 0 ; i < sSpellStore . GetNumRows (); ++ i )
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( i );
if ( ! spellInfo )
continue ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < 3 ; ++ j )
2008-10-11 14:16:25 -05:00
{
if ( spellInfo -> Effect [ j ] != SPELL_EFFECT_QUEST_COMPLETE )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 quest_id = spellInfo -> EffectMiscValue [ j ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Quest const * quest = GetQuestTemplate ( quest_id );
2009-10-17 15:51:44 -07:00
2008-11-14 16:28:45 -06:00
// some quest referenced in spells not exist (outdated spells)
2008-10-11 14:16:25 -05:00
if ( ! quest )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
if ( ! quest -> HasFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT ))
2008-10-11 14:16:25 -05:00
{
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u , but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective." , spellInfo -> Id , quest_id );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// this will prevent quest completing without objective
2008-10-14 11:57:03 -05:00
const_cast < Quest *> ( quest ) -> SetFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT );
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu quests definitions" , ( unsigned long ) mQuestTemplates . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadQuestLocales ()
{
2008-11-20 16:16:57 -06:00
mQuestLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,"
2010-03-02 09:59:59 -07:00
"Title_loc1,Details_loc1,Objectives_loc1,OfferRewardText_loc1,RequestItemsText_loc1,EndText_loc1,CompletedText_loc1,ObjectiveText1_loc1,ObjectiveText2_loc1,ObjectiveText3_loc1,ObjectiveText4_loc1,"
"Title_loc2,Details_loc2,Objectives_loc2,OfferRewardText_loc2,RequestItemsText_loc2,EndText_loc2,CompletedText_loc2,ObjectiveText1_loc2,ObjectiveText2_loc2,ObjectiveText3_loc2,ObjectiveText4_loc2,"
"Title_loc3,Details_loc3,Objectives_loc3,OfferRewardText_loc3,RequestItemsText_loc3,EndText_loc3,CompletedText_loc3,ObjectiveText1_loc3,ObjectiveText2_loc3,ObjectiveText3_loc3,ObjectiveText4_loc3,"
"Title_loc4,Details_loc4,Objectives_loc4,OfferRewardText_loc4,RequestItemsText_loc4,EndText_loc4,CompletedText_loc4,ObjectiveText1_loc4,ObjectiveText2_loc4,ObjectiveText3_loc4,ObjectiveText4_loc4,"
"Title_loc5,Details_loc5,Objectives_loc5,OfferRewardText_loc5,RequestItemsText_loc5,EndText_loc5,CompletedText_loc5,ObjectiveText1_loc5,ObjectiveText2_loc5,ObjectiveText3_loc5,ObjectiveText4_loc5,"
"Title_loc6,Details_loc6,Objectives_loc6,OfferRewardText_loc6,RequestItemsText_loc6,EndText_loc6,CompletedText_loc6,ObjectiveText1_loc6,ObjectiveText2_loc6,ObjectiveText3_loc6,ObjectiveText4_loc6,"
"Title_loc7,Details_loc7,Objectives_loc7,OfferRewardText_loc7,RequestItemsText_loc7,EndText_loc7,CompletedText_loc7,ObjectiveText1_loc7,ObjectiveText2_loc7,ObjectiveText3_loc7,ObjectiveText4_loc7,"
"Title_loc8,Details_loc8,Objectives_loc8,OfferRewardText_loc8,RequestItemsText_loc8,EndText_loc8,CompletedText_loc8,ObjectiveText1_loc8,ObjectiveText2_loc8,ObjectiveText3_loc8,ObjectiveText4_loc8"
2008-10-11 14:16:25 -05:00
" FROM locales_quest"
);
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
QuestLocale & data = mQuestLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
2010-03-02 09:59:59 -07:00
std :: string str = fields [ 1 + 11 * ( i - 1 )]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Title . size () <= idx )
data . Title . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Title [ idx ] = str ;
}
}
2010-03-02 09:59:59 -07:00
str = fields [ 1 + 11 * ( i - 1 ) + 1 ]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Details . size () <= idx )
data . Details . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Details [ idx ] = str ;
}
}
2010-03-02 09:59:59 -07:00
str = fields [ 1 + 11 * ( i - 1 ) + 2 ]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Objectives . size () <= idx )
data . Objectives . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Objectives [ idx ] = str ;
}
}
2010-03-02 09:59:59 -07:00
str = fields [ 1 + 11 * ( i - 1 ) + 3 ]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . OfferRewardText . size () <= idx )
data . OfferRewardText . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . OfferRewardText [ idx ] = str ;
}
}
2010-03-02 09:59:59 -07:00
str = fields [ 1 + 11 * ( i - 1 ) + 4 ]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . RequestItemsText . size () <= idx )
data . RequestItemsText . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . RequestItemsText [ idx ] = str ;
}
}
2010-03-02 09:59:59 -07:00
str = fields [ 1 + 11 * ( i - 1 ) + 5 ]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . EndText . size () <= idx )
data . EndText . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . EndText [ idx ] = str ;
}
}
2010-03-02 09:59:59 -07:00
str = fields [ 1 + 11 * ( i - 1 ) + 6 ]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . CompletedText . size () <= idx )
data . CompletedText . resize ( idx + 1 );
data . CompletedText [ idx ] = str ;
}
}
2009-10-17 16:20:24 -07:00
for ( uint8 k = 0 ; k < 4 ; ++ k )
2008-10-11 14:16:25 -05:00
{
2010-03-02 09:59:59 -07:00
str = fields [ 1 + 11 * ( i - 1 ) + 7 + k ]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . ObjectiveText [ k ]. size () <= idx )
data . ObjectiveText [ k ]. resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . ObjectiveText [ k ][ idx ] = str ;
}
}
}
}
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu Quest locale strings" , ( unsigned long ) mQuestLocaleMap . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadScripts ( ScriptMapMap & scripts , char const * tablename )
{
if ( sWorld . IsScriptScheduled ()) // function don't must be called in time scripts use.
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
sLog . outString ( "%s :" , tablename );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
scripts . clear (); // need for reload support
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . PQuery ( "SELECT id,delay,command,datalong,datalong2,dataint, x, y, z, o FROM %s" , tablename );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u script definitions" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
ScriptInfo tmp ;
2008-11-20 16:16:57 -06:00
tmp . id = fields [ 0 ]. GetUInt32 ();
tmp . delay = fields [ 1 ]. GetUInt32 ();
tmp . command = fields [ 2 ]. GetUInt32 ();
tmp . datalong = fields [ 3 ]. GetUInt32 ();
2008-10-11 14:16:25 -05:00
tmp . datalong2 = fields [ 4 ]. GetUInt32 ();
2008-11-20 16:16:57 -06:00
tmp . dataint = fields [ 5 ]. GetInt32 ();
tmp . x = fields [ 6 ]. GetFloat ();
tmp . y = fields [ 7 ]. GetFloat ();
tmp . z = fields [ 8 ]. GetFloat ();
tmp . o = fields [ 9 ]. GetFloat ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// generic command args check
switch ( tmp . command )
{
case SCRIPT_COMMAND_TALK :
{
2009-09-13 00:01:35 -07:00
if ( tmp . datalong > 4 )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Table `%s` has invalid talk type (datalong = %u) in SCRIPT_COMMAND_TALK for script id %u" , tablename , tmp . datalong , tmp . id );
continue ;
}
2008-11-20 16:16:57 -06:00
if ( tmp . dataint == 0 )
{
sLog . outErrorDb ( "Table `%s` has invalid talk text id (dataint = %i) in SCRIPT_COMMAND_TALK for script id %u" , tablename , tmp . dataint , tmp . id );
continue ;
}
if ( tmp . dataint < MIN_DB_SCRIPT_STRING_ID || tmp . dataint >= MAX_DB_SCRIPT_STRING_ID )
{
sLog . outErrorDb ( "Table `%s` has out of range text id (dataint = %i expected %u-%u) in SCRIPT_COMMAND_TALK for script id %u" , tablename , tmp . dataint , MIN_DB_SCRIPT_STRING_ID , MAX_DB_SCRIPT_STRING_ID , tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
// if(!objmgr.GetMangosStringLocale(tmp.dataint)) will checked after db_script_string loading
2008-10-11 14:16:25 -05:00
break ;
}
2009-10-17 15:51:44 -07:00
2009-04-19 18:24:40 -05:00
case SCRIPT_COMMAND_EMOTE :
{
if ( ! sEmotesStore . LookupEntry ( tmp . datalong ))
{
sLog . outErrorDb ( "Table `%s` has invalid emote id (datalong = %u) in SCRIPT_COMMAND_EMOTE for script id %u" , tablename , tmp . datalong , tmp . id );
continue ;
}
break ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case SCRIPT_COMMAND_TELEPORT_TO :
{
if ( ! sMapStore . LookupEntry ( tmp . datalong ))
{
sLog . outErrorDb ( "Table `%s` has invalid map (Id: %u) in SCRIPT_COMMAND_TELEPORT_TO for script id %u" , tablename , tmp . datalong , tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
if ( ! Trinity :: IsValidMapCoord ( tmp . x , tmp . y , tmp . z , tmp . o ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TELEPORT_TO for script id %u" , tablename , tmp . x , tmp . y , tmp . id );
continue ;
}
break ;
}
2009-10-17 15:51:44 -07:00
2009-12-19 18:53:27 +01:00
case SCRIPT_COMMAND_KILL_CREDIT :
{
if ( ! GetCreatureTemplate ( tmp . datalong ))
{
sLog . outErrorDb ( "Table `%s` has invalid creature (Entry: %u) in SCRIPT_COMMAND_KILL_CREDIT for script id %u" , tablename , tmp . datalong , tmp . id );
continue ;
}
break ;
}
2008-10-11 14:16:25 -05:00
case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE :
{
2008-10-14 11:57:03 -05:00
if ( ! Trinity :: IsValidMapCoord ( tmp . x , tmp . y , tmp . z , tmp . o ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Table `%s` has invalid coordinates (X: %f Y: %f) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u" , tablename , tmp . x , tmp . y , tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! GetCreatureTemplate ( tmp . datalong ))
{
sLog . outErrorDb ( "Table `%s` has invalid creature (Entry: %u) in SCRIPT_COMMAND_TEMP_SUMMON_CREATURE for script id %u" , tablename , tmp . datalong , tmp . id );
continue ;
}
break ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case SCRIPT_COMMAND_RESPAWN_GAMEOBJECT :
{
GameObjectData const * data = GetGOData ( tmp . datalong );
if ( ! data )
{
sLog . outErrorDb ( "Table `%s` has invalid gameobject (GUID: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u" , tablename , tmp . datalong , tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
GameObjectInfo const * info = GetGameObjectInfo ( data -> id );
if ( ! info )
{
sLog . outErrorDb ( "Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u" , tablename , tmp . datalong , data -> id , tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( info -> type == GAMEOBJECT_TYPE_FISHINGNODE ||
info -> type == GAMEOBJECT_TYPE_FISHINGHOLE ||
info -> type == GAMEOBJECT_TYPE_DOOR ||
info -> type == GAMEOBJECT_TYPE_BUTTON ||
info -> type == GAMEOBJECT_TYPE_TRAP )
{
sLog . outErrorDb ( "Table `%s` have gameobject type (%u) unsupported by command SCRIPT_COMMAND_RESPAWN_GAMEOBJECT for script id %u" , tablename , info -> id , tmp . id );
continue ;
}
break ;
}
case SCRIPT_COMMAND_OPEN_DOOR :
case SCRIPT_COMMAND_CLOSE_DOOR :
{
GameObjectData const * data = GetGOData ( tmp . datalong );
if ( ! data )
{
sLog . outErrorDb ( "Table `%s` has invalid gameobject (GUID: %u) in %s for script id %u" , tablename , tmp . datalong ,( tmp . command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR" ), tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
GameObjectInfo const * info = GetGameObjectInfo ( data -> id );
if ( ! info )
{
sLog . outErrorDb ( "Table `%s` has gameobject with invalid entry (GUID: %u Entry: %u) in %s for script id %u" , tablename , tmp . datalong , data -> id ,( tmp . command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR" ), tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( info -> type != GAMEOBJECT_TYPE_DOOR )
{
sLog . outErrorDb ( "Table `%s` has gameobject type (%u) non supported by command %s for script id %u" , tablename , info -> id ,( tmp . command == SCRIPT_COMMAND_OPEN_DOOR ? "SCRIPT_COMMAND_OPEN_DOOR" : "SCRIPT_COMMAND_CLOSE_DOOR" ), tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
break ;
}
case SCRIPT_COMMAND_QUEST_EXPLORED :
{
Quest const * quest = GetQuestTemplate ( tmp . datalong );
if ( ! quest )
{
sLog . outErrorDb ( "Table `%s` has invalid quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u" , tablename , tmp . datalong , tmp . id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
if ( ! quest -> HasFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT ))
2008-10-11 14:16:25 -05:00
{
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective." , tablename , tmp . datalong , tmp . id );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// this will prevent quest completing without objective
2008-10-14 11:57:03 -05:00
const_cast < Quest *> ( quest ) -> SetFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT );
2009-10-17 15:51:44 -07:00
2008-11-14 16:28:45 -06:00
// continue; - quest objective requirement set and command can be allowed
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( float ( tmp . datalong2 ) > DEFAULT_VISIBILITY_DISTANCE )
{
2008-11-10 09:04:23 -06:00
sLog . outErrorDb ( "Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u" ,
tablename , tmp . datalong2 , tmp . id );
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( tmp . datalong2 && float ( tmp . datalong2 ) > DEFAULT_VISIBILITY_DISTANCE )
{
2008-11-10 09:04:23 -06:00
sLog . outErrorDb ( "Table `%s` has too large distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, max distance is %f or 0 for disable distance check" ,
tablename , tmp . datalong2 , tmp . id , DEFAULT_VISIBILITY_DISTANCE );
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( tmp . datalong2 && float ( tmp . datalong2 ) < INTERACTION_DISTANCE )
{
2008-11-10 09:04:23 -06:00
sLog . outErrorDb ( "Table `%s` has too small distance (%u) for exploring objective complete in `datalong2` in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, min distance is %f or 0 for disable distance check" ,
tablename , tmp . datalong2 , tmp . id , INTERACTION_DISTANCE );
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
break ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
case SCRIPT_COMMAND_REMOVE_AURA :
2009-02-19 18:56:50 -06:00
{
if ( ! sSpellStore . LookupEntry ( tmp . datalong ))
{
sLog . outErrorDb ( "Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u" ,
tablename , tmp . datalong , tmp . id );
continue ;
}
if ( tmp . datalong2 & ~ 0x1 ) // 1 bits (0,1)
{
sLog . outErrorDb ( "Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u" ,
tablename , tmp . datalong2 , tmp . id );
continue ;
}
break ;
}
2008-10-11 14:16:25 -05:00
case SCRIPT_COMMAND_CAST_SPELL :
{
if ( ! sSpellStore . LookupEntry ( tmp . datalong ))
{
2008-11-10 09:04:23 -06:00
sLog . outErrorDb ( "Table `%s` using non-existent spell (id: %u) in SCRIPT_COMMAND_REMOVE_AURA or SCRIPT_COMMAND_CAST_SPELL for script id %u" ,
tablename , tmp . datalong , tmp . id );
2008-10-11 14:16:25 -05:00
continue ;
}
2009-02-19 18:56:50 -06:00
if ( tmp . datalong2 & ~ 0x3 ) // 2 bits
{
sLog . outErrorDb ( "Table `%s` using unknown flags in datalong2 (%u)i n SCRIPT_COMMAND_CAST_SPELL for script id %u" ,
tablename , tmp . datalong2 , tmp . id );
continue ;
}
2008-10-11 14:16:25 -05:00
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( scripts . find ( tmp . id ) == scripts . end ())
{
ScriptMap emptyMap ;
scripts [ tmp . id ] = emptyMap ;
}
scripts [ tmp . id ]. insert ( std :: pair < uint32 , ScriptInfo > ( tmp . delay , tmp ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u script definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameObjectScripts ()
{
LoadScripts ( sGameObjectScripts , "gameobject_scripts" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check ids
2009-10-17 16:20:24 -07:00
for ( ScriptMapMap :: const_iterator itr = sGameObjectScripts . begin (); itr != sGameObjectScripts . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
if ( ! GetGOData ( itr -> first ))
sLog . outErrorDb ( "Table `gameobject_scripts` has not existing gameobject (GUID: %u) as script id" , itr -> first );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadQuestEndScripts ()
{
LoadScripts ( sQuestEndScripts , "quest_end_scripts" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check ids
2009-10-17 16:20:24 -07:00
for ( ScriptMapMap :: const_iterator itr = sQuestEndScripts . begin (); itr != sQuestEndScripts . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
if ( ! GetQuestTemplate ( itr -> first ))
sLog . outErrorDb ( "Table `quest_end_scripts` has not existing quest (Id: %u) as script id" , itr -> first );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadQuestStartScripts ()
{
LoadScripts ( sQuestStartScripts , "quest_start_scripts" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check ids
2009-10-17 16:20:24 -07:00
for ( ScriptMapMap :: const_iterator itr = sQuestStartScripts . begin (); itr != sQuestStartScripts . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
if ( ! GetQuestTemplate ( itr -> first ))
sLog . outErrorDb ( "Table `quest_start_scripts` has not existing quest (Id: %u) as script id" , itr -> first );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadSpellScripts ()
{
LoadScripts ( sSpellScripts , "spell_scripts" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// check ids
2009-10-17 16:20:24 -07:00
for ( ScriptMapMap :: const_iterator itr = sSpellScripts . begin (); itr != sSpellScripts . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
SpellEntry const * spellInfo = sSpellStore . LookupEntry ( itr -> first );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! spellInfo )
{
sLog . outErrorDb ( "Table `spell_scripts` has not existing spell (Id: %u) as script id" , itr -> first );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//check for correct spellEffect
bool found = false ;
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; i < 3 ; ++ i )
2008-10-11 14:16:25 -05:00
{
// skip empty effects
if ( ! spellInfo -> Effect [ i ] )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( spellInfo -> Effect [ i ] == SPELL_EFFECT_SCRIPT_EFFECT )
{
found = true ;
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! found )
sLog . outErrorDb ( "Table `spell_scripts` has unsupported spell (Id: %u) without SPELL_EFFECT_SCRIPT_EFFECT (%u) spell effect" , itr -> first , SPELL_EFFECT_SCRIPT_EFFECT );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadEventScripts ()
{
LoadScripts ( sEventScripts , "event_scripts" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
std :: set < uint32 > evt_scripts ;
// Load all possible script entries from gameobjects
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sGOStorage . MaxEntry ; ++ i )
2008-10-11 14:16:25 -05:00
{
GameObjectInfo const * goInfo = sGOStorage . LookupEntry < GameObjectInfo > ( i );
if ( goInfo )
{
switch ( goInfo -> type )
{
case GAMEOBJECT_TYPE_GOOBER :
2009-06-01 14:56:54 -05:00
if ( goInfo -> goober . eventId )
2008-10-11 14:16:25 -05:00
evt_scripts . insert ( goInfo -> goober . eventId );
break ;
case GAMEOBJECT_TYPE_CHEST :
2009-06-01 14:56:54 -05:00
if ( goInfo -> chest . eventId )
2008-10-11 14:16:25 -05:00
evt_scripts . insert ( goInfo -> chest . eventId );
break ;
2009-06-01 14:56:54 -05:00
case GAMEOBJECT_TYPE_CAMERA :
if ( goInfo -> camera . eventID )
evt_scripts . insert ( goInfo -> camera . eventID );
2008-10-11 14:16:25 -05:00
default :
break ;
}
}
}
// Load all possible script entries from spells
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sSpellStore . GetNumRows (); ++ i )
2008-10-11 14:16:25 -05:00
{
SpellEntry const * spell = sSpellStore . LookupEntry ( i );
if ( spell )
{
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < 3 ; ++ j )
2008-10-11 14:16:25 -05:00
{
if ( spell -> Effect [ j ] == SPELL_EFFECT_SEND_EVENT )
{
if ( spell -> EffectMiscValue [ j ])
evt_scripts . insert ( spell -> EffectMiscValue [ j ]);
}
}
}
}
// Then check if all scripts are in above list of possible script entries
2009-10-17 16:20:24 -07:00
for ( ScriptMapMap :: const_iterator itr = sEventScripts . begin (); itr != sEventScripts . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
std :: set < uint32 >:: const_iterator itr2 = evt_scripts . find ( itr -> first );
if ( itr2 == evt_scripts . end ())
2009-06-01 14:56:54 -05:00
sLog . outErrorDb ( "Table `event_scripts` has script (Id: %u) not referring to any gameobject_template type 10 data2 field, type 3 data6 field, type 13 data 2 field or any spell effect %u" ,
itr -> first , SPELL_EFFECT_SEND_EVENT );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-12-09 23:06:16 -06:00
//Load WP Scripts
void ObjectMgr :: LoadWaypointScripts ()
{
LoadScripts ( sWaypointScripts , "waypoint_scripts" );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( ScriptMapMap :: const_iterator itr = sWaypointScripts . begin (); itr != sWaypointScripts . end (); ++ itr )
2008-12-09 23:06:16 -06:00
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr query = WorldDatabase . PQuery ( "SELECT * FROM waypoint_scripts WHERE id = %u" , itr -> first );
2008-12-09 23:06:16 -06:00
if ( ! query || ! query -> GetRowCount ())
sLog . outErrorDb ( "There is no waypoint which links to the waypoint script %u" , itr -> first );
}
}
2009-10-17 15:51:44 -07:00
2009-12-20 13:35:08 +02:00
void ObjectMgr :: LoadGossipScripts ()
{
LoadScripts ( sGossipScripts , "gossip_scripts" );
// checks are done in LoadGossipMenuItems
}
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadItemTexts ()
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT id, text FROM item_text" );
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-12-18 13:41:30 -08:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u item pages" , count );
return ;
}
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
Field * fields ;
do
{
bar . step ();
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
fields = result -> Fetch ();
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
mItemTexts [ fields [ 0 ]. GetUInt32 () ] = fields [ 1 ]. GetCppString ();
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
++ count ;
2009-12-18 13:41:30 -08:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow () );
2009-12-18 13:41:30 -08:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u item texts" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadPageTexts ()
{
sPageTextStore . Free (); // for reload case
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
sPageTextStore . Load ();
sLog . outString ( ">> Loaded %u page texts" , sPageTextStore . RecordCount );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sPageTextStore . MaxEntry ; ++ i )
2008-10-11 14:16:25 -05:00
{
// check data correctness
PageText const * page = sPageTextStore . LookupEntry < PageText > ( i );
2010-01-01 14:19:29 -06:00
if ( ! page )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( page -> Next_Page && ! sPageTextStore . LookupEntry < PageText > ( page -> Next_Page ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Page text (Id: %u) has not existing next page (Id:%u)" , i , page -> Next_Page );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// detect circular reference
std :: set < uint32 > checkedPages ;
2009-10-17 16:20:24 -07:00
for ( PageText const * pageItr = page ; pageItr ; pageItr = sPageTextStore . LookupEntry < PageText > ( pageItr -> Next_Page ))
2008-10-11 14:16:25 -05:00
{
2010-01-01 14:19:29 -06:00
if ( ! pageItr -> Next_Page )
2008-10-11 14:16:25 -05:00
break ;
checkedPages . insert ( pageItr -> Page_ID );
2010-01-01 14:19:29 -06:00
if ( checkedPages . find ( pageItr -> Next_Page ) != checkedPages . end ())
2008-10-11 14:16:25 -05:00
{
std :: ostringstream ss ;
2010-01-01 14:19:29 -06:00
ss << "The text page(s) " ;
2009-10-17 16:20:24 -07:00
for ( std :: set < uint32 >:: iterator itr = checkedPages . begin (); itr != checkedPages . end (); ++ itr )
2008-10-11 14:16:25 -05:00
ss << * itr << " " ;
ss << "create(s) a circular reference, which can cause the server to freeze. Changing Next_Page of page "
<< pageItr -> Page_ID << " to 0" ;
sLog . outErrorDb ( ss . str (). c_str ());
const_cast < PageText *> ( pageItr ) -> Next_Page = 0 ;
break ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadPageTextLocales ()
{
2008-11-20 16:16:57 -06:00
mPageTextLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,text_loc1,text_loc2,text_loc3,text_loc4,text_loc5,text_loc6,text_loc7,text_loc8 FROM locales_page_text" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
PageTextLocale & data = mPageTextLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
std :: string str = fields [ i ]. GetCppString ();
if ( str . empty ())
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Text . size () <= idx )
data . Text . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Text [ idx ] = str ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu PageText locale strings" , ( unsigned long ) mPageTextLocaleMap . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
struct SQLInstanceLoader : public SQLStorageLoaderBase < SQLInstanceLoader >
{
template < class D >
2009-04-29 00:31:03 -05:00
void convert_from_str ( uint32 /*field_pos*/ , char * src , D & dst )
2008-11-20 16:16:57 -06:00
{
dst = D ( objmgr . GetScriptId ( src ));
}
};
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadInstanceTemplate ()
{
2008-11-20 16:16:57 -06:00
SQLInstanceLoader loader ;
loader . Load ( sInstanceTemplate );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < sInstanceTemplate . MaxEntry ; i ++ )
2008-10-11 14:16:25 -05:00
{
InstanceTemplate * temp = ( InstanceTemplate * ) GetInstanceTemplate ( i );
2009-12-17 14:06:20 +01:00
if ( ! temp )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-12-17 14:06:20 +01:00
if ( ! MapManager :: IsValidMAP ( temp -> map ))
sLog . outErrorDb ( "ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!" , temp -> map );
if ( ! MapManager :: IsValidMapCoord ( temp -> parent , temp -> startLocX , temp -> startLocY , temp -> startLocZ , temp -> startLocO ))
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:06:20 +01:00
sLog . outErrorDb ( "ObjectMgr::LoadInstanceTemplate: bad parent entrance coordinates for map id %d template!" , temp -> map );
temp -> parent = 0 ; // will have wrong continent 0 parent, at least existed
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u Instance Template definitions" , sInstanceTemplate . RecordCount );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-02-16 20:12:55 -06:00
GossipText const * ObjectMgr :: GetGossipText ( uint32 Text_ID ) const
2008-10-11 14:16:25 -05:00
{
2009-02-16 20:12:55 -06:00
GossipTextMap :: const_iterator itr = mGossipText . find ( Text_ID );
if ( itr != mGossipText . end ())
return & itr -> second ;
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGossipText ()
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT * FROM npc_text" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
int count = 0 ;
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u npc texts" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
int cic ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
++ count ;
cic = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-02-16 20:12:55 -06:00
uint32 Text_ID = fields [ cic ++ ]. GetUInt32 ();
if ( ! Text_ID )
2008-10-11 14:16:25 -05:00
{
2009-02-16 20:12:55 -06:00
sLog . outErrorDb ( "Table `npc_text` has record wit reserved id 0, ignore." );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-02-16 20:12:55 -06:00
GossipText & gText = mGossipText [ Text_ID ];
2009-10-17 15:51:44 -07:00
2009-02-16 20:12:55 -06:00
for ( int i = 0 ; i < 8 ; i ++ )
{
gText . Options [ i ]. Text_0 = fields [ cic ++ ]. GetCppString ();
gText . Options [ i ]. Text_1 = fields [ cic ++ ]. GetCppString ();
2009-10-17 15:51:44 -07:00
2009-02-16 20:12:55 -06:00
gText . Options [ i ]. Language = fields [ cic ++ ]. GetUInt32 ();
gText . Options [ i ]. Probability = fields [ cic ++ ]. GetFloat ();
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < 3 ; ++ j )
2009-02-16 20:12:55 -06:00
{
gText . Options [ i ]. Emotes [ j ]. _Delay = fields [ cic ++ ]. GetUInt32 ();
gText . Options [ i ]. Emotes [ j ]. _Emote = fields [ cic ++ ]. GetUInt32 ();
}
2008-10-11 14:16:25 -05:00
}
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u npc texts" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadNpcTextLocales ()
{
2008-11-20 16:16:57 -06:00
mNpcTextLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,"
2008-10-11 14:16:25 -05:00
"Text0_0_loc1,Text0_1_loc1,Text1_0_loc1,Text1_1_loc1,Text2_0_loc1,Text2_1_loc1,Text3_0_loc1,Text3_1_loc1,Text4_0_loc1,Text4_1_loc1,Text5_0_loc1,Text5_1_loc1,Text6_0_loc1,Text6_1_loc1,Text7_0_loc1,Text7_1_loc1,"
"Text0_0_loc2,Text0_1_loc2,Text1_0_loc2,Text1_1_loc2,Text2_0_loc2,Text2_1_loc2,Text3_0_loc2,Text3_1_loc1,Text4_0_loc2,Text4_1_loc2,Text5_0_loc2,Text5_1_loc2,Text6_0_loc2,Text6_1_loc2,Text7_0_loc2,Text7_1_loc2,"
"Text0_0_loc3,Text0_1_loc3,Text1_0_loc3,Text1_1_loc3,Text2_0_loc3,Text2_1_loc3,Text3_0_loc3,Text3_1_loc1,Text4_0_loc3,Text4_1_loc3,Text5_0_loc3,Text5_1_loc3,Text6_0_loc3,Text6_1_loc3,Text7_0_loc3,Text7_1_loc3,"
"Text0_0_loc4,Text0_1_loc4,Text1_0_loc4,Text1_1_loc4,Text2_0_loc4,Text2_1_loc4,Text3_0_loc4,Text3_1_loc1,Text4_0_loc4,Text4_1_loc4,Text5_0_loc4,Text5_1_loc4,Text6_0_loc4,Text6_1_loc4,Text7_0_loc4,Text7_1_loc4,"
"Text0_0_loc5,Text0_1_loc5,Text1_0_loc5,Text1_1_loc5,Text2_0_loc5,Text2_1_loc5,Text3_0_loc5,Text3_1_loc1,Text4_0_loc5,Text4_1_loc5,Text5_0_loc5,Text5_1_loc5,Text6_0_loc5,Text6_1_loc5,Text7_0_loc5,Text7_1_loc5,"
"Text0_0_loc6,Text0_1_loc6,Text1_0_loc6,Text1_1_loc6,Text2_0_loc6,Text2_1_loc6,Text3_0_loc6,Text3_1_loc1,Text4_0_loc6,Text4_1_loc6,Text5_0_loc6,Text5_1_loc6,Text6_0_loc6,Text6_1_loc6,Text7_0_loc6,Text7_1_loc6,"
"Text0_0_loc7,Text0_1_loc7,Text1_0_loc7,Text1_1_loc7,Text2_0_loc7,Text2_1_loc7,Text3_0_loc7,Text3_1_loc1,Text4_0_loc7,Text4_1_loc7,Text5_0_loc7,Text5_1_loc7,Text6_0_loc7,Text6_1_loc7,Text7_0_loc7,Text7_1_loc7, "
"Text0_0_loc8,Text0_1_loc8,Text1_0_loc8,Text1_1_loc8,Text2_0_loc8,Text2_1_loc8,Text3_0_loc8,Text3_1_loc1,Text4_0_loc8,Text4_1_loc8,Text5_0_loc8,Text5_1_loc8,Text6_0_loc8,Text6_1_loc8,Text7_0_loc8,Text7_1_loc8 "
" FROM locales_npc_text" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
NpcTextLocale & data = mNpcTextLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
2009-10-17 16:20:24 -07:00
for ( uint8 j = 0 ; j < 8 ; ++ j )
2008-10-11 14:16:25 -05:00
{
std :: string str0 = fields [ 1 + 8 * 2 * ( i - 1 ) + 2 * j ]. GetCppString ();
if ( ! str0 . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Text_0 [ j ]. size () <= idx )
data . Text_0 [ j ]. resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Text_0 [ j ][ idx ] = str0 ;
}
}
std :: string str1 = fields [ 1 + 8 * 2 * ( i - 1 ) + 2 * j + 1 ]. GetCppString ();
if ( ! str1 . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Text_1 [ j ]. size () <= idx )
data . Text_1 [ j ]. resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Text_1 [ j ][ idx ] = str1 ;
}
}
}
}
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu NpcText locale strings" , ( unsigned long ) mNpcTextLocaleMap . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//not very fast function but it is called only once a day, or on starting-up
void ObjectMgr :: ReturnOrDeleteOldMails ( bool serverUp )
{
2009-12-24 10:20:15 +01:00
time_t basetime = time ( NULL );
2008-10-11 14:16:25 -05:00
sLog . outDebug ( "Returning mails current time: hour: %d, minute: %d, second: %d " , localtime ( & basetime ) -> tm_hour , localtime ( & basetime ) -> tm_min , localtime ( & basetime ) -> tm_sec );
//delete all old mails without item and without body immediately, if starting server
if ( ! serverUp )
2009-05-31 16:15:12 -05:00
CharacterDatabase . PExecute ( "DELETE FROM mail WHERE expire_time < '" UI64FMTD "' AND has_items = '0' AND itemTextId = 0" , ( uint64 ) basetime );
2008-10-11 14:16:25 -05:00
// 0 1 2 3 4 5 6 7 8 9
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . PQuery ( "SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" UI64FMTD "'" , ( uint64 ) basetime );
2008-10-11 14:16:25 -05:00
if ( ! result )
2009-01-22 22:44:27 -06:00
{
barGoLink bar ( 1 );
bar . step ();
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outString ( ">> Only expired mails (need to be return or delete) or DB table `mail` is empty." );
2008-10-11 14:16:25 -05:00
return ; // any mails need to be returned or deleted
2009-01-22 22:44:27 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//std::ostringstream delitems, delmails; //will be here for optimization
//bool deletemail = false, deleteitem = false;
//delitems << "DELETE FROM item_instance WHERE guid IN ( ";
//delmails << "DELETE FROM mail WHERE id IN ( "
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
barGoLink bar ( result -> GetRowCount () );
uint32 count = 0 ;
Field * fields ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
2009-01-22 22:44:27 -06:00
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
fields = result -> Fetch ();
Mail * m = new Mail ;
m -> messageID = fields [ 0 ]. GetUInt32 ();
m -> messageType = fields [ 1 ]. GetUInt8 ();
m -> sender = fields [ 2 ]. GetUInt32 ();
m -> receiver = fields [ 3 ]. GetUInt32 ();
m -> itemTextId = fields [ 4 ]. GetUInt32 ();
bool has_items = fields [ 5 ]. GetBool ();
m -> expire_time = ( time_t ) fields [ 6 ]. GetUInt64 ();
m -> deliver_time = 0 ;
m -> COD = fields [ 7 ]. GetUInt32 ();
m -> checked = fields [ 8 ]. GetUInt32 ();
m -> mailTemplateId = fields [ 9 ]. GetInt16 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Player * pl = 0 ;
if ( serverUp )
pl = GetPlayer (( uint64 ) m -> receiver );
if ( pl && pl -> m_mailsLoaded )
{ //this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail
//his in mailbox and he has already listed his mails )
delete m ;
continue ;
}
//delete or return mail:
if ( has_items )
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr resultItems = CharacterDatabase . PQuery ( "SELECT item_guid,item_template FROM mail_items WHERE mail_id='%u'" , m -> messageID );
2008-10-11 14:16:25 -05:00
if ( resultItems )
{
do
{
Field * fields2 = resultItems -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 item_guid_low = fields2 [ 0 ]. GetUInt32 ();
uint32 item_template = fields2 [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m -> AddItem ( item_guid_low , item_template );
}
while ( resultItems -> NextRow ());
}
//if it is mail from AH, it shouldn't be returned, but deleted
if ( m -> messageType != MAIL_NORMAL || ( m -> checked & ( MAIL_CHECK_MASK_AUCTION | MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED )))
{
// mail open and then not returned
2009-10-17 16:20:24 -07:00
for ( std :: vector < MailItemInfo >:: iterator itr2 = m -> items . begin (); itr2 != m -> items . end (); ++ itr2 )
2008-10-11 14:16:25 -05:00
CharacterDatabase . PExecute ( "DELETE FROM item_instance WHERE guid = '%u'" , itr2 -> item_guid );
}
else
{
//mail will be returned:
2009-05-31 16:15:12 -05:00
CharacterDatabase . PExecute ( "UPDATE mail SET sender = '%u', receiver = '%u', expire_time = '" UI64FMTD "', deliver_time = '" UI64FMTD "',cod = '0', checked = '%u' WHERE id = '%u'" , m -> receiver , m -> sender , ( uint64 )( basetime + 30 * DAY ), ( uint64 ) basetime , MAIL_CHECK_MASK_RETURNED , m -> messageID );
2008-10-11 14:16:25 -05:00
delete m ;
continue ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m -> itemTextId )
CharacterDatabase . PExecute ( "DELETE FROM item_text WHERE id = '%u'" , m -> itemTextId );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//deletemail = true;
//delmails << m->messageID << ", ";
CharacterDatabase . PExecute ( "DELETE FROM mail WHERE id = '%u'" , m -> messageID );
delete m ;
2009-01-22 22:44:27 -06:00
++ count ;
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outString ( ">> Loaded %u mails" , count );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadQuestAreaTriggers ()
{
mQuestAreaTriggerMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT id,quest FROM areatrigger_involvedrelation" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u quest trigger points" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
++ count ;
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 trigger_ID = fields [ 0 ]. GetUInt32 ();
uint32 quest_ID = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
AreaTriggerEntry const * atEntry = sAreaTriggerStore . LookupEntry ( trigger_ID );
if ( ! atEntry )
{
sLog . outErrorDb ( "Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`." , trigger_ID );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Quest const * quest = GetQuestTemplate ( quest_ID );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! quest )
{
sLog . outErrorDb ( "Table `areatrigger_involvedrelation` has record (id: %u) for not existing quest %u" , trigger_ID , quest_ID );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
if ( ! quest -> HasFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT ))
2008-10-11 14:16:25 -05:00
{
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective." , trigger_ID , quest_ID );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// this will prevent quest completing without objective
2008-10-14 11:57:03 -05:00
const_cast < Quest *> ( quest ) -> SetFlag ( QUEST_TRINITY_FLAGS_EXPLORATION_OR_EVENT );
2009-10-17 15:51:44 -07:00
2008-11-14 16:28:45 -06:00
// continue; - quest modified to required objective and trigger can be allowed.
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mQuestAreaTriggerMap [ trigger_ID ] = quest_ID ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u quest trigger points" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadTavernAreaTriggers ()
{
mTavernAreaTriggerSet . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT id FROM areatrigger_tavern" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u tavern triggers" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
++ count ;
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 Trigger_ID = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
AreaTriggerEntry const * atEntry = sAreaTriggerStore . LookupEntry ( Trigger_ID );
if ( ! atEntry )
{
sLog . outErrorDb ( "Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`." , Trigger_ID );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mTavernAreaTriggerSet . insert ( Trigger_ID );
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u tavern triggers" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadAreaTriggerScripts ()
{
mAreaTriggerScripts . clear (); // need for reload case
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, ScriptName FROM areatrigger_scripts" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u areatrigger scripts" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
++ count ;
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 Trigger_ID = fields [ 0 ]. GetUInt32 ();
2008-11-20 16:16:57 -06:00
const char * scriptName = fields [ 1 ]. GetString ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
AreaTriggerEntry const * atEntry = sAreaTriggerStore . LookupEntry ( Trigger_ID );
if ( ! atEntry )
{
sLog . outErrorDb ( "Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`." , Trigger_ID );
continue ;
}
2008-11-20 16:16:57 -06:00
mAreaTriggerScripts [ Trigger_ID ] = GetScriptId ( scriptName );
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u areatrigger scripts" , count );
}
2009-10-17 15:51:44 -07:00
2009-01-21 16:18:57 -06:00
uint32 ObjectMgr :: GetNearestTaxiNode ( float x , float y , float z , uint32 mapid , uint32 team )
2008-10-11 14:16:25 -05:00
{
bool found = false ;
float dist ;
uint32 id = 0 ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 i = 1 ; i < sTaxiNodesStore . GetNumRows (); ++ i )
2008-10-11 14:16:25 -05:00
{
TaxiNodesEntry const * node = sTaxiNodesStore . LookupEntry ( i );
2009-12-17 14:55:19 +01:00
2009-12-18 13:41:30 -08:00
if ( ! node || node -> map_id != mapid || ! node -> MountCreatureID [ team == ALLIANCE ? 1 : 0 ] && node -> MountCreatureID [ 0 ] != 32981 ) // dk flight
2009-01-22 22:44:27 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
uint8 field = ( uint8 )(( i - 1 ) / 32 );
uint32 submask = 1 << (( i - 1 ) % 32 );
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
// skip not taxi network nodes
if (( sTaxiNodesMask [ field ] & submask ) == 0 )
continue ;
2009-10-17 15:51:44 -07:00
2009-12-18 13:41:30 -08:00
float dist2 = ( node -> x - x ) * ( node -> x - x ) + ( node -> y - y ) * ( node -> y - y ) + ( node -> z - z ) * ( node -> z - z );
2009-01-22 22:44:27 -06:00
if ( found )
2008-10-11 14:16:25 -05:00
{
2009-01-22 22:44:27 -06:00
if ( dist2 < dist )
2008-10-11 14:16:25 -05:00
{
dist = dist2 ;
id = i ;
}
}
2009-01-22 22:44:27 -06:00
else
{
found = true ;
dist = dist2 ;
id = i ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return id ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: GetTaxiPath ( uint32 source , uint32 destination , uint32 & path , uint32 & cost )
{
TaxiPathSetBySource :: iterator src_i = sTaxiPathSetBySource . find ( source );
if ( src_i == sTaxiPathSetBySource . end ())
{
path = 0 ;
cost = 0 ;
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
TaxiPathSetForSource & pathSet = src_i -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
TaxiPathSetForSource :: iterator dest_i = pathSet . find ( destination );
if ( dest_i == pathSet . end ())
{
path = 0 ;
cost = 0 ;
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
cost = dest_i -> second . price ;
path = dest_i -> second . ID ;
}
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
uint32 ObjectMgr :: GetTaxiMountDisplayId ( uint32 id , uint32 team , bool allowed_alt_team /* = false */ )
2008-10-11 14:16:25 -05:00
{
2009-09-21 07:52:16 +02:00
uint32 mount_entry = 0 ;
uint32 mount_id = 0 ;
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
// select mount creature id
2008-10-11 14:16:25 -05:00
TaxiNodesEntry const * node = sTaxiNodesStore . LookupEntry ( id );
2008-11-20 16:16:57 -06:00
if ( node )
2008-10-11 14:16:25 -05:00
{
2008-12-24 09:58:26 -06:00
if ( team == ALLIANCE )
mount_entry = node -> MountCreatureID [ 1 ];
2009-09-21 07:52:16 +02:00
else
2008-12-24 09:58:26 -06:00
mount_entry = node -> MountCreatureID [ 0 ];
2009-10-17 15:51:44 -07:00
2009-11-17 20:26:35 -08:00
// Fix for Alliance not being able to use Acherus taxi
// only one mount type for both sides
if ( mount_entry == 0 && allowed_alt_team )
{
// Simply reverse the selection. At least one team in theory should have a valid mount ID to choose.
mount_entry = team == ALLIANCE ? node -> MountCreatureID [ 0 ] : node -> MountCreatureID [ 1 ];
}
2009-10-17 15:51:44 -07:00
2009-09-21 07:52:16 +02:00
CreatureInfo const * mount_info = GetCreatureTemplate ( mount_entry );
if ( mount_info )
{
if ( ! ( mount_id = mount_info -> GetRandomValidModelId ()))
{
sLog . outErrorDb ( "No displayid found for the taxi mount with the entry %u! Can't load it!" , mount_entry );
return false ;
}
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
CreatureModelInfo const * minfo = objmgr . GetCreatureModelRandomGender ( mount_id );
if ( minfo )
mount_id = minfo -> modelid ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return mount_id ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: GetTaxiPathNodes ( uint32 path , Path & pathnodes , std :: vector < uint32 >& mapIds )
{
if ( path >= sTaxiPathNodesByPath . size ())
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
TaxiPathNodeList & nodeList = sTaxiPathNodesByPath [ path ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pathnodes . Resize ( nodeList . size ());
mapIds . resize ( nodeList . size ());
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( size_t i = 0 ; i < nodeList . size (); ++ i )
2008-10-11 14:16:25 -05:00
{
pathnodes [ i ]. x = nodeList [ i ]. x ;
pathnodes [ i ]. y = nodeList [ i ]. y ;
pathnodes [ i ]. z = nodeList [ i ]. z ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mapIds [ i ] = nodeList [ i ]. mapid ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: GetTransportPathNodes ( uint32 path , TransportPath & pathnodes )
{
if ( path >= sTaxiPathNodesByPath . size ())
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
TaxiPathNodeList & nodeList = sTaxiPathNodesByPath [ path ];
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
pathnodes . Resize ( nodeList . size ());
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( size_t i = 0 ; i < nodeList . size (); ++ i )
2008-10-11 14:16:25 -05:00
{
pathnodes [ i ]. mapid = nodeList [ i ]. mapid ;
pathnodes [ i ]. x = nodeList [ i ]. x ;
pathnodes [ i ]. y = nodeList [ i ]. y ;
pathnodes [ i ]. z = nodeList [ i ]. z ;
pathnodes [ i ]. actionFlag = nodeList [ i ]. actionFlag ;
pathnodes [ i ]. delay = nodeList [ i ]. delay ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGraveyardZones ()
{
mGraveYardMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT id,ghost_zone,faction FROM game_graveyard_zone" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u graveyard-zone links" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
++ count ;
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 safeLocId = fields [ 0 ]. GetUInt32 ();
uint32 zoneId = fields [ 1 ]. GetUInt32 ();
uint32 team = fields [ 2 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldSafeLocsEntry const * entry = sWorldSafeLocsStore . LookupEntry ( safeLocId );
if ( ! entry )
{
sLog . outErrorDb ( "Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped." , safeLocId );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
AreaTableEntry const * areaEntry = GetAreaEntryByAreaID ( zoneId );
if ( ! areaEntry )
{
sLog . outErrorDb ( "Table `game_graveyard_zone` has record for not existing zone id (%u), skipped." , zoneId );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( areaEntry -> zone != 0 )
{
sLog . outErrorDb ( "Table `game_graveyard_zone` has record subzone id (%u) instead of zone, skipped." , zoneId );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( team != 0 && team != HORDE && team != ALLIANCE )
{
sLog . outErrorDb ( "Table `game_graveyard_zone` has record for non player faction (%u), skipped." , team );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! AddGraveYardLink ( safeLocId , zoneId , team , false ))
2008-11-14 16:28:45 -06:00
sLog . outErrorDb ( "Table `game_graveyard_zone` has a duplicate record for Graveyard (ID: %u) and Zone (ID: %u), skipped." , safeLocId , zoneId );
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u graveyard-zone links" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldSafeLocsEntry const * ObjectMgr :: GetClosestGraveYard ( float x , float y , float z , uint32 MapId , uint32 team )
{
// search for zone associated closest graveyard
2009-01-02 11:03:43 -06:00
uint32 zoneId = MapManager :: Instance (). GetZoneId ( MapId , x , y , z );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Simulate std. algorithm:
// found some graveyard associated to (ghost_zone,ghost_map)
//
// if mapId == graveyard.mapId (ghost in plain zone or city or battleground) and search graveyard at same map
// then check faction
// if mapId != graveyard.mapId (ghost in instance) and search any graveyard associated
2008-11-14 17:03:03 -06:00
// then check faction
2008-10-11 14:16:25 -05:00
GraveYardMap :: const_iterator graveLow = mGraveYardMap . lower_bound ( zoneId );
GraveYardMap :: const_iterator graveUp = mGraveYardMap . upper_bound ( zoneId );
2009-03-18 21:18:45 +01:00
MapEntry const * map = sMapStore . LookupEntry ( MapId );
// not need to check validity of map object; MapId _MUST_ be valid here
2009-10-17 15:51:44 -07:00
2009-03-18 21:18:45 +01:00
if ( graveLow == graveUp && ! map -> IsBattleArena ())
2008-10-11 14:16:25 -05:00
{
2009-12-17 14:55:19 +01:00
//sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team);
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
// at corpse map
2008-10-11 14:16:25 -05:00
bool foundNear = false ;
float distNear ;
WorldSafeLocsEntry const * entryNear = NULL ;
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
// at entrance map for corpse map
bool foundEntr = false ;
float distEntr ;
WorldSafeLocsEntry const * entryEntr = NULL ;
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
// some where other
2008-10-11 14:16:25 -05:00
WorldSafeLocsEntry const * entryFar = NULL ;
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
MapEntry const * mapEntry = sMapStore . LookupEntry ( MapId );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( GraveYardMap :: const_iterator itr = graveLow ; itr != graveUp ; ++ itr )
2008-10-11 14:16:25 -05:00
{
GraveYardData const & data = itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldSafeLocsEntry const * entry = sWorldSafeLocsStore . LookupEntry ( data . safeLocId );
if ( ! entry )
{
sLog . outErrorDb ( "Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped." , data . safeLocId );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
// skip enemy faction graveyard
2008-10-11 14:16:25 -05:00
// team == 0 case can be at call from .neargrave
if ( data . team != 0 && team != 0 && data . team != team )
continue ;
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
// find now nearest graveyard at other map
if ( MapId != entry -> map_id )
2008-10-11 14:16:25 -05:00
{
2008-11-14 17:03:03 -06:00
// if find graveyard at different map from where entrance placed (or no entrance data), use any first
2009-05-03 22:21:46 -05:00
if ( ! mapEntry ||
mapEntry -> entrance_map < 0 ||
mapEntry -> entrance_map != entry -> map_id ||
( mapEntry -> entrance_x == 0 && mapEntry -> entrance_y == 0 ))
2008-10-11 14:16:25 -05:00
{
2008-11-14 17:03:03 -06:00
// not have any corrdinates for check distance anyway
entryFar = entry ;
continue ;
}
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
// at entrance map calculate distance (2D);
float dist2 = ( entry -> x - mapEntry -> entrance_x ) * ( entry -> x - mapEntry -> entrance_x )
+ ( entry -> y - mapEntry -> entrance_y ) * ( entry -> y - mapEntry -> entrance_y );
if ( foundEntr )
{
if ( dist2 < distEntr )
{
distEntr = dist2 ;
entryEntr = entry ;
}
}
else
{
foundEntr = true ;
distEntr = dist2 ;
entryEntr = entry ;
2008-10-11 14:16:25 -05:00
}
}
2008-11-14 17:03:03 -06:00
// find now nearest graveyard at same map
2008-10-11 14:16:25 -05:00
else
{
2008-11-14 17:03:03 -06:00
float dist2 = ( entry -> x - x ) * ( entry -> x - x ) + ( entry -> y - y ) * ( entry -> y - y ) + ( entry -> z - z ) * ( entry -> z - z );
if ( foundNear )
{
if ( dist2 < distNear )
{
distNear = dist2 ;
entryNear = entry ;
}
}
else
{
foundNear = true ;
distNear = dist2 ;
entryNear = entry ;
}
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( entryNear )
return entryNear ;
2009-10-17 15:51:44 -07:00
2008-11-14 17:03:03 -06:00
if ( entryEntr )
return entryEntr ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return entryFar ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
GraveYardData const * ObjectMgr :: FindGraveYardData ( uint32 id , uint32 zoneId )
{
GraveYardMap :: const_iterator graveLow = mGraveYardMap . lower_bound ( zoneId );
GraveYardMap :: const_iterator graveUp = mGraveYardMap . upper_bound ( zoneId );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( GraveYardMap :: const_iterator itr = graveLow ; itr != graveUp ; ++ itr )
2008-10-11 14:16:25 -05:00
{
if ( itr -> second . safeLocId == id )
return & itr -> second ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool ObjectMgr :: AddGraveYardLink ( uint32 id , uint32 zoneId , uint32 team , bool inDB )
{
if ( FindGraveYardData ( id , zoneId ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// add link to loaded data
GraveYardData data ;
data . safeLocId = id ;
data . team = team ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mGraveYardMap . insert ( GraveYardMap :: value_type ( zoneId , data ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// add link to DB
if ( inDB )
{
WorldDatabase . PExecuteLog ( "INSERT INTO game_graveyard_zone ( id,ghost_zone,faction) "
"VALUES ('%u', '%u','%u')" , id , zoneId , team );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
void ObjectMgr :: RemoveGraveYardLink ( uint32 id , uint32 zoneId , uint32 team , bool inDB )
{
GraveYardMap :: iterator graveLow = mGraveYardMap . lower_bound ( zoneId );
GraveYardMap :: iterator graveUp = mGraveYardMap . upper_bound ( zoneId );
if ( graveLow == graveUp )
{
//sLog.outErrorDb("Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.",zoneId,team);
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
bool found = false ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
GraveYardMap :: iterator itr ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( itr = graveLow ; itr != graveUp ; ++ itr )
2008-10-14 11:57:03 -05:00
{
GraveYardData & data = itr -> second ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
// skip not matching safezone id
if ( data . safeLocId != id )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
// skip enemy faction graveyard at same map (normal area, city, or battleground)
// team == 0 case can be at call from .neargrave
if ( data . team != 0 && team != 0 && data . team != team )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
found = true ;
break ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
// no match, return
if ( ! found )
return ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
// remove from links
mGraveYardMap . erase ( itr );
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
// remove link from DB
if ( inDB )
{
WorldDatabase . PExecute ( "DELETE FROM game_graveyard_zone WHERE id = '%u' AND ghost_zone = '%u' AND faction = '%u'" , id , zoneId , team );
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
return ;
}
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadAreaTriggerTeleports ()
{
mAreaTriggers . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2009-04-06 21:14:51 +02:00
// 0 1 2 3 4 5 6
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT id, access_id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport" );
2009-02-09 08:16:34 -05:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u area trigger teleport definitions" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 Trigger_ID = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
AreaTrigger at ;
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
at . access_id = fields [ 1 ]. GetUInt32 ();
at . target_mapId = fields [ 2 ]. GetUInt32 ();
at . target_X = fields [ 3 ]. GetFloat ();
at . target_Y = fields [ 4 ]. GetFloat ();
at . target_Z = fields [ 5 ]. GetFloat ();
at . target_Orientation = fields [ 6 ]. GetFloat ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
AreaTriggerEntry const * atEntry = sAreaTriggerStore . LookupEntry ( Trigger_ID );
if ( ! atEntry )
{
sLog . outErrorDb ( "Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`." , Trigger_ID );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
MapEntry const * mapEntry = sMapStore . LookupEntry ( at . target_mapId );
if ( ! mapEntry )
{
sLog . outErrorDb ( "Area trigger (ID:%u) target map (ID: %u) does not exist in `Map.dbc`." , Trigger_ID , at . target_mapId );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
if ( at . target_X == 0 && at . target_Y == 0 && at . target_Z == 0 )
2008-10-11 14:16:25 -05:00
{
2009-03-05 21:02:33 +01:00
sLog . outErrorDb ( "Area trigger (ID:%u) target coordinates not provided." , Trigger_ID );
continue ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
mAreaTriggers [ Trigger_ID ] = at ;
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-05 21:02:33 +01:00
sLog . outString ( ">> Loaded %u area trigger teleport definitions" , count );
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
void ObjectMgr :: LoadAccessRequirements ()
{
mAccessRequirements . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2010-02-25 16:26:03 +01:00
// 0 1 2 3 4 5 6 7 8 9 10 11 12
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT id, level_min, level_max, item, item2, heroic_key, heroic_key2, quest_done, quest_failed_text, heroic_quest_done, heroic_quest_failed_text, heroic_level_min, status FROM access_requirement" );
2009-04-07 10:51:45 +02:00
if ( ! result )
2009-03-05 21:02:33 +01:00
{
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-05 21:02:33 +01:00
sLog . outString ( ">> Loaded %u access requirement definitions" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
do
{
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
++ count ;
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
uint32 requiremt_ID = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
AccessRequirement ar ;
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
ar . levelMin = fields [ 1 ]. GetUInt8 ();
2009-06-08 15:31:04 -05:00
ar . levelMax = fields [ 2 ]. GetUInt8 ();
ar . heroicLevelMin = fields [ 11 ]. GetUInt8 ();
2009-03-05 21:02:33 +01:00
ar . item = fields [ 3 ]. GetUInt32 ();
ar . item2 = fields [ 4 ]. GetUInt32 ();
ar . heroicKey = fields [ 5 ]. GetUInt32 ();
ar . heroicKey2 = fields [ 6 ]. GetUInt32 ();
ar . quest = fields [ 7 ]. GetUInt32 ();
ar . questFailedText = fields [ 8 ]. GetCppString ();
ar . heroicQuest = fields [ 9 ]. GetUInt32 ();
ar . heroicQuestFailedText = fields [ 10 ]. GetCppString ();
2010-02-25 16:26:03 +01:00
ar . status = fields [ 12 ]. GetUInt8 ();
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
if ( ar . item )
2008-10-11 14:16:25 -05:00
{
2009-03-05 21:02:33 +01:00
ItemPrototype const * pProto = GetItemPrototype ( ar . item );
2008-10-11 14:16:25 -05:00
if ( ! pProto )
{
2009-03-05 21:02:33 +01:00
sLog . outError ( "Key item %u does not exist for requirement %u, removing key requirement." , ar . item , requiremt_ID );
ar . item = 0 ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
if ( ar . item2 )
2008-10-11 14:16:25 -05:00
{
2009-03-05 21:02:33 +01:00
ItemPrototype const * pProto = GetItemPrototype ( ar . item2 );
2008-10-11 14:16:25 -05:00
if ( ! pProto )
{
2009-03-05 21:02:33 +01:00
sLog . outError ( "Second item %u does not exist for requirement %u, removing key requirement." , ar . item2 , requiremt_ID );
ar . item2 = 0 ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
if ( ar . heroicKey )
2008-10-11 14:16:25 -05:00
{
2009-03-05 21:02:33 +01:00
ItemPrototype const * pProto = GetItemPrototype ( ar . heroicKey );
2008-10-11 14:16:25 -05:00
if ( ! pProto )
{
2009-03-05 21:02:33 +01:00
sLog . outError ( "Heroic key %u not exist for trigger %u, remove key requirement." , ar . heroicKey , requiremt_ID );
ar . heroicKey = 0 ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
if ( ar . heroicKey2 )
2009-02-09 08:16:34 -05:00
{
2009-03-05 21:02:33 +01:00
ItemPrototype const * pProto = GetItemPrototype ( ar . heroicKey2 );
if ( ! pProto )
2009-02-09 08:16:34 -05:00
{
2009-03-05 21:02:33 +01:00
sLog . outError ( "Second heroic key %u not exist for trigger %u, remove key requirement." , ar . heroicKey2 , requiremt_ID );
ar . heroicKey2 = 0 ;
2009-02-09 08:16:34 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-04-07 10:51:45 +02:00
if ( ar . heroicQuest )
2009-04-20 18:11:55 -05:00
{
2009-03-09 17:40:40 -06:00
QuestMap :: iterator qReqItr = mQuestTemplates . find ( ar . heroicQuest );
2009-03-10 15:33:14 -06:00
if ( qReqItr == mQuestTemplates . end ())
2009-04-07 10:51:45 +02:00
{
sLog . outErrorDb ( "Required Heroic Quest %u not exist for trigger %u, remove heroic quest done requirement." , ar . heroicQuest , requiremt_ID );
ar . heroicQuest = 0 ;
2009-04-20 18:11:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
if ( ar . quest )
2008-10-11 14:16:25 -05:00
{
2009-03-09 17:40:40 -06:00
QuestMap :: iterator qReqItr = mQuestTemplates . find ( ar . quest );
2009-03-10 15:33:14 -06:00
if ( qReqItr == mQuestTemplates . end ())
2008-10-11 14:16:25 -05:00
{
2009-03-05 21:02:33 +01:00
sLog . outErrorDb ( "Required Quest %u not exist for trigger %u, remove quest done requirement." , ar . quest , requiremt_ID );
ar . quest = 0 ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-05 21:02:33 +01:00
mAccessRequirements [ requiremt_ID ] = ar ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-05 21:02:33 +01:00
sLog . outString ( ">> Loaded %u access requirement definitions" , count );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-01-03 10:54:51 -06:00
/*
* Searches for the areatrigger which teleports players out of the given map
*/
2008-10-11 14:16:25 -05:00
AreaTrigger const * ObjectMgr :: GetGoBackTrigger ( uint32 Map ) const
{
const MapEntry * mapEntry = sMapStore . LookupEntry ( Map );
if ( ! mapEntry ) return NULL ;
2008-12-08 16:34:03 -06:00
for ( AreaTriggerMap :: const_iterator itr = mAreaTriggers . begin (); itr != mAreaTriggers . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
2008-11-14 17:03:03 -06:00
if ( itr -> second . target_mapId == mapEntry -> entrance_map )
2008-10-11 14:16:25 -05:00
{
AreaTriggerEntry const * atEntry = sAreaTriggerStore . LookupEntry ( itr -> first );
if ( atEntry && atEntry -> mapid == Map )
return & itr -> second ;
}
}
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-01-03 10:54:51 -06:00
/**
* Searches for the areatrigger which teleports players to the given map
*/
AreaTrigger const * ObjectMgr :: GetMapEntranceTrigger ( uint32 Map ) const
{
for ( AreaTriggerMap :: const_iterator itr = mAreaTriggers . begin (); itr != mAreaTriggers . end (); ++ itr )
{
if ( itr -> second . target_mapId == Map )
{
AreaTriggerEntry const * atEntry = sAreaTriggerStore . LookupEntry ( itr -> first );
if ( atEntry )
return & itr -> second ;
}
}
return NULL ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: SetHighestGuids ()
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT MAX(guid) FROM characters" );
2008-10-11 14:16:25 -05:00
if ( result )
m_hiCharGuid = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
result = WorldDatabase . Query ( "SELECT MAX(guid) FROM creature" );
if ( result )
m_hiCreatureGuid = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
result = CharacterDatabase . Query ( "SELECT MAX(guid) FROM item_instance" );
if ( result )
m_hiItemGuid = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Cleanup other tables from not existed guids (>=m_hiItemGuid)
CharacterDatabase . PExecute ( "DELETE FROM character_inventory WHERE item >= '%u'" , m_hiItemGuid );
CharacterDatabase . PExecute ( "DELETE FROM mail_items WHERE item_guid >= '%u'" , m_hiItemGuid );
CharacterDatabase . PExecute ( "DELETE FROM auctionhouse WHERE itemguid >= '%u'" , m_hiItemGuid );
CharacterDatabase . PExecute ( "DELETE FROM guild_bank_item WHERE item_guid >= '%u'" , m_hiItemGuid );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
result = WorldDatabase . Query ( "SELECT MAX(guid) FROM gameobject" );
if ( result )
m_hiGoGuid = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
result = CharacterDatabase . Query ( "SELECT MAX(id) FROM auctionhouse" );
if ( result )
m_auctionid = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
result = CharacterDatabase . Query ( "SELECT MAX(id) FROM mail" );
if ( result )
m_mailid = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
result = CharacterDatabase . Query ( "SELECT MAX(id) FROM item_text" );
if ( result )
2008-11-20 16:16:57 -06:00
m_ItemTextId = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
result = CharacterDatabase . Query ( "SELECT MAX(guid) FROM corpse" );
if ( result )
m_hiCorpseGuid = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
result = CharacterDatabase . Query ( "SELECT MAX(arenateamid) FROM arena_team" );
if ( result )
m_arenaTeamId = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
result = CharacterDatabase . Query ( "SELECT MAX(setguid) FROM character_equipmentsets" );
if ( result )
m_equipmentSetGuid = ( * result )[ 0 ]. GetUInt64 () + 1 ;
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
result = CharacterDatabase . Query ( "SELECT MAX(guildid) FROM guild" );
if ( result )
m_guildId = ( * result )[ 0 ]. GetUInt32 () + 1 ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
uint32 ObjectMgr :: GenerateArenaTeamId ()
{
if ( m_arenaTeamId >= 0xFFFFFFFE )
{
sLog . outError ( "Arena team ids overflow!! Can't continue, shutting down server. " );
World :: StopNow ( ERROR_EXIT_CODE );
}
return m_arenaTeamId ++ ;
}
2009-10-17 15:51:44 -07:00
2009-02-13 19:50:20 -06:00
uint32 ObjectMgr :: GenerateAuctionID ()
2008-11-20 16:16:57 -06:00
{
2009-02-13 19:50:20 -06:00
if ( m_auctionid >= 0xFFFFFFFE )
2008-11-20 16:16:57 -06:00
{
2009-02-13 19:50:20 -06:00
sLog . outError ( "Auctions ids overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
}
2009-02-13 19:50:20 -06:00
return m_auctionid ++ ;
2008-11-20 16:16:57 -06:00
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
uint64 ObjectMgr :: GenerateEquipmentSetGuid ()
{
if ( m_equipmentSetGuid >= 0xFFFFFFFFFFFFFFFEll )
{
sLog . outError ( "EquipmentSet guid overflow!! Can't continue, shutting down server. " );
World :: StopNow ( ERROR_EXIT_CODE );
}
return m_equipmentSetGuid ++ ;
}
2009-10-17 15:51:44 -07:00
2009-02-13 19:50:20 -06:00
uint32 ObjectMgr :: GenerateGuildId ()
2008-10-11 14:16:25 -05:00
{
2009-02-13 19:50:20 -06:00
if ( m_guildId >= 0xFFFFFFFE )
2008-10-11 14:16:25 -05:00
{
2009-02-13 19:50:20 -06:00
sLog . outError ( "Guild ids overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2009-02-13 19:50:20 -06:00
return m_guildId ++ ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 ObjectMgr :: GenerateMailID ()
{
2008-11-20 16:16:57 -06:00
if ( m_mailid >= 0xFFFFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Mail ids overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_mailid ++ ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 ObjectMgr :: GenerateItemTextID ()
{
2008-11-20 16:16:57 -06:00
if ( m_ItemTextId >= 0xFFFFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Item text ids overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_ItemTextId ++ ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 ObjectMgr :: CreateItemText ( std :: string text )
{
uint32 newItemTextId = GenerateItemTextID ();
//insert new itempage to container
mItemTexts [ newItemTextId ] = text ;
//save new itempage
CharacterDatabase . escape_string ( text );
//any Delete query needed, itemTextId is maximum of all ids
std :: ostringstream query ;
query << "INSERT INTO item_text (id,text) VALUES ( '" << newItemTextId << "', '" << text << "')" ;
CharacterDatabase . Execute ( query . str (). c_str ()); //needs to be run this way, because mail body may be more than 1024 characters
return newItemTextId ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 ObjectMgr :: GenerateLowGuid ( HighGuid guidhigh )
{
switch ( guidhigh )
{
case HIGHGUID_ITEM :
2008-11-20 16:16:57 -06:00
if ( m_hiItemGuid >= 0xFFFFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Item guid overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_hiItemGuid ++ ;
2008-10-11 14:16:25 -05:00
case HIGHGUID_UNIT :
2008-11-20 16:16:57 -06:00
if ( m_hiCreatureGuid >= 0x00FFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Creature guid overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_hiCreatureGuid ++ ;
2008-10-11 14:16:25 -05:00
case HIGHGUID_PET :
2008-11-20 16:16:57 -06:00
if ( m_hiPetGuid >= 0x00FFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Pet guid overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_hiPetGuid ++ ;
2008-12-24 09:58:26 -06:00
case HIGHGUID_VEHICLE :
if ( m_hiVehicleGuid >= 0x00FFFFFF )
{
sLog . outError ( "Vehicle guid overflow!! Can't continue, shutting down server. " );
World :: StopNow ( ERROR_EXIT_CODE );
}
return m_hiVehicleGuid ++ ;
2008-10-11 14:16:25 -05:00
case HIGHGUID_PLAYER :
2008-11-20 16:16:57 -06:00
if ( m_hiCharGuid >= 0xFFFFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Players guid overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_hiCharGuid ++ ;
2008-10-11 14:16:25 -05:00
case HIGHGUID_GAMEOBJECT :
2008-11-20 16:16:57 -06:00
if ( m_hiGoGuid >= 0x00FFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Gameobject guid overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_hiGoGuid ++ ;
2008-10-11 14:16:25 -05:00
case HIGHGUID_CORPSE :
2008-11-20 16:16:57 -06:00
if ( m_hiCorpseGuid >= 0xFFFFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "Corpse guid overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_hiCorpseGuid ++ ;
2008-10-11 14:16:25 -05:00
case HIGHGUID_DYNAMICOBJECT :
2008-11-20 16:16:57 -06:00
if ( m_hiDoGuid >= 0xFFFFFFFE )
2008-10-11 14:16:25 -05:00
{
2008-11-14 16:28:45 -06:00
sLog . outError ( "DynamicObject guid overflow!! Can't continue, shutting down server. " );
2008-11-20 16:16:57 -06:00
World :: StopNow ( ERROR_EXIT_CODE );
2008-10-11 14:16:25 -05:00
}
2008-11-20 16:16:57 -06:00
return m_hiDoGuid ++ ;
2008-10-11 14:16:25 -05:00
default :
ASSERT ( 0 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ASSERT ( 0 );
return 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameObjectLocales ()
{
2008-11-20 16:16:57 -06:00
mGameObjectLocaleMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,"
2008-10-11 14:16:25 -05:00
"name_loc1,name_loc2,name_loc3,name_loc4,name_loc5,name_loc6,name_loc7,name_loc8,"
"castbarcaption_loc1,castbarcaption_loc2,castbarcaption_loc3,castbarcaption_loc4,"
"castbarcaption_loc5,castbarcaption_loc6,castbarcaption_loc7,castbarcaption_loc8 FROM locales_gameobject" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
GameObjectLocale & data = mGameObjectLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
std :: string str = fields [ i ]. GetCppString ();
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . Name . size () <= idx )
data . Name . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Name [ idx ] = str ;
}
}
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
2009-02-23 21:06:41 -06:00
std :: string str = fields [ i + ( MAX_LOCALE - 1 )]. GetCppString ();
2008-10-11 14:16:25 -05:00
if ( ! str . empty ())
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
if ( idx >= 0 )
{
if ( data . CastBarCaption . size () <= idx )
data . CastBarCaption . resize ( idx + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . CastBarCaption [ idx ] = str ;
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-03-24 17:38:14 -06:00
sLog . outString ( ">> Loaded %lu gameobject locale strings" , ( unsigned long ) mGameObjectLocaleMap . size () );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
struct SQLGameObjectLoader : public SQLStorageLoaderBase < SQLGameObjectLoader >
{
template < class D >
2009-04-29 00:31:03 -05:00
void convert_from_str ( uint32 /*field_pos*/ , char * src , D & dst )
2008-11-20 16:16:57 -06:00
{
dst = D ( objmgr . GetScriptId ( src ));
}
};
2009-10-17 15:51:44 -07:00
2009-04-08 16:38:07 -05:00
inline void CheckGOLockId ( GameObjectInfo const * goInfo , uint32 dataN , uint32 N )
{
2009-04-08 16:39:49 -05:00
if ( sLockStore . LookupEntry ( dataN ))
2009-04-08 16:38:07 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:38:07 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data%d=%u but lock (Id: %u) not found." ,
goInfo -> id , goInfo -> type , N , goInfo -> door . lockId , goInfo -> door . lockId );
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:38:58 -05:00
inline void CheckGOLinkedTrapId ( GameObjectInfo const * goInfo , uint32 dataN , uint32 N )
{
2009-04-08 16:39:49 -05:00
if ( GameObjectInfo const * trapInfo = sGOStorage . LookupEntry < GameObjectInfo > ( dataN ))
2009-04-08 16:38:58 -05:00
{
2009-04-08 16:39:49 -05:00
if ( trapInfo -> type != GAMEOBJECT_TYPE_TRAP )
2009-04-08 16:38:58 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data%d=%u but GO (Entry %u) have not GAMEOBJECT_TYPE_TRAP (%u) type." ,
goInfo -> id , goInfo -> type , N , dataN , dataN , GAMEOBJECT_TYPE_TRAP );
}
/* disable check for while (too many error reports baout not existed in trap templates
else
sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data%d=%u but trap GO (Entry %u) not exist in `gameobject_template`.",
goInfo->id,goInfo->type,N,dataN,dataN);
*/
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
inline void CheckGOSpellId ( GameObjectInfo const * goInfo , uint32 dataN , uint32 N )
{
if ( sSpellStore . LookupEntry ( dataN ))
return ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data%d=%u but Spell (Entry %u) not exist." ,
goInfo -> id , goInfo -> type , N , dataN , dataN );
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
inline void CheckAndFixGOChairHeightId ( GameObjectInfo const * goInfo , uint32 const & dataN , uint32 N )
{
if ( dataN <= ( UNIT_STAND_STATE_SIT_HIGH_CHAIR - UNIT_STAND_STATE_SIT_LOW_CHAIR ) )
return ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data%d=%u but correct chair height in range 0..%i." ,
goInfo -> id , goInfo -> type , N , dataN , UNIT_STAND_STATE_SIT_HIGH_CHAIR - UNIT_STAND_STATE_SIT_LOW_CHAIR );
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
// prevent client and server unexpected work
const_cast < uint32 &> ( dataN ) = 0 ;
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:40:26 -05:00
inline void CheckGONoDamageImmuneId ( GameObjectInfo const * goInfo , uint32 dataN , uint32 N )
{
// 0/1 correct values
if ( dataN <= 1 )
return ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:40:26 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) noDamageImmune field value." ,
goInfo -> id , goInfo -> type , N , dataN );
}
2009-10-17 15:51:44 -07:00
2009-07-16 12:06:07 +08:00
inline void CheckGOConsumable ( GameObjectInfo const * goInfo , uint32 dataN , uint32 N )
{
// 0/1 correct values
if ( dataN <= 1 )
return ;
2009-10-17 15:51:44 -07:00
2009-07-16 12:06:07 +08:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data%d=%u but expected boolean (0/1) consumable field value." ,
goInfo -> id , goInfo -> type , N , dataN );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameobjectInfo ()
{
2008-11-20 16:16:57 -06:00
SQLGameObjectLoader loader ;
loader . Load ( sGOStorage );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// some checks
2009-10-17 16:20:24 -07:00
for ( uint32 id = 1 ; id < sGOStorage . MaxEntry ; id ++ )
2008-10-11 14:16:25 -05:00
{
GameObjectInfo const * goInfo = sGOStorage . LookupEntry < GameObjectInfo > ( id );
2009-04-08 16:39:49 -05:00
if ( ! goInfo )
2008-10-11 14:16:25 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-06-13 09:40:44 -05:00
// some GO types have unused go template, check goInfo->displayId at GO spawn data loading or ignore
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
switch ( goInfo -> type )
{
case GAMEOBJECT_TYPE_DOOR : //0
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> door . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> door . lockId , 1 );
2009-04-08 16:40:26 -05:00
CheckGONoDamageImmuneId ( goInfo , goInfo -> door . noDamageImmune , 3 );
2008-10-11 14:16:25 -05:00
break ;
}
case GAMEOBJECT_TYPE_BUTTON : //1
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> button . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> button . lockId , 1 );
2009-04-08 16:40:26 -05:00
CheckGONoDamageImmuneId ( goInfo , goInfo -> button . noDamageImmune , 4 );
2009-04-08 16:38:07 -05:00
break ;
}
case GAMEOBJECT_TYPE_QUESTGIVER : //2
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> questgiver . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> questgiver . lockId , 0 );
2009-04-08 16:40:26 -05:00
CheckGONoDamageImmuneId ( goInfo , goInfo -> questgiver . noDamageImmune , 5 );
2008-10-11 14:16:25 -05:00
break ;
}
case GAMEOBJECT_TYPE_CHEST : //3
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> chest . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> chest . lockId , 0 );
2009-10-17 15:51:44 -07:00
2009-07-16 12:06:07 +08:00
CheckGOConsumable ( goInfo , goInfo -> chest . consumable , 3 );
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
if ( goInfo -> chest . linkedTrapId ) // linked trap
2009-04-08 16:38:58 -05:00
CheckGOLinkedTrapId ( goInfo , goInfo -> chest . linkedTrapId , 7 );
2008-10-11 14:16:25 -05:00
break ;
}
case GAMEOBJECT_TYPE_TRAP : //6
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> trap . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> trap . lockId , 0 );
2009-04-08 16:39:49 -05:00
/* disable check for while, too many not existed spells
if (goInfo->trap.spellId) // spell
CheckGOSpellId(goInfo,goInfo->trap.spellId,3);
2008-10-11 14:16:25 -05:00
*/
break ;
}
case GAMEOBJECT_TYPE_CHAIR : //7
2009-04-08 16:39:49 -05:00
CheckAndFixGOChairHeightId ( goInfo , goInfo -> chair . height , 1 );
2008-10-11 14:16:25 -05:00
break ;
case GAMEOBJECT_TYPE_SPELL_FOCUS : //8
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> spellFocus . focusId )
2008-10-11 14:16:25 -05:00
{
2009-04-08 16:39:49 -05:00
if ( ! sSpellFocusObjectStore . LookupEntry ( goInfo -> spellFocus . focusId ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data0=%u but SpellFocus (Id: %u) not exist." ,
id , goInfo -> type , goInfo -> spellFocus . focusId , goInfo -> spellFocus . focusId );
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
if ( goInfo -> spellFocus . linkedTrapId ) // linked trap
2009-04-08 16:38:58 -05:00
CheckGOLinkedTrapId ( goInfo , goInfo -> spellFocus . linkedTrapId , 2 );
2008-10-11 14:16:25 -05:00
break ;
}
case GAMEOBJECT_TYPE_GOOBER : //10
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> goober . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> goober . lockId , 0 );
2009-10-17 15:51:44 -07:00
2009-07-16 12:06:07 +08:00
CheckGOConsumable ( goInfo , goInfo -> goober . consumable , 3 );
2009-10-17 15:51:44 -07:00
2009-04-08 16:39:49 -05:00
if ( goInfo -> goober . pageId ) // pageId
2008-10-11 14:16:25 -05:00
{
2009-04-08 16:39:49 -05:00
if ( ! sPageTextStore . LookupEntry < PageText > ( goInfo -> goober . pageId ))
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data7=%u but PageText (Entry %u) not exist." ,
id , goInfo -> type , goInfo -> goober . pageId , goInfo -> goober . pageId );
}
2009-04-08 16:39:49 -05:00
/* disable check for while, too many not existed spells
if (goInfo->goober.spellId) // spell
CheckGOSpellId(goInfo,goInfo->goober.spellId,10);
2008-10-11 14:16:25 -05:00
*/
2009-04-08 16:40:26 -05:00
CheckGONoDamageImmuneId ( goInfo , goInfo -> goober . noDamageImmune , 11 );
2009-04-08 16:39:49 -05:00
if ( goInfo -> goober . linkedTrapId ) // linked trap
2009-04-08 16:38:58 -05:00
CheckGOLinkedTrapId ( goInfo , goInfo -> goober . linkedTrapId , 12 );
2008-10-11 14:16:25 -05:00
break ;
}
2009-04-08 16:38:07 -05:00
case GAMEOBJECT_TYPE_AREADAMAGE : //12
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> areadamage . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> areadamage . lockId , 0 );
break ;
}
case GAMEOBJECT_TYPE_CAMERA : //13
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> camera . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> camera . lockId , 0 );
break ;
}
2008-10-11 14:16:25 -05:00
case GAMEOBJECT_TYPE_MO_TRANSPORT : //15
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> moTransport . taxiPathId )
2008-10-11 14:16:25 -05:00
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> moTransport . taxiPathId >= sTaxiPathNodesByPath . size () || sTaxiPathNodesByPath [ goInfo -> moTransport . taxiPathId ]. empty ())
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( "Gameobject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist." ,
id , goInfo -> type , goInfo -> moTransport . taxiPathId , goInfo -> moTransport . taxiPathId );
}
break ;
}
case GAMEOBJECT_TYPE_SUMMONING_RITUAL : //18
{
2009-04-08 16:39:49 -05:00
/* disable check for while, too many not existed spells
// always must have spell
CheckGOSpellId(goInfo,goInfo->summoningRitual.spellId,1);
2008-10-11 14:16:25 -05:00
*/
break ;
}
case GAMEOBJECT_TYPE_SPELLCASTER : //22
{
2009-04-08 16:39:49 -05:00
// always must have spell
CheckGOSpellId ( goInfo , goInfo -> spellcaster . spellId , 0 );
2008-10-11 14:16:25 -05:00
break ;
}
2009-04-08 16:38:07 -05:00
case GAMEOBJECT_TYPE_FLAGSTAND : //24
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> flagstand . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> flagstand . lockId , 0 );
2009-04-08 16:40:26 -05:00
CheckGONoDamageImmuneId ( goInfo , goInfo -> flagstand . noDamageImmune , 5 );
2009-04-08 16:38:07 -05:00
break ;
}
case GAMEOBJECT_TYPE_FISHINGHOLE : //25
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> fishinghole . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> fishinghole . lockId , 4 );
break ;
}
case GAMEOBJECT_TYPE_FLAGDROP : //26
{
2009-04-08 16:39:49 -05:00
if ( goInfo -> flagdrop . lockId )
2009-04-08 16:38:07 -05:00
CheckGOLockId ( goInfo , goInfo -> flagdrop . lockId , 0 );
2009-04-08 16:40:26 -05:00
CheckGONoDamageImmuneId ( goInfo , goInfo -> flagdrop . noDamageImmune , 3 );
2009-04-08 16:38:07 -05:00
break ;
}
2009-01-31 14:41:36 -06:00
case GAMEOBJECT_TYPE_BARBER_CHAIR : //32
2009-04-08 16:39:49 -05:00
CheckAndFixGOChairHeightId ( goInfo , goInfo -> barberChair . chairheight , 0 );
2009-01-31 14:41:36 -06:00
break ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u game object templates" , sGOStorage . RecordCount );
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadExplorationBaseXP ()
{
uint32 count = 0 ;
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT level,basexp FROM exploration_basexp" );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-11-01 17:53:07 -08:00
sLog . outString ( ">> Loaded %u BaseXP definitions" , count );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-11-01 17:53:07 -08:00
uint8 level = fields [ 0 ]. GetUInt8 ();
2008-10-11 14:16:25 -05:00
uint32 basexp = fields [ 1 ]. GetUInt32 ();
mBaseXPTable [ level ] = basexp ;
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u BaseXP definitions" , count );
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
uint32 ObjectMgr :: GetBaseXP ( uint8 level )
2008-10-11 14:16:25 -05:00
{
return mBaseXPTable [ level ] ? mBaseXPTable [ level ] : 0 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
uint32 ObjectMgr :: GetXPForLevel ( uint8 level )
2009-01-16 14:17:24 -06:00
{
if ( level < mPlayerXPperLevel . size ())
return mPlayerXPperLevel [ level ];
return 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadPetNames ()
{
uint32 count = 0 ;
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT word,entry,half FROM pet_name_generation" );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u pet name parts" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
std :: string word = fields [ 0 ]. GetString ();
uint32 entry = fields [ 1 ]. GetUInt32 ();
bool half = fields [ 2 ]. GetBool ();
2009-11-01 17:53:07 -08:00
if ( half )
2008-10-11 14:16:25 -05:00
PetHalfName1 [ entry ]. push_back ( word );
else
PetHalfName0 [ entry ]. push_back ( word );
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u pet name parts" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadPetNumber ()
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT MAX(id) FROM character_pet" );
2009-11-01 17:53:07 -08:00
if ( result )
2008-10-11 14:16:25 -05:00
{
Field * fields = result -> Fetch ();
m_hiPetNumber = fields [ 0 ]. GetUInt32 () + 1 ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
barGoLink bar ( 1 );
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded the max pet number: %d" , m_hiPetNumber - 1 );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
std :: string ObjectMgr :: GeneratePetName ( uint32 entry )
{
std :: vector < std :: string > & list0 = PetHalfName0 [ entry ];
std :: vector < std :: string > & list1 = PetHalfName1 [ entry ];
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( list0 . empty () || list1 . empty ())
2008-10-11 14:16:25 -05:00
{
CreatureInfo const * cinfo = GetCreatureTemplate ( entry );
char * petname = GetPetName ( cinfo -> family , sWorld . GetDefaultDbcLocale ());
2009-11-01 17:53:07 -08:00
if ( ! petname )
2008-10-11 14:16:25 -05:00
petname = cinfo -> Name ;
return std :: string ( petname );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return * ( list0 . begin () + urand ( 0 , list0 . size () - 1 )) + * ( list1 . begin () + urand ( 0 , list1 . size () - 1 ));
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 ObjectMgr :: GeneratePetNumber ()
{
return ++ m_hiPetNumber ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCorpses ()
{
uint32 count = 0 ;
2009-11-01 17:53:07 -08:00
// 0 1 2 3 4 5 6 7 8 10
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT position_x, position_y, position_z, orientation, map, data, time, corpse_type, instance, guid FROM corpse WHERE corpse_type <> 0" );
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
2009-11-01 17:53:07 -08:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-11-01 17:53:07 -08:00
sLog . outString ( ">> Loaded %u corpses" , count );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 guid = fields [ result -> GetFieldCount () - 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Corpse * corpse = new Corpse ;
2009-11-01 17:53:07 -08:00
if ( ! corpse -> LoadFromDB ( guid , fields ))
2008-10-11 14:16:25 -05:00
{
delete corpse ;
continue ;
}
2009-10-17 15:51:44 -07:00
2009-08-03 12:52:31 +02:00
ObjectAccessor :: Instance (). AddCorpse ( corpse );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-11-01 17:53:07 -08:00
sLog . outString ( ">> Loaded %u corpses" , count );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadReputationOnKill ()
{
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0 1 2
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT creature_id, RewOnKillRepFaction1, RewOnKillRepFaction2,"
2008-10-11 14:16:25 -05:00
// 3 4 5 6 7 8 9
"IsTeamAward1, MaxStanding1, RewOnKillRepValue1, IsTeamAward2, MaxStanding2, RewOnKillRepValue2, TeamDependent "
"FROM creature_onkill_reputation" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 creature_id = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
ReputationOnKillEntry repOnKill ;
repOnKill . repfaction1 = fields [ 1 ]. GetUInt32 ();
repOnKill . repfaction2 = fields [ 2 ]. GetUInt32 ();
repOnKill . is_teamaward1 = fields [ 3 ]. GetBool ();
repOnKill . reputation_max_cap1 = fields [ 4 ]. GetUInt32 ();
repOnKill . repvalue1 = fields [ 5 ]. GetInt32 ();
repOnKill . is_teamaward2 = fields [ 6 ]. GetBool ();
repOnKill . reputation_max_cap2 = fields [ 7 ]. GetUInt32 ();
repOnKill . repvalue2 = fields [ 8 ]. GetInt32 ();
repOnKill . team_dependent = fields [ 9 ]. GetUInt8 ();
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( ! GetCreatureTemplate ( creature_id ))
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Table `creature_onkill_reputation` have data for not existed creature entry (%u), skipped" , creature_id );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( repOnKill . repfaction1 )
2008-10-11 14:16:25 -05:00
{
FactionEntry const * factionEntry1 = sFactionStore . LookupEntry ( repOnKill . repfaction1 );
2009-11-01 17:53:07 -08:00
if ( ! factionEntry1 )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`" , repOnKill . repfaction1 );
continue ;
}
}
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
if ( repOnKill . repfaction2 )
2008-10-11 14:16:25 -05:00
{
FactionEntry const * factionEntry2 = sFactionStore . LookupEntry ( repOnKill . repfaction2 );
2009-11-01 17:53:07 -08:00
if ( ! factionEntry2 )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`" , repOnKill . repfaction2 );
continue ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mRepOnKill [ creature_id ] = repOnKill ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u creature award reputation definitions" , count );
}
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
void ObjectMgr :: LoadPointsOfInterest ()
{
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2009-11-01 17:53:07 -08:00
// 0 1 2 3 4 5 6
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, x, y, icon, flags, data, icon_name FROM points_of_interest" );
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-02-17 17:40:03 -06:00
sLog . outErrorDb ( ">> Loaded 0 Points of Interest definitions. DB table `points_of_interest` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
uint32 point_id = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
PointOfInterest POI ;
POI . x = fields [ 1 ]. GetFloat ();
POI . y = fields [ 2 ]. GetFloat ();
POI . icon = fields [ 3 ]. GetUInt32 ();
POI . flags = fields [ 4 ]. GetUInt32 ();
POI . data = fields [ 5 ]. GetUInt32 ();
POI . icon_name = fields [ 6 ]. GetCppString ();
2009-10-17 15:51:44 -07:00
2009-12-20 15:20:04 +01:00
if ( ! Trinity :: IsValidMapCoord ( POI . x , POI . y ))
2009-02-17 17:40:03 -06:00
{
sLog . outErrorDb ( "Table `points_of_interest` (Entry: %u) have invalid coordinates (X: %f Y: %f), ignored." , point_id , POI . x , POI . y );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
mPointsOfInterest [ point_id ] = POI ;
2009-10-17 15:51:44 -07:00
2009-02-17 17:40:03 -06:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-02-17 17:40:03 -06:00
sLog . outString ( ">> Loaded %u Points of Interest definitions" , count );
}
2009-10-17 15:51:44 -07:00
2010-02-14 19:13:14 -07:00
void ObjectMgr :: LoadQuestPOI ()
{
uint32 count = 0 ;
// 0 1 2 3
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT questId, id, objIndex, mapid, WorldMapAreaId, FloorId, unk3, unk4 FROM quest_poi order by questId" );
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outErrorDb ( ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty." );
return ;
}
barGoLink bar ( result -> GetRowCount ());
do
{
Field * fields = result -> Fetch ();
bar . step ();
uint32 questId = fields [ 0 ]. GetUInt32 ();
uint32 id = fields [ 1 ]. GetUInt32 ();
int32 objIndex = fields [ 2 ]. GetInt32 ();
uint32 mapId = fields [ 3 ]. GetUInt32 ();
uint32 WorldMapAreaId = fields [ 4 ]. GetUInt32 ();
uint32 FloorId = fields [ 5 ]. GetUInt32 ();
uint32 unk3 = fields [ 6 ]. GetUInt32 ();
uint32 unk4 = fields [ 7 ]. GetUInt32 ();
QuestPOI POI ( objIndex , mapId , WorldMapAreaId , FloorId , unk3 , unk4 );
QueryResult_AutoPtr points = WorldDatabase . PQuery ( "SELECT x, y FROM quest_poi_points WHERE questId='%u' AND id='%i'" , questId , id );
if ( points )
{
do
{
Field * pointFields = points -> Fetch ();
int32 x = pointFields [ 0 ]. GetInt32 ();
int32 y = pointFields [ 1 ]. GetInt32 ();
QuestPOIPoint point ( x , y );
POI . points . push_back ( point );
} while ( points -> NextRow ());
}
mQuestPOIMap [ questId ]. push_back ( POI );
++ count ;
} while ( result -> NextRow ());
sLog . outString ();
sLog . outString ( ">> Loaded %u quest POI definitions" , count );
}
2009-05-05 16:56:15 -05:00
void ObjectMgr :: LoadNPCSpellClickSpells ()
{
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
mSpellClickInfoMap . clear ();
2009-08-17 02:53:39 +02:00
// 0 1 2 3 4 5 6 7 8
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT npc_entry, spell_id, quest_start, quest_start_active, quest_end, cast_flags, aura_required, aura_forbidden, user_type FROM npc_spellclick_spells" );
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
sLog . outString ();
sLog . outErrorDb ( ">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
uint32 npc_entry = fields [ 0 ]. GetUInt32 ();
CreatureInfo const * cInfo = GetCreatureTemplate ( npc_entry );
if ( ! cInfo )
{
sLog . outErrorDb ( "Table npc_spellclick_spells references unknown creature_template %u. Skipping entry." , npc_entry );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-06-08 23:43:25 -05:00
if ( ! ( cInfo -> npcflag & UNIT_NPC_FLAG_SPELLCLICK ))
const_cast < CreatureInfo *> ( cInfo ) -> npcflag |= UNIT_NPC_FLAG_SPELLCLICK ;
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
uint32 spellid = fields [ 1 ]. GetUInt32 ();
SpellEntry const * spellinfo = sSpellStore . LookupEntry ( spellid );
if ( ! spellinfo )
{
sLog . outErrorDb ( "Table npc_spellclick_spells references unknown spellid %u. Skipping entry." , spellid );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
uint32 auraRequired = fields [ 6 ]. GetUInt32 ();
if ( auraRequired )
{
SpellEntry const * aurReqInfo = sSpellStore . LookupEntry ( auraRequired );
if ( ! aurReqInfo )
{
sLog . outErrorDb ( "Table npc_spellclick_spells references unknown aura required %u. Skipping entry." , auraRequired );
continue ;
}
}
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
uint32 auraForbidden = fields [ 7 ]. GetUInt32 ();
if ( auraForbidden )
{
SpellEntry const * aurForInfo = sSpellStore . LookupEntry ( auraForbidden );
if ( ! aurForInfo )
{
sLog . outErrorDb ( "Table npc_spellclick_spells references unknown aura forbidden %u. Skipping entry." , auraForbidden );
continue ;
}
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
uint32 quest_start = fields [ 2 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
// quest might be 0 to enable spellclick independent of any quest
2009-06-15 23:07:43 -05:00
if ( quest_start )
2009-05-05 16:56:15 -05:00
{
2009-06-15 23:07:43 -05:00
if ( mQuestTemplates . find ( quest_start ) == mQuestTemplates . end ())
2009-05-05 16:56:15 -05:00
{
2009-06-15 23:07:43 -05:00
sLog . outErrorDb ( "Table npc_spellclick_spells references unknown start quest %u. Skipping entry." , quest_start );
2009-05-05 16:56:15 -05:00
continue ;
}
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
bool quest_start_active = fields [ 3 ]. GetBool ();
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
uint32 quest_end = fields [ 4 ]. GetUInt32 ();
// quest might be 0 to enable spellclick active infinity after start quest
if ( quest_end )
{
if ( mQuestTemplates . find ( quest_end ) == mQuestTemplates . end ())
{
sLog . outErrorDb ( "Table npc_spellclick_spells references unknown end quest %u. Skipping entry." , quest_end );
continue ;
}
}
2009-10-17 15:51:44 -07:00
2009-08-17 02:53:39 +02:00
uint8 userType = fields [ 8 ]. GetUInt8 ();
if ( userType >= SPELL_CLICK_USER_MAX )
sLog . outErrorDb ( "Table npc_spellclick_spells references unknown user type %u. Skipping entry." , uint32 ( userType ));
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
uint8 castFlags = fields [ 5 ]. GetUInt8 ();
2009-05-05 16:56:15 -05:00
SpellClickInfo info ;
info . spellId = spellid ;
2009-06-15 23:07:43 -05:00
info . questStart = quest_start ;
info . questStartCanActive = quest_start_active ;
info . questEnd = quest_end ;
2009-05-05 16:56:15 -05:00
info . castFlags = castFlags ;
2009-08-17 02:53:39 +02:00
info . auraRequired = auraRequired ;
info . auraForbidden = auraForbidden ;
2009-08-17 19:29:33 +02:00
info . userType = SpellClickUserTypes ( userType );
2009-05-05 16:56:15 -05:00
mSpellClickInfoMap . insert ( SpellClickInfoMap :: value_type ( npc_entry , info ));
2009-10-17 15:51:44 -07:00
2009-06-15 23:07:43 -05:00
// mark creature template as spell clickable
const_cast < CreatureInfo *> ( cInfo ) -> npcflag |= UNIT_NPC_FLAG_SPELLCLICK ;
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
sLog . outString ();
sLog . outString ( ">> Loaded %u spellclick definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadWeatherZoneChances ()
{
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0 1 2 3 4 5 6 7 8 9 10 11 12
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT zone, spring_rain_chance, spring_snow_chance, spring_storm_chance, summer_rain_chance, summer_snow_chance, summer_storm_chance, fall_rain_chance, fall_snow_chance, fall_storm_chance, winter_rain_chance, winter_snow_chance, winter_storm_chance FROM game_weather" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded 0 weather definitions. DB table `game_weather` is empty." );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 zone_id = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WeatherZoneChances & wzc = mWeatherZoneMap [ zone_id ];
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 season = 0 ; season < WEATHER_SEASONS ; ++ season )
2008-10-11 14:16:25 -05:00
{
wzc . data [ season ]. rainChance = fields [ season * ( MAX_WEATHER_TYPE - 1 ) + 1 ]. GetUInt32 ();
wzc . data [ season ]. snowChance = fields [ season * ( MAX_WEATHER_TYPE - 1 ) + 2 ]. GetUInt32 ();
wzc . data [ season ]. stormChance = fields [ season * ( MAX_WEATHER_TYPE - 1 ) + 3 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( wzc . data [ season ]. rainChance > 100 )
{
wzc . data [ season ]. rainChance = 25 ;
2009-02-24 11:14:28 -06:00
sLog . outErrorDb ( "Weather for zone %u season %u has wrong rain chance > 100%%" , zone_id , season );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( wzc . data [ season ]. snowChance > 100 )
{
wzc . data [ season ]. snowChance = 25 ;
2009-02-24 11:14:28 -06:00
sLog . outErrorDb ( "Weather for zone %u season %u has wrong snow chance > 100%%" , zone_id , season );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( wzc . data [ season ]. stormChance > 100 )
{
wzc . data [ season ]. stormChance = 25 ;
2009-02-24 11:14:28 -06:00
sLog . outErrorDb ( "Weather for zone %u season %u has wrong storm chance > 100%%" , zone_id , season );
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u weather definitions" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: SaveCreatureRespawnTime ( uint32 loguid , uint32 instance , time_t t )
{
mCreatureRespawnTimes [ MAKE_PAIR64 ( loguid , instance )] = t ;
WorldDatabase . PExecute ( "DELETE FROM creature_respawn WHERE guid = '%u' AND instance = '%u'" , loguid , instance );
if ( t )
2009-05-31 16:15:12 -05:00
WorldDatabase . PExecute ( "INSERT INTO creature_respawn VALUES ( '%u', '" UI64FMTD "', '%u' )" , loguid , uint64 ( t ), instance );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: DeleteCreatureData ( uint32 guid )
{
// remove mapid*cellid -> guid_set map
CreatureData const * data = GetCreatureData ( guid );
if ( data )
RemoveCreatureFromGrid ( guid , data );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mCreatureDataMap . erase ( guid );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: SaveGORespawnTime ( uint32 loguid , uint32 instance , time_t t )
{
mGORespawnTimes [ MAKE_PAIR64 ( loguid , instance )] = t ;
WorldDatabase . PExecute ( "DELETE FROM gameobject_respawn WHERE guid = '%u' AND instance = '%u'" , loguid , instance );
if ( t )
2009-05-31 16:15:12 -05:00
WorldDatabase . PExecute ( "INSERT INTO gameobject_respawn VALUES ( '%u', '" UI64FMTD "', '%u' )" , loguid , uint64 ( t ), instance );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: DeleteRespawnTimeForInstance ( uint32 instance )
{
RespawnTimes :: iterator next ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( RespawnTimes :: iterator itr = mGORespawnTimes . begin (); itr != mGORespawnTimes . end (); itr = next )
2008-10-11 14:16:25 -05:00
{
next = itr ;
++ next ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( GUID_HIPART ( itr -> first ) == instance )
mGORespawnTimes . erase ( itr );
}
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( RespawnTimes :: iterator itr = mCreatureRespawnTimes . begin (); itr != mCreatureRespawnTimes . end (); itr = next )
2008-10-11 14:16:25 -05:00
{
next = itr ;
++ next ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( GUID_HIPART ( itr -> first ) == instance )
mCreatureRespawnTimes . erase ( itr );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldDatabase . PExecute ( "DELETE FROM creature_respawn WHERE instance = '%u'" , instance );
WorldDatabase . PExecute ( "DELETE FROM gameobject_respawn WHERE instance = '%u'" , instance );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: DeleteGOData ( uint32 guid )
{
// remove mapid*cellid -> guid_set map
GameObjectData const * data = GetGOData ( guid );
if ( data )
RemoveGameobjectFromGrid ( guid , data );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mGameObjectDataMap . erase ( guid );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: AddCorpseCellData ( uint32 mapid , uint32 cellid , uint32 player_guid , uint32 instance )
{
// corpses are always added to spawn mode 0 and they are spawned by their instance id
CellObjectGuids & cell_guids = mMapObjectGuids [ MAKE_PAIR32 ( mapid , 0 )][ cellid ];
cell_guids . corpses [ player_guid ] = instance ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: DeleteCorpseCellData ( uint32 mapid , uint32 cellid , uint32 player_guid )
{
// corpses are always added to spawn mode 0 and they are spawned by their instance id
CellObjectGuids & cell_guids = mMapObjectGuids [ MAKE_PAIR32 ( mapid , 0 )][ cellid ];
cell_guids . corpses . erase ( player_guid );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadQuestRelationsHelper ( QuestRelations & map , char const * table )
{
map . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . PQuery ( "SELECT id,quest FROM %s" , table );
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded 0 quest relations from %s. DB table `%s` is empty." , table , table );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 id = fields [ 0 ]. GetUInt32 ();
uint32 quest = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( mQuestTemplates . find ( quest ) == mQuestTemplates . end ())
{
sLog . outErrorDb ( "Table `%s: Quest %u listed for entry %u does not exist." , table , quest , id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
map . insert ( QuestRelations :: value_type ( id , quest ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u quest relations from %s" , count , table );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameobjectQuestRelations ()
{
LoadQuestRelationsHelper ( mGOQuestRelations , "gameobject_questrelation" );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( QuestRelations :: iterator itr = mGOQuestRelations . begin (); itr != mGOQuestRelations . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
GameObjectInfo const * goInfo = GetGameObjectInfo ( itr -> first );
if ( ! goInfo )
sLog . outErrorDb ( "Table `gameobject_questrelation` have data for not existed gameobject entry (%u) and existed quest %u" , itr -> first , itr -> second );
else if ( goInfo -> type != GAMEOBJECT_TYPE_QUESTGIVER )
sLog . outErrorDb ( "Table `gameobject_questrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER" , itr -> first , itr -> second );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameobjectInvolvedRelations ()
{
LoadQuestRelationsHelper ( mGOQuestInvolvedRelations , "gameobject_involvedrelation" );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( QuestRelations :: iterator itr = mGOQuestInvolvedRelations . begin (); itr != mGOQuestInvolvedRelations . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
GameObjectInfo const * goInfo = GetGameObjectInfo ( itr -> first );
if ( ! goInfo )
sLog . outErrorDb ( "Table `gameobject_involvedrelation` have data for not existed gameobject entry (%u) and existed quest %u" , itr -> first , itr -> second );
else if ( goInfo -> type != GAMEOBJECT_TYPE_QUESTGIVER )
sLog . outErrorDb ( "Table `gameobject_involvedrelation` have data gameobject entry (%u) for quest %u, but GO is not GAMEOBJECT_TYPE_QUESTGIVER" , itr -> first , itr -> second );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCreatureQuestRelations ()
{
LoadQuestRelationsHelper ( mCreatureQuestRelations , "creature_questrelation" );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( QuestRelations :: iterator itr = mCreatureQuestRelations . begin (); itr != mCreatureQuestRelations . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
CreatureInfo const * cInfo = GetCreatureTemplate ( itr -> first );
if ( ! cInfo )
sLog . outErrorDb ( "Table `creature_questrelation` have data for not existed creature entry (%u) and existed quest %u" , itr -> first , itr -> second );
else if ( ! ( cInfo -> npcflag & UNIT_NPC_FLAG_QUESTGIVER ))
sLog . outErrorDb ( "Table `creature_questrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER" , itr -> first , itr -> second );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadCreatureInvolvedRelations ()
{
LoadQuestRelationsHelper ( mCreatureQuestInvolvedRelations , "creature_involvedrelation" );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( QuestRelations :: iterator itr = mCreatureQuestInvolvedRelations . begin (); itr != mCreatureQuestInvolvedRelations . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
CreatureInfo const * cInfo = GetCreatureTemplate ( itr -> first );
if ( ! cInfo )
sLog . outErrorDb ( "Table `creature_involvedrelation` have data for not existed creature entry (%u) and existed quest %u" , itr -> first , itr -> second );
else if ( ! ( cInfo -> npcflag & UNIT_NPC_FLAG_QUESTGIVER ))
sLog . outErrorDb ( "Table `creature_involvedrelation` has creature entry (%u) for quest %u, but npcflag does not include UNIT_NPC_FLAG_QUESTGIVER" , itr -> first , itr -> second );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadReservedPlayersNames ()
{
m_ReservedNames . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT name FROM reserved_name" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u reserved player names" , count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields ;
do
{
bar . step ();
fields = result -> Fetch ();
std :: string name = fields [ 0 ]. GetCppString ();
2009-10-17 15:51:44 -07:00
2009-01-25 16:35:14 -06:00
std :: wstring wstr ;
if ( ! Utf8toWStr ( name , wstr ))
2008-10-11 14:16:25 -05:00
{
2009-01-25 16:35:14 -06:00
sLog . outError ( "Table `reserved_name` have invalid name: %s" , name . c_str () );
continue ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-01-25 16:35:14 -06:00
wstrToLower ( wstr );
2009-10-17 15:51:44 -07:00
2009-01-25 16:35:14 -06:00
m_ReservedNames . insert ( wstr );
++ count ;
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u reserved player names" , count );
}
2009-10-17 15:51:44 -07:00
2009-01-25 16:35:14 -06:00
bool ObjectMgr :: IsReservedName ( const std :: string & name ) const
{
std :: wstring wstr ;
if ( ! Utf8toWStr ( name , wstr ))
return false ;
2009-10-17 15:51:44 -07:00
2009-01-25 16:35:14 -06:00
wstrToLower ( wstr );
2009-10-17 15:51:44 -07:00
2009-01-25 16:35:14 -06:00
return m_ReservedNames . find ( wstr ) != m_ReservedNames . end ();
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
enum LanguageType
{
LT_BASIC_LATIN = 0x0000 ,
LT_EXTENDEN_LATIN = 0x0001 ,
LT_CYRILLIC = 0x0002 ,
LT_EAST_ASIA = 0x0004 ,
LT_ANY = 0xFFFF
};
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
static LanguageType GetRealmLanguageType ( bool create )
{
switch ( sWorld . getConfig ( CONFIG_REALM_ZONE ))
{
case REALM_ZONE_UNKNOWN : // any language
case REALM_ZONE_DEVELOPMENT :
case REALM_ZONE_TEST_SERVER :
case REALM_ZONE_QA_SERVER :
return LT_ANY ;
case REALM_ZONE_UNITED_STATES : // extended-Latin
case REALM_ZONE_OCEANIC :
case REALM_ZONE_LATIN_AMERICA :
case REALM_ZONE_ENGLISH :
case REALM_ZONE_GERMAN :
case REALM_ZONE_FRENCH :
case REALM_ZONE_SPANISH :
return LT_EXTENDEN_LATIN ;
case REALM_ZONE_KOREA : // East-Asian
case REALM_ZONE_TAIWAN :
case REALM_ZONE_CHINA :
return LT_EAST_ASIA ;
case REALM_ZONE_RUSSIAN : // Cyrillic
return LT_CYRILLIC ;
default :
return create ? LT_BASIC_LATIN : LT_ANY ; // basic-Latin at create, any at login
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool isValidString ( std :: wstring wstr , uint32 strictMask , bool numericOrSpace , bool create = false )
{
if ( strictMask == 0 ) // any language, ignore realm
{
if ( isExtendedLatinString ( wstr , numericOrSpace ))
return true ;
if ( isCyrillicString ( wstr , numericOrSpace ))
return true ;
if ( isEastAsianString ( wstr , numericOrSpace ))
return true ;
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( strictMask & 0x2 ) // realm zone specific
{
LanguageType lt = GetRealmLanguageType ( create );
if ( lt & LT_EXTENDEN_LATIN )
if ( isExtendedLatinString ( wstr , numericOrSpace ))
return true ;
if ( lt & LT_CYRILLIC )
if ( isCyrillicString ( wstr , numericOrSpace ))
return true ;
if ( lt & LT_EAST_ASIA )
if ( isEastAsianString ( wstr , numericOrSpace ))
return true ;
}
2009-10-17 15:51:44 -07:00
2008-11-14 16:28:45 -06:00
if ( strictMask & 0x1 ) // basic Latin
2008-10-11 14:16:25 -05:00
{
if ( isBasicLatinString ( wstr , numericOrSpace ))
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
uint8 ObjectMgr :: CheckPlayerName ( const std :: string & name , bool create )
2008-10-11 14:16:25 -05:00
{
std :: wstring wname ;
if ( ! Utf8toWStr ( name , wname ))
2009-07-10 08:25:33 +08:00
return CHAR_NAME_INVALID_CHARACTER ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
if ( wname . size () > MAX_PLAYER_NAME )
return CHAR_NAME_TOO_LONG ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
uint32 minName = sWorld . getConfig ( CONFIG_MIN_PLAYER_NAME );
if ( wname . size () < minName )
return CHAR_NAME_TOO_SHORT ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
uint32 strictMask = sWorld . getConfig ( CONFIG_STRICT_PLAYER_NAMES );
if ( ! isValidString ( wname , strictMask , false , create ))
return CHAR_NAME_MIXED_LANGUAGES ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
return CHAR_NAME_SUCCESS ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
bool ObjectMgr :: IsValidCharterName ( const std :: string & name )
2008-10-11 14:16:25 -05:00
{
std :: wstring wname ;
if ( ! Utf8toWStr ( name , wname ))
return false ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
if ( wname . size () > MAX_CHARTER_NAME )
return false ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
uint32 minName = sWorld . getConfig ( CONFIG_MIN_CHARTER_NAME );
if ( wname . size () < minName )
2008-10-11 14:16:25 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 strictMask = sWorld . getConfig ( CONFIG_STRICT_CHARTER_NAMES );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return isValidString ( wname , strictMask , true );
}
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
PetNameInvalidReason ObjectMgr :: CheckPetName ( const std :: string & name )
2008-10-11 14:16:25 -05:00
{
std :: wstring wname ;
if ( ! Utf8toWStr ( name , wname ))
2009-07-10 08:25:33 +08:00
return PET_NAME_INVALID ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
if ( wname . size () > MAX_PET_NAME )
return PET_NAME_TOO_LONG ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
uint32 minName = sWorld . getConfig ( CONFIG_MIN_PET_NAME );
if ( wname . size () < minName )
return PET_NAME_TOO_SHORT ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 strictMask = sWorld . getConfig ( CONFIG_STRICT_PET_NAMES );
2009-07-10 08:25:33 +08:00
if ( ! isValidString ( wname , strictMask , false ))
return PET_NAME_MIXED_LANGUAGES ;
2009-10-17 15:51:44 -07:00
2009-07-10 08:25:33 +08:00
return PET_NAME_SUCCESS ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
int ObjectMgr :: GetIndexForLocale ( LocaleConstant loc )
{
if ( loc == LOCALE_enUS )
return - 1 ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( size_t i = 0 ; i < m_LocalForIndex . size (); ++ i )
2008-10-11 14:16:25 -05:00
if ( m_LocalForIndex [ i ] == loc )
return i ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return - 1 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
LocaleConstant ObjectMgr :: GetLocaleForIndex ( int i )
{
if ( i < 0 || i >= m_LocalForIndex . size ())
return LOCALE_enUS ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return m_LocalForIndex [ i ];
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
int ObjectMgr :: GetOrNewIndexForLocale ( LocaleConstant loc )
{
if ( loc == LOCALE_enUS )
return - 1 ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( size_t i = 0 ; i < m_LocalForIndex . size (); ++ i )
2008-10-11 14:16:25 -05:00
if ( m_LocalForIndex [ i ] == loc )
return i ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_LocalForIndex . push_back ( loc );
return m_LocalForIndex . size () - 1 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameObjectForQuests ()
{
mGameObjectForQuestSet . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
if ( ! sGOStorage . MaxEntry )
{
barGoLink bar ( 1 );
bar . step ();
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outString ( ">> Loaded 0 GameObjects for quests" );
return ;
}
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
barGoLink bar ( sGOStorage . MaxEntry - 1 );
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// collect GO entries for GO that must activated
2009-10-17 16:20:24 -07:00
for ( uint32 go_entry = 1 ; go_entry < sGOStorage . MaxEntry ; ++ go_entry )
2008-10-11 14:16:25 -05:00
{
2009-01-22 22:44:27 -06:00
bar . step ();
2008-10-11 14:16:25 -05:00
GameObjectInfo const * goInfo = sGOStorage . LookupEntry < GameObjectInfo > ( go_entry );
if ( ! goInfo )
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
switch ( goInfo -> type )
{
// scan GO chest with loot including quest items
case GAMEOBJECT_TYPE_CHEST :
{
2009-07-16 12:06:07 +08:00
uint32 loot_id = goInfo -> GetLootId ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// find quest loot for GO
if ( LootTemplates_Gameobject . HaveQuestLootFor ( loot_id ))
{
mGameObjectForQuestSet . insert ( go_entry );
++ count ;
}
break ;
}
case GAMEOBJECT_TYPE_GOOBER :
{
if ( goInfo -> goober . questId ) //quests objects
{
mGameObjectForQuestSet . insert ( go_entry );
count ++ ;
}
break ;
}
default :
break ;
}
}
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outString ( ">> Loaded %u GameObjects for quests" , count );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
bool ObjectMgr :: LoadTrinityStrings ( DatabaseType & db , char const * table , int32 min_value , int32 max_value )
2008-10-11 14:16:25 -05:00
{
2009-05-15 16:41:36 -05:00
int32 start_value = min_value ;
int32 end_value = max_value ;
// some string can have negative indexes range
if ( start_value < 0 )
{
if ( end_value >= start_value )
{
sLog . outErrorDb ( "Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded." , table , min_value , max_value );
return false ;
}
2009-10-17 15:51:44 -07:00
2009-05-15 16:41:36 -05:00
// real range (max+1,min+1) exaple: (-10,-1000) -> -999...-10+1
std :: swap ( start_value , end_value );
++ start_value ;
++ end_value ;
}
else
{
if ( start_value >= end_value )
{
sLog . outErrorDb ( "Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded." , table , min_value , max_value );
return false ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// cleanup affected map part for reloading case
2009-11-20 19:11:28 -08:00
for ( TrinityStringLocaleMap :: iterator itr = mTrinityStringLocaleMap . begin (); itr != mTrinityStringLocaleMap . end ();)
2008-10-11 14:16:25 -05:00
{
2009-05-15 16:41:36 -05:00
if ( itr -> first >= start_value && itr -> first < end_value )
2009-05-18 15:07:14 -05:00
mTrinityStringLocaleMap . erase ( itr ++ );
2008-10-11 14:16:25 -05:00
else
++ itr ;
}
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = db . PQuery ( "SELECT entry,content_default,content_loc1,content_loc2,content_loc3,content_loc4,content_loc5,content_loc6,content_loc7,content_loc8 FROM %s" , table );
2009-10-17 15:51:44 -07:00
2009-05-15 16:41:36 -05:00
if ( ! result )
2008-10-11 14:16:25 -05:00
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-05-15 16:41:36 -05:00
if ( min_value == MIN_TRINITY_STRING_ID ) // error only in case internal strings
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( ">> Loaded 0 trinity strings. DB table `%s` is empty. Cannot continue." , table );
2008-10-11 14:16:25 -05:00
else
sLog . outString ( ">> Loaded 0 string templates. DB table `%s` is empty." , table );
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
Field * fields = result -> Fetch ();
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
int32 entry = fields [ 0 ]. GetInt32 ();
2009-10-17 15:51:44 -07:00
2009-05-15 16:41:36 -05:00
if ( entry == 0 )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Table `%s` contain reserved entry 0, ignored." , table );
continue ;
}
2009-05-15 16:41:36 -05:00
else if ( entry < start_value || entry >= end_value )
2008-10-11 14:16:25 -05:00
{
2009-05-15 16:41:36 -05:00
sLog . outErrorDb ( "Table `%s` contain entry %i out of allowed range (%d - %d), ignored." , table , entry , min_value , max_value );
2008-10-11 14:16:25 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
TrinityStringLocale & data = mTrinityStringLocaleMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-05-15 16:41:36 -05:00
if ( data . Content . size () > 0 )
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Table `%s` contain data for already loaded entry %i (from another table?), ignored." , table , entry );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Content . resize ( 1 );
++ count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0 -> default, idx in to idx+1
data . Content [ 0 ] = fields [ 1 ]. GetCppString ();
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint8 i = 1 ; i < MAX_LOCALE ; ++ i )
2008-10-11 14:16:25 -05:00
{
std :: string str = fields [ i + 1 ]. GetCppString ();
2009-05-15 16:41:36 -05:00
if ( ! str . empty ())
2008-10-11 14:16:25 -05:00
{
int idx = GetOrNewIndexForLocale ( LocaleConstant ( i ));
2009-05-15 16:41:36 -05:00
if ( idx >= 0 )
2008-10-11 14:16:25 -05:00
{
// 0 -> default, idx in to idx+1
2009-05-15 16:41:36 -05:00
if ( data . Content . size () <= idx + 1 )
2008-10-11 14:16:25 -05:00
data . Content . resize ( idx + 2 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data . Content [ idx + 1 ] = str ;
}
}
}
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-05-15 16:41:36 -05:00
if ( min_value == MIN_TRINITY_STRING_ID )
2008-10-14 11:57:03 -05:00
sLog . outString ( ">> Loaded %u Trinity strings from table %s" , count , table );
2008-10-11 14:16:25 -05:00
else
sLog . outString ( ">> Loaded %u string templates from %s" , count , table );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
const char * ObjectMgr :: GetTrinityString ( int32 entry , int locale_idx ) const
2008-10-11 14:16:25 -05:00
{
// locale_idx==-1 -> default, locale_idx >= 0 in to idx+1
2008-10-14 11:57:03 -05:00
// Content[0] always exist if exist TrinityStringLocale
if ( TrinityStringLocale const * msl = GetTrinityStringLocale ( entry ))
2008-10-11 14:16:25 -05:00
{
if ( msl -> Content . size () > locale_idx + 1 && ! msl -> Content [ locale_idx + 1 ]. empty ())
return msl -> Content [ locale_idx + 1 ]. c_str ();
else
return msl -> Content [ 0 ]. c_str ();
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( entry > 0 )
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Entry %i not found in `trinity_string` table." , entry );
2008-10-11 14:16:25 -05:00
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Trinity string entry %i not found in DB." , entry );
2008-10-11 14:16:25 -05:00
return "<error>" ;
}
2009-10-17 15:51:44 -07:00
2008-10-21 03:58:38 -05:00
void ObjectMgr :: LoadSpellDisabledEntrys ()
{
m_DisabledPlayerSpells . clear (); // need for reload case
m_DisabledCreatureSpells . clear ();
2009-03-07 07:47:02 -05:00
m_DisabledPetSpells . clear ();
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, disable_mask FROM spell_disabled" );
2009-10-17 15:51:44 -07:00
2008-10-21 03:58:38 -05:00
uint32 total_count = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-21 03:58:38 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-21 03:58:38 -05:00
sLog . outString ( ">> Loaded %u disabled spells" , total_count );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-21 03:58:38 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-21 03:58:38 -05:00
Field * fields ;
do
{
bar . step ();
fields = result -> Fetch ();
uint32 spellid = fields [ 0 ]. GetUInt32 ();
if ( ! sSpellStore . LookupEntry ( spellid ))
{
sLog . outErrorDb ( "Spell entry %u from `spell_disabled` doesn't exist in dbc, ignoring." , spellid );
continue ;
}
uint32 disable_mask = fields [ 1 ]. GetUInt32 ();
if ( disable_mask & SPELL_DISABLE_PLAYER )
m_DisabledPlayerSpells . insert ( spellid );
if ( disable_mask & SPELL_DISABLE_CREATURE )
m_DisabledCreatureSpells . insert ( spellid );
2009-03-07 07:47:02 -05:00
if ( disable_mask & SPELL_DISABLE_PET )
m_DisabledPetSpells . insert ( spellid );
2008-10-21 03:58:38 -05:00
++ total_count ;
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-21 03:58:38 -05:00
sLog . outString ( ">> Loaded %u disabled spells from `spell_disabled`" , total_count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadFishingBaseSkillLevel ()
{
2008-11-14 16:28:45 -06:00
mFishingBaseForArea . clear (); // for reload case
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry,skill FROM skill_fishing_base_level" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded `skill_fishing_base_level`, table is empty!" );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
uint32 entry = fields [ 0 ]. GetUInt32 ();
int32 skill = fields [ 1 ]. GetInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
AreaTableEntry const * fArea = GetAreaEntryByAreaID ( entry );
if ( ! fArea )
{
sLog . outErrorDb ( "AreaId %u defined in `skill_fishing_base_level` does not exist" , entry );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mFishingBaseForArea [ entry ] = skill ;
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %u areas for fishing base skill level" , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Searches for the same condition already in Conditions store
// Returns Id if found, else adds it to Conditions and returns Id
uint16 ObjectMgr :: GetConditionId ( ConditionType condition , uint32 value1 , uint32 value2 )
{
PlayerCondition lc = PlayerCondition ( condition , value1 , value2 );
for ( uint16 i = 0 ; i < mConditions . size (); ++ i )
{
if ( lc == mConditions [ i ])
return i ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
mConditions . push_back ( lc );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( mConditions . size () > 0xFFFF )
{
sLog . outError ( "Conditions store overflow! Current and later loaded conditions will ignored!" );
return 0 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return mConditions . size () - 1 ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool ObjectMgr :: CheckDeclinedNames ( std :: wstring mainpart , DeclinedName const & names )
{
2009-10-17 16:20:24 -07:00
for ( uint8 i = 0 ; i < MAX_DECLINED_NAME_CASES ; ++ i )
2008-10-11 14:16:25 -05:00
{
std :: wstring wname ;
if ( ! Utf8toWStr ( names . name [ i ], wname ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( mainpart != GetMainPartOfName ( wname , i + 1 ))
return false ;
}
return true ;
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
uint32 ObjectMgr :: GetAreaTriggerScriptId ( uint32 trigger_id )
2008-10-11 14:16:25 -05:00
{
2008-11-20 16:16:57 -06:00
AreaTriggerScriptMap :: const_iterator i = mAreaTriggerScripts . find ( trigger_id );
2008-10-11 14:16:25 -05:00
if ( i != mAreaTriggerScripts . end ())
2008-11-20 16:16:57 -06:00
return i -> second ;
return 0 ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Checks if player meets the condition
bool PlayerCondition :: Meets ( Player const * player ) const
{
if ( ! player )
return false ; // player not present, return false
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
switch ( condition )
{
case CONDITION_NONE :
return true ; // empty condition, always met
case CONDITION_AURA :
2009-04-20 16:48:35 +02:00
return player -> HasAuraEffect ( value1 , value2 );
2008-10-11 14:16:25 -05:00
case CONDITION_ITEM :
return player -> HasItemCount ( value1 , value2 );
case CONDITION_ITEM_EQUIPPED :
2009-02-15 11:58:27 -06:00
return player -> HasItemOrGemWithIdEquipped ( value1 , 1 );
2008-10-11 14:16:25 -05:00
case CONDITION_ZONEID :
return player -> GetZoneId () == value1 ;
case CONDITION_REPUTATION_RANK :
{
FactionEntry const * faction = sFactionStore . LookupEntry ( value1 );
2009-09-18 14:10:37 -07:00
return faction && uint32 ( player -> GetReputationMgr (). GetRank ( faction )) >= int32 ( value2 );
2008-10-11 14:16:25 -05:00
}
2010-03-14 11:45:34 -06:00
case CONDITION_ACHIEVEMENT :
{
2010-03-14 16:35:38 -06:00
AchievementEntry const * achievement = GetAchievementStore () -> LookupEntry ( value1 );
2010-03-15 04:37:28 +01:00
return player -> GetAchievementMgr (). HasAchieved ( achievement );
2010-03-14 11:45:34 -06:00
}
2008-10-11 14:16:25 -05:00
case CONDITION_TEAM :
return player -> GetTeam () == value1 ;
2010-03-14 11:45:34 -06:00
case CONDITION_CLASS :
return player -> getClass () == value1 ;
case CONDITION_RACE :
return player -> getRace () == value1 ;
2008-10-11 14:16:25 -05:00
case CONDITION_SKILL :
return player -> HasSkill ( value1 ) && player -> GetBaseSkillValue ( value1 ) >= value2 ;
case CONDITION_QUESTREWARDED :
return player -> GetQuestRewardStatus ( value1 );
case CONDITION_QUESTTAKEN :
{
QuestStatus status = player -> GetQuestStatus ( value1 );
return ( status == QUEST_STATUS_INCOMPLETE );
}
2010-02-16 21:21:52 -07:00
case CONDITION_QUEST_NONE :
{
QuestStatus status = player -> GetQuestStatus ( value1 );
return ( status == QUEST_STATUS_NONE );
}
2008-10-11 14:16:25 -05:00
case CONDITION_AD_COMMISSION_AURA :
{
2010-01-10 01:23:15 +01:00
Unit :: AuraApplicationMap const & auras = player -> GetAppliedAuras ();
for ( Unit :: AuraApplicationMap :: const_iterator itr = auras . begin (); itr != auras . end (); ++ itr )
if (( itr -> second -> GetBase () -> GetSpellProto () -> Attributes & 0x1000010 ) && itr -> second -> GetBase () -> GetSpellProto () -> SpellVisual [ 0 ] == 3580 )
2008-10-11 14:16:25 -05:00
return true ;
return false ;
}
2008-11-20 16:16:57 -06:00
case CONDITION_NO_AURA :
2009-04-20 16:48:35 +02:00
return ! player -> HasAuraEffect ( value1 , value2 );
2008-11-20 16:16:57 -06:00
case CONDITION_ACTIVE_EVENT :
return gameeventmgr . IsActiveEvent ( value1 );
2008-12-02 18:12:39 -06:00
case CONDITION_INSTANCE_DATA :
{
Map * map = player -> GetMap ();
if ( map && map -> IsDungeon () && (( InstanceMap * ) map ) -> GetInstanceData ())
return (( InstanceMap * ) map ) -> GetInstanceData () -> GetData ( value1 ) == value2 ;
}
2008-10-11 14:16:25 -05:00
default :
return false ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Verification of condition values validity
bool PlayerCondition :: IsValid ( ConditionType condition , uint32 value1 , uint32 value2 )
{
if ( condition >= MAX_CONDITION ) // Wrong condition type
{
sLog . outErrorDb ( "Condition has bad type of %u, skipped " , condition );
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
switch ( condition )
{
case CONDITION_AURA :
{
if ( ! sSpellStore . LookupEntry ( value1 ))
{
sLog . outErrorDb ( "Aura condition requires to have non existing spell (Id: %d), skipped" , value1 );
return false ;
}
if ( value2 > 2 )
{
sLog . outErrorDb ( "Aura condition requires to have non existing effect index (%u) (must be 0..2), skipped" , value2 );
return false ;
}
break ;
}
case CONDITION_ITEM :
{
ItemPrototype const * proto = objmgr . GetItemPrototype ( value1 );
if ( ! proto )
{
sLog . outErrorDb ( "Item condition requires to have non existing item (%u), skipped" , value1 );
return false ;
}
break ;
}
case CONDITION_ITEM_EQUIPPED :
{
ItemPrototype const * proto = objmgr . GetItemPrototype ( value1 );
if ( ! proto )
{
sLog . outErrorDb ( "ItemEquipped condition requires to have non existing item (%u) equipped, skipped" , value1 );
return false ;
}
break ;
}
case CONDITION_ZONEID :
{
AreaTableEntry const * areaEntry = GetAreaEntryByAreaID ( value1 );
if ( ! areaEntry )
{
sLog . outErrorDb ( "Zone condition requires to be in non existing area (%u), skipped" , value1 );
return false ;
}
if ( areaEntry -> zone != 0 )
{
sLog . outErrorDb ( "Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped" , value1 );
return false ;
}
break ;
}
case CONDITION_REPUTATION_RANK :
{
FactionEntry const * factionEntry = sFactionStore . LookupEntry ( value1 );
if ( ! factionEntry )
{
sLog . outErrorDb ( "Reputation condition requires to have reputation non existing faction (%u), skipped" , value1 );
return false ;
}
break ;
}
case CONDITION_TEAM :
{
if ( value1 != ALLIANCE && value1 != HORDE )
{
sLog . outErrorDb ( "Team condition specifies unknown team (%u), skipped" , value1 );
return false ;
}
break ;
}
case CONDITION_SKILL :
{
SkillLineEntry const * pSkill = sSkillLineStore . LookupEntry ( value1 );
if ( ! pSkill )
{
sLog . outErrorDb ( "Skill condition specifies non-existing skill (%u), skipped" , value1 );
return false ;
}
if ( value2 < 1 || value2 > sWorld . GetConfigMaxSkillValue () )
{
sLog . outErrorDb ( "Skill condition specifies invalid skill value (%u), skipped" , value2 );
return false ;
}
break ;
}
case CONDITION_QUESTREWARDED :
case CONDITION_QUESTTAKEN :
{
Quest const * Quest = objmgr . GetQuestTemplate ( value1 );
if ( ! Quest )
{
sLog . outErrorDb ( "Quest condition specifies non-existing quest (%u), skipped" , value1 );
return false ;
}
if ( value2 )
sLog . outErrorDb ( "Quest condition has useless data in value2 (%u)!" , value2 );
break ;
}
case CONDITION_AD_COMMISSION_AURA :
{
if ( value1 )
sLog . outErrorDb ( "Quest condition has useless data in value1 (%u)!" , value1 );
if ( value2 )
sLog . outErrorDb ( "Quest condition has useless data in value2 (%u)!" , value2 );
break ;
}
2008-11-20 16:16:57 -06:00
case CONDITION_NO_AURA :
{
if ( ! sSpellStore . LookupEntry ( value1 ))
{
sLog . outErrorDb ( "Aura condition requires to have non existing spell (Id: %d), skipped" , value1 );
return false ;
}
if ( value2 > 2 )
{
sLog . outErrorDb ( "Aura condition requires to have non existing effect index (%u) (must be 0..2), skipped" , value2 );
return false ;
}
break ;
}
case CONDITION_ACTIVE_EVENT :
{
2009-03-06 19:36:47 -06:00
GameEventMgr :: GameEventDataMap const & events = gameeventmgr . GetEventMap ();
2008-11-20 16:16:57 -06:00
if ( value1 >= events . size () || ! events [ value1 ]. isValid ())
{
sLog . outErrorDb ( "Active event condition requires existed event id (%u), skipped" , value1 );
return false ;
}
break ;
}
2008-12-02 18:12:39 -06:00
case CONDITION_INSTANCE_DATA :
//TODO: need some check
break ;
2009-05-03 22:21:46 -05:00
case CONDITION_NONE :
break ;
2008-10-11 14:16:25 -05:00
}
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SkillRangeType GetSkillRangeType ( SkillLineEntry const * pSkill , bool racial )
{
switch ( pSkill -> categoryId )
{
case SKILL_CATEGORY_LANGUAGES : return SKILL_RANGE_LANGUAGE ;
case SKILL_CATEGORY_WEAPON :
if ( pSkill -> id != SKILL_FIST_WEAPONS )
return SKILL_RANGE_LEVEL ;
else
return SKILL_RANGE_MONO ;
case SKILL_CATEGORY_ARMOR :
case SKILL_CATEGORY_CLASS :
2008-12-24 09:58:26 -06:00
if ( pSkill -> id != SKILL_LOCKPICKING )
2008-10-11 14:16:25 -05:00
return SKILL_RANGE_MONO ;
else
return SKILL_RANGE_LEVEL ;
case SKILL_CATEGORY_SECONDARY :
case SKILL_CATEGORY_PROFESSION :
// not set skills for professions and racial abilities
if ( IsProfessionSkill ( pSkill -> id ))
return SKILL_RANGE_RANK ;
else if ( racial )
return SKILL_RANGE_NONE ;
else
return SKILL_RANGE_MONO ;
default :
case SKILL_CATEGORY_ATTRIBUTES : //not found in dbc
2008-12-24 09:58:26 -06:00
case SKILL_CATEGORY_GENERIC : //only GENERIC(DND)
2008-10-11 14:16:25 -05:00
return SKILL_RANGE_NONE ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadGameTele ()
{
2008-11-14 16:28:45 -06:00
m_GameTeleMap . clear (); // for reload case
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT id, position_x, position_y, position_z, orientation, map, name FROM game_tele" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded `game_tele`, table is empty!" );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 id = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
GameTele gt ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
gt . position_x = fields [ 1 ]. GetFloat ();
gt . position_y = fields [ 2 ]. GetFloat ();
gt . position_z = fields [ 3 ]. GetFloat ();
gt . orientation = fields [ 4 ]. GetFloat ();
gt . mapId = fields [ 5 ]. GetUInt32 ();
gt . name = fields [ 6 ]. GetCppString ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! MapManager :: IsValidMapCoord ( gt . mapId , gt . position_x , gt . position_y , gt . position_z , gt . orientation ))
{
sLog . outErrorDb ( "Wrong position for id %u (name: %s) in `game_tele` table, ignoring." , id , gt . name . c_str ());
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! Utf8toWStr ( gt . name , gt . wnameLow ))
{
sLog . outErrorDb ( "Wrong UTF8 name for id %u in `game_tele` table, ignoring." , id );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
wstrToLower ( gt . wnameLow );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_GameTeleMap [ id ] = gt ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outString ( ">> Loaded %u GameTeleports" , count );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
GameTele const * ObjectMgr :: GetGameTele ( const std :: string & name ) const
2008-10-11 14:16:25 -05:00
{
// explicit name case
std :: wstring wname ;
if ( ! Utf8toWStr ( name , wname ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// converting string that we try to find to lower case
wstrToLower ( wname );
2009-10-17 15:51:44 -07:00
2008-10-29 18:06:01 -05:00
// Alternative first GameTele what contains wnameLow as substring in case no GameTele location found
const GameTele * alt = NULL ;
2009-10-17 16:20:24 -07:00
for ( GameTeleMap :: const_iterator itr = m_GameTeleMap . begin (); itr != m_GameTeleMap . end (); ++ itr )
2008-10-29 18:06:01 -05:00
{
2008-10-11 14:16:25 -05:00
if ( itr -> second . wnameLow == wname )
return & itr -> second ;
2008-10-29 18:06:01 -05:00
else if ( alt == NULL && itr -> second . wnameLow . find ( wname ) != std :: wstring :: npos )
alt = & itr -> second ;
}
2009-10-17 15:51:44 -07:00
2008-10-29 18:06:01 -05:00
return alt ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool ObjectMgr :: AddGameTele ( GameTele & tele )
{
// find max id
uint32 new_id = 0 ;
2009-10-17 16:20:24 -07:00
for ( GameTeleMap :: const_iterator itr = m_GameTeleMap . begin (); itr != m_GameTeleMap . end (); ++ itr )
2008-10-11 14:16:25 -05:00
if ( itr -> first > new_id )
new_id = itr -> first ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// use next
++ new_id ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! Utf8toWStr ( tele . name , tele . wnameLow ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
wstrToLower ( tele . wnameLow );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_GameTeleMap [ new_id ] = tele ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return WorldDatabase . PExecuteLog ( "INSERT INTO game_tele (id,position_x,position_y,position_z,orientation,map,name) VALUES (%u,%f,%f,%f,%f,%d,'%s')" ,
new_id , tele . position_x , tele . position_y , tele . position_z , tele . orientation , tele . mapId , tele . name . c_str ());
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
bool ObjectMgr :: DeleteGameTele ( const std :: string & name )
2008-10-11 14:16:25 -05:00
{
// explicit name case
std :: wstring wname ;
if ( ! Utf8toWStr ( name , wname ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// converting string that we try to find to lower case
wstrToLower ( wname );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( GameTeleMap :: iterator itr = m_GameTeleMap . begin (); itr != m_GameTeleMap . end (); ++ itr )
2008-10-11 14:16:25 -05:00
{
if ( itr -> second . wnameLow == wname )
{
WorldDatabase . PExecuteLog ( "DELETE FROM game_tele WHERE name = '%s'" , itr -> second . name . c_str ());
m_GameTeleMap . erase ( itr );
return true ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-12-16 18:58:36 +02:00
void ObjectMgr :: LoadMailLevelRewards ()
{
m_mailLevelRewardMap . clear (); // for reload case
uint32 count = 0 ;
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT level, raceMask, mailTemplateId, senderEntry FROM mail_level_reward" );
2009-12-16 18:58:36 +02:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outErrorDb ( ">> Loaded `mail_level_reward`, table is empty!" );
return ;
}
barGoLink bar ( result -> GetRowCount () );
do
{
bar . step ();
Field * fields = result -> Fetch ();
uint8 level = fields [ 0 ]. GetUInt8 ();
uint32 raceMask = fields [ 1 ]. GetUInt32 ();
uint32 mailTemplateId = fields [ 2 ]. GetUInt32 ();
uint32 senderEntry = fields [ 3 ]. GetUInt32 ();
if ( level > MAX_LEVEL )
{
sLog . outErrorDb ( "Table `mail_level_reward` have data for level %u that more supported by client (%u), ignoring." , level , MAX_LEVEL );
continue ;
}
if ( ! ( raceMask & RACEMASK_ALL_PLAYABLE ))
{
sLog . outErrorDb ( "Table `mail_level_reward` have raceMask (%u) for level %u that not include any player races, ignoring." , raceMask , level );
continue ;
}
if ( ! sMailTemplateStore . LookupEntry ( mailTemplateId ))
{
sLog . outErrorDb ( "Table `mail_level_reward` have invalid mailTemplateId (%u) for level %u that invalid not include any player races, ignoring." , mailTemplateId , level );
continue ;
}
if ( ! GetCreatureTemplateStore ( senderEntry ))
{
sLog . outErrorDb ( "Table `mail_level_reward` have not existed sender creature entry (%u) for level %u that invalid not include any player races, ignoring." , senderEntry , level );
continue ;
}
m_mailLevelRewardMap [ level ]. push_back ( MailLevelReward ( raceMask , mailTemplateId , senderEntry ));
++ count ;
}
while ( result -> NextRow ());
sLog . outString ();
sLog . outString ( ">> Loaded %u level dependent mail rewards," , count );
}
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadTrainerSpell ()
{
2008-11-20 16:16:57 -06:00
// For reload case
2008-10-11 14:16:25 -05:00
for ( CacheTrainerSpellMap :: iterator itr = m_mCacheTrainerSpellMap . begin (); itr != m_mCacheTrainerSpellMap . end (); ++ itr )
itr -> second . Clear ();
m_mCacheTrainerSpellMap . clear ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
std :: set < uint32 > skip_trainers ;
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer" );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded `npc_trainer`, table is empty!" );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2009-06-18 17:03:16 -05:00
std :: set < uint32 > talentIds ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
uint32 spell = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
CreatureInfo const * cInfo = GetCreatureTemplate ( entry );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! cInfo )
{
sLog . outErrorDb ( "Table `npc_trainer` have entry for not existed creature template (Entry: %u), ignore" , entry );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! ( cInfo -> npcflag & UNIT_NPC_FLAG_TRAINER ))
{
2010-01-16 19:18:53 +03:00
if ( skip_trainers . find ( entry ) == skip_trainers . end ())
2008-10-11 14:16:25 -05:00
{
sLog . outErrorDb ( "Table `npc_trainer` have data for not creature template (Entry: %u) without trainer flag, ignore" , entry );
skip_trainers . insert ( entry );
}
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SpellEntry const * spellinfo = sSpellStore . LookupEntry ( spell );
if ( ! spellinfo )
{
sLog . outErrorDb ( "Table `npc_trainer` for Trainer (Entry: %u ) has non existing spell %u, ignore" , entry , spell );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! SpellMgr :: IsSpellValid ( spellinfo ))
{
sLog . outErrorDb ( "Table `npc_trainer` for Trainer (Entry: %u) has broken learning spell %u, ignore" , entry , spell );
continue ;
}
2009-10-17 15:51:44 -07:00
2009-06-18 17:03:16 -05:00
if ( GetTalentSpellCost ( spell ))
{
if ( talentIds . count ( spell ) == 0 )
{
sLog . outErrorDb ( "Table `npc_trainer` has talent as learning spell %u, ignore" , spell );
talentIds . insert ( spell );
}
continue ;
}
2009-10-17 15:51:44 -07:00
2009-02-16 20:10:04 -06:00
TrainerSpellData & data = m_mCacheTrainerSpellMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-02-16 20:10:04 -06:00
TrainerSpell & trainerSpell = data . spellList [ spell ];
trainerSpell . spell = spell ;
trainerSpell . spellCost = fields [ 2 ]. GetUInt32 ();
trainerSpell . reqSkill = fields [ 3 ]. GetUInt32 ();
trainerSpell . reqSkillValue = fields [ 4 ]. GetUInt32 ();
trainerSpell . reqLevel = fields [ 5 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-02-16 20:10:04 -06:00
if ( ! trainerSpell . reqLevel )
trainerSpell . reqLevel = spellinfo -> spellLevel ;
2009-10-17 15:51:44 -07:00
2009-01-14 00:35:13 -06:00
// calculate learned spell for profession case when stored cast-spell
2010-01-31 17:24:13 +01:00
trainerSpell . learnedSpell [ 0 ] = spell ;
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
2009-01-14 00:35:13 -06:00
{
2009-02-16 20:10:04 -06:00
if ( spellinfo -> Effect [ i ] != SPELL_EFFECT_LEARN_SPELL )
2009-01-14 00:35:13 -06:00
continue ;
2010-02-01 19:22:32 +01:00
if ( trainerSpell . learnedSpell [ 0 ] == spell )
trainerSpell . learnedSpell [ 0 ] = 0 ;
2010-01-31 17:24:13 +01:00
// player must be able to cast spell on himself
2010-02-01 19:22:32 +01:00
if ( spellinfo -> EffectImplicitTargetA [ i ] != 0 && spellinfo -> EffectImplicitTargetA [ i ] != TARGET_UNIT_TARGET_ALLY
&& spellinfo -> EffectImplicitTargetA [ i ] != TARGET_UNIT_TARGET_ANY && spellinfo -> EffectImplicitTargetA [ i ] != TARGET_UNIT_CASTER )
2009-01-14 00:35:13 -06:00
{
2010-01-31 17:24:13 +01:00
sLog . outErrorDb ( "Table `npc_trainer` has spell %u for trainer entry %u with learn effect which has incorrect target type, ignoring learn effect!" , spell , entry );
continue ;
2009-01-14 00:35:13 -06:00
}
2010-01-31 17:24:13 +01:00
trainerSpell . learnedSpell [ i ] = spellinfo -> EffectTriggerSpell [ i ];
2009-01-14 00:35:13 -06:00
}
2009-10-17 15:51:44 -07:00
2010-01-31 17:24:13 +01:00
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
{
if ( ! trainerSpell . learnedSpell [ i ])
continue ;
if ( SpellMgr :: IsProfessionSpell ( trainerSpell . learnedSpell [ i ]))
{
data . trainerType = 2 ;
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
++ count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outString ( ">> Loaded %d Trainers" , count );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadVendors ()
{
2008-11-20 16:16:57 -06:00
// For reload case
2008-10-11 14:16:25 -05:00
for ( CacheVendorItemMap :: iterator itr = m_mCacheVendorItemMap . begin (); itr != m_mCacheVendorItemMap . end (); ++ itr )
itr -> second . Clear ();
m_mCacheVendorItemMap . clear ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
std :: set < uint32 > skip_vendors ;
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor" );
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded `npc_vendor`, table is empty!" );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
do
{
bar . step ();
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
uint32 item_id = fields [ 1 ]. GetUInt32 ();
2009-12-21 14:48:30 -07:00
int32 maxcount = fields [ 2 ]. GetInt32 ();
2008-10-11 14:16:25 -05:00
uint32 incrtime = fields [ 3 ]. GetUInt32 ();
uint32 ExtendedCost = fields [ 4 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! IsVendorItemValid ( entry , item_id , maxcount , incrtime , ExtendedCost , NULL , & skip_vendors ))
continue ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
VendorItemData & vList = m_mCacheVendorItemMap [ entry ];
2009-10-17 15:51:44 -07:00
2009-12-24 10:20:15 +01:00
vList . AddItem ( item_id , maxcount , incrtime , ExtendedCost );
2008-10-11 14:16:25 -05:00
++ count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %d Vendors " , count );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void ObjectMgr :: LoadNpcTextId ()
{
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_mCacheNpcTextIdMap . clear ();
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT npc_guid, textid FROM npc_gossip" );
2008-10-11 14:16:25 -05:00
if ( ! result )
{
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outErrorDb ( ">> Loaded `npc_gossip`, table is empty!" );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 count = 0 ;
uint32 guid , textid ;
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
guid = fields [ 0 ]. GetUInt32 ();
textid = fields [ 1 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! GetCreatureData ( guid ))
{
sLog . outErrorDb ( "Table `npc_gossip` have not existed creature (GUID: %u) entry, ignore. " , guid );
continue ;
}
if ( ! GetGossipText ( textid ))
{
sLog . outErrorDb ( "Table `npc_gossip` for creature (GUID: %u) have wrong Textid (%u), ignore. " , guid , textid );
continue ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_mCacheNpcTextIdMap [ guid ] = textid ;
++ count ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2008-10-11 14:16:25 -05:00
sLog . outString ( ">> Loaded %d NpcTextId " , count );
}
2009-10-17 15:51:44 -07:00
2009-12-20 13:35:08 +02:00
void ObjectMgr :: LoadGossipMenu ()
2008-11-05 09:22:56 -06:00
{
2009-12-20 13:35:08 +02:00
m_mGossipMenusMap . clear ();
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, text_id, "
2009-12-20 13:35:08 +02:00
"cond_1, cond_1_val_1, cond_1_val_2, cond_2, cond_2_val_1, cond_2_val_2 FROM gossip_menu" );
2009-10-17 15:51:44 -07:00
2009-12-20 13:35:08 +02:00
if ( ! result )
2008-11-05 09:22:56 -06:00
{
2009-12-20 13:35:08 +02:00
barGoLink bar ( 1 );
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
bar . step ();
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-12-20 13:35:08 +02:00
sLog . outErrorDb ( ">> Loaded `gossip_menu`, table is empty!" );
2008-11-05 09:22:56 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
barGoLink bar ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
do
{
bar . step ();
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2009-12-20 13:35:08 +02:00
GossipMenus gMenu ;
gMenu . entry = fields [ 0 ]. GetUInt32 ();
gMenu . text_id = fields [ 1 ]. GetUInt32 ();
ConditionType cond_1 = ( ConditionType ) fields [ 2 ]. GetUInt32 ();
uint32 cond_1_val_1 = fields [ 3 ]. GetUInt32 ();
uint32 cond_1_val_2 = fields [ 4 ]. GetUInt32 ();
ConditionType cond_2 = ( ConditionType ) fields [ 5 ]. GetUInt32 ();
uint32 cond_2_val_1 = fields [ 6 ]. GetUInt32 ();
uint32 cond_2_val_2 = fields [ 7 ]. GetUInt32 ();
if ( ! GetGossipText ( gMenu . text_id ))
{
sLog . outErrorDb ( "Table gossip_menu entry %u are using non-existing text_id %u" , gMenu . entry , gMenu . text_id );
continue ;
}
if ( ! PlayerCondition :: IsValid ( cond_1 , cond_1_val_1 , cond_1_val_2 ))
{
sLog . outErrorDb ( "Table gossip_menu entry %u, invalid condition 1 for id %u" , gMenu . entry , gMenu . text_id );
continue ;
}
if ( ! PlayerCondition :: IsValid ( cond_2 , cond_2_val_1 , cond_2_val_2 ))
{
sLog . outErrorDb ( "Table gossip_menu entry %u, invalid condition 2 for id %u" , gMenu . entry , gMenu . text_id );
continue ;
}
gMenu . cond_1 = GetConditionId ( cond_1 , cond_1_val_1 , cond_1_val_2 );
gMenu . cond_2 = GetConditionId ( cond_2 , cond_2_val_1 , cond_2_val_2 );
2009-10-17 15:51:44 -07:00
2009-12-20 13:35:08 +02:00
m_mGossipMenusMap . insert ( GossipMenusMap :: value_type ( gMenu . entry , gMenu ));
2009-10-17 15:51:44 -07:00
2008-11-05 09:22:56 -06:00
++ count ;
2009-12-20 13:35:08 +02:00
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-12-20 13:35:08 +02:00
sLog . outString ( ">> Loaded %u gossip_menu entries" , count );
}
void ObjectMgr :: LoadGossipMenuItems ()
{
m_mGossipMenuItemsMap . clear ();
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query (
2009-12-20 13:35:08 +02:00
"SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, "
"action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text, "
"cond_1, cond_1_val_1, cond_1_val_2, "
"cond_2, cond_2_val_1, cond_2_val_2, "
"cond_3, cond_3_val_1, cond_3_val_2 "
"FROM gossip_menu_option" );
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outErrorDb ( ">> Loaded gossip_menu_option, table is empty!" );
return ;
}
barGoLink bar ( result -> GetRowCount ());
uint32 count = 0 ;
std :: set < uint32 > gossipScriptSet ;
for ( ScriptMapMap :: const_iterator itr = sGossipScripts . begin (); itr != sGossipScripts . end (); ++ itr )
gossipScriptSet . insert ( itr -> first );
do
{
bar . step ();
Field * fields = result -> Fetch ();
GossipMenuItems gMenuItem ;
gMenuItem . menu_id = fields [ 0 ]. GetUInt32 ();
gMenuItem . id = fields [ 1 ]. GetUInt32 ();
gMenuItem . option_icon = fields [ 2 ]. GetUInt8 ();
gMenuItem . option_text = fields [ 3 ]. GetCppString ();
gMenuItem . option_id = fields [ 4 ]. GetUInt32 ();
gMenuItem . npc_option_npcflag = fields [ 5 ]. GetUInt32 ();
gMenuItem . action_menu_id = fields [ 6 ]. GetUInt32 ();
gMenuItem . action_poi_id = fields [ 7 ]. GetUInt32 ();
gMenuItem . action_script_id = fields [ 8 ]. GetUInt32 ();
gMenuItem . box_coded = fields [ 9 ]. GetUInt8 () != 0 ;
gMenuItem . box_money = fields [ 10 ]. GetUInt32 ();
gMenuItem . box_text = fields [ 11 ]. GetCppString ();
ConditionType cond_1 = ( ConditionType ) fields [ 12 ]. GetUInt32 ();
uint32 cond_1_val_1 = fields [ 13 ]. GetUInt32 ();
uint32 cond_1_val_2 = fields [ 14 ]. GetUInt32 ();
ConditionType cond_2 = ( ConditionType ) fields [ 15 ]. GetUInt32 ();
uint32 cond_2_val_1 = fields [ 16 ]. GetUInt32 ();
uint32 cond_2_val_2 = fields [ 17 ]. GetUInt32 ();
ConditionType cond_3 = ( ConditionType ) fields [ 18 ]. GetUInt32 ();
uint32 cond_3_val_1 = fields [ 19 ]. GetUInt32 ();
uint32 cond_3_val_2 = fields [ 20 ]. GetUInt32 ();
if ( ! PlayerCondition :: IsValid ( cond_1 , cond_1_val_1 , cond_1_val_2 ))
{
sLog . outErrorDb ( "Table gossip_menu_option menu %u, invalid condition 1 for id %u" , gMenuItem . menu_id , gMenuItem . id );
continue ;
}
if ( ! PlayerCondition :: IsValid ( cond_2 , cond_2_val_1 , cond_2_val_2 ))
{
sLog . outErrorDb ( "Table gossip_menu_option menu %u, invalid condition 2 for id %u" , gMenuItem . menu_id , gMenuItem . id );
continue ;
}
if ( ! PlayerCondition :: IsValid ( cond_3 , cond_3_val_1 , cond_3_val_2 ))
{
sLog . outErrorDb ( "Table gossip_menu_option menu %u, invalid condition 3 for id %u" , gMenuItem . menu_id , gMenuItem . id );
continue ;
}
if ( gMenuItem . option_icon >= GOSSIP_ICON_MAX )
{
sLog . outErrorDb ( "Table gossip_menu_option for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT" , gMenuItem . menu_id , gMenuItem . id , gMenuItem . option_icon );
gMenuItem . option_icon = GOSSIP_ICON_CHAT ;
}
if ( gMenuItem . option_id >= GOSSIP_OPTION_MAX )
sLog . outErrorDb ( "Table gossip_menu_option for menu %u, id %u has unknown option id %u. Option will not be used" , gMenuItem . menu_id , gMenuItem . id , gMenuItem . option_id );
if ( gMenuItem . action_poi_id && ! GetPointOfInterest ( gMenuItem . action_poi_id ))
{
sLog . outErrorDb ( "Table gossip_menu_option for menu %u, id %u use non-existing action_poi_id %u, ignoring" , gMenuItem . menu_id , gMenuItem . id , gMenuItem . action_poi_id );
gMenuItem . action_poi_id = 0 ;
}
if ( gMenuItem . action_script_id )
{
if ( gMenuItem . option_id != GOSSIP_OPTION_GOSSIP )
{
sLog . outErrorDb ( "Table gossip_menu_option for menu %u, id %u have action_script_id %u but option_id is not GOSSIP_OPTION_GOSSIP, ignoring" , gMenuItem . menu_id , gMenuItem . id , gMenuItem . action_script_id );
continue ;
}
if ( sGossipScripts . find ( gMenuItem . action_script_id ) == sGossipScripts . end ())
{
sLog . outErrorDb ( "Table gossip_menu_option for menu %u, id %u have action_script_id %u that does not exist in `gossip_scripts`, ignoring" , gMenuItem . menu_id , gMenuItem . id , gMenuItem . action_script_id );
continue ;
}
gossipScriptSet . erase ( gMenuItem . action_script_id );
}
gMenuItem . cond_1 = GetConditionId ( cond_1 , cond_1_val_1 , cond_1_val_2 );
gMenuItem . cond_2 = GetConditionId ( cond_2 , cond_2_val_1 , cond_2_val_2 );
gMenuItem . cond_3 = GetConditionId ( cond_3 , cond_3_val_1 , cond_3_val_2 );
m_mGossipMenuItemsMap . insert ( GossipMenuItemsMap :: value_type ( gMenuItem . menu_id , gMenuItem ));
++ count ;
}
while ( result -> NextRow ());
if ( ! gossipScriptSet . empty ())
{
for ( std :: set < uint32 >:: const_iterator itr = gossipScriptSet . begin (); itr != gossipScriptSet . end (); ++ itr )
sLog . outErrorDb ( "Table `gossip_scripts` contain unused script, id %u." , * itr );
}
sLog . outString ();
sLog . outString ( ">> Loaded %u gossip_menu_option entries" , count );
2008-11-05 09:22:56 -06:00
}
2009-10-17 15:51:44 -07:00
2009-12-21 14:48:30 -07:00
void ObjectMgr :: AddVendorItem ( uint32 entry , uint32 item , int32 maxcount , uint32 incrtime , uint32 extendedcost , bool savetodb )
2008-10-11 14:16:25 -05:00
{
VendorItemData & vList = m_mCacheVendorItemMap [ entry ];
2009-12-24 10:20:15 +01:00
vList . AddItem ( item , maxcount , incrtime , extendedcost );
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
if ( savetodb ) WorldDatabase . PExecuteLog ( "INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')" , entry , item , maxcount , incrtime , extendedcost );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
bool ObjectMgr :: RemoveVendorItem ( uint32 entry , uint32 item , bool savetodb )
2008-10-11 14:16:25 -05:00
{
CacheVendorItemMap :: iterator iter = m_mCacheVendorItemMap . find ( entry );
if ( iter == m_mCacheVendorItemMap . end ())
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! iter -> second . FindItem ( item ))
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
iter -> second . RemoveItem ( item );
2008-10-14 11:57:03 -05:00
if ( savetodb ) WorldDatabase . PExecuteLog ( "DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'" , entry , item );
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2009-12-21 14:48:30 -07:00
bool ObjectMgr :: IsVendorItemValid ( uint32 vendor_entry , uint32 item_id , int32 maxcount , uint32 incrtime , uint32 ExtendedCost , Player * pl , std :: set < uint32 >* skip_vendors , uint32 ORnpcflag ) const
2008-10-11 14:16:25 -05:00
{
CreatureInfo const * cInfo = GetCreatureTemplate ( vendor_entry );
if ( ! cInfo )
{
if ( pl )
ChatHandler ( pl ). SendSysMessage ( LANG_COMMAND_VENDORSELECTION );
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `(game_event_)npc_vendor` have data for not existed creature template (Entry: %u), ignore" , vendor_entry );
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
if ( ! (( cInfo -> npcflag | ORnpcflag ) & UNIT_NPC_FLAG_VENDOR ))
2008-10-11 14:16:25 -05:00
{
if ( ! skip_vendors || skip_vendors -> count ( vendor_entry ) == 0 )
{
if ( pl )
ChatHandler ( pl ). SendSysMessage ( LANG_COMMAND_VENDORSELECTION );
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `(game_event_)npc_vendor` have data for not creature template (Entry: %u) without vendor flag, ignore" , vendor_entry );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( skip_vendors )
skip_vendors -> insert ( vendor_entry );
}
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ! GetItemPrototype ( item_id ))
{
if ( pl )
ChatHandler ( pl ). PSendSysMessage ( LANG_ITEM_NOT_FOUND , item_id );
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `(game_event_)npc_vendor` for Vendor (Entry: %u) have in item list non-existed item (%u), ignore" , vendor_entry , item_id );
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( ExtendedCost && ! sItemExtendedCostStore . LookupEntry ( ExtendedCost ))
{
if ( pl )
ChatHandler ( pl ). PSendSysMessage ( LANG_EXTENDED_COST_NOT_EXIST , ExtendedCost );
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `(game_event_)npc_vendor` have Item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignore" , item_id , ExtendedCost , vendor_entry );
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( maxcount > 0 && incrtime == 0 )
{
if ( pl )
ChatHandler ( pl ). PSendSysMessage ( "MaxCount!=0 (%u) but IncrTime==0" , maxcount );
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `(game_event_)npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignore" , maxcount , item_id , vendor_entry );
2008-10-11 14:16:25 -05:00
return false ;
}
else if ( maxcount == 0 && incrtime > 0 )
{
if ( pl )
ChatHandler ( pl ). PSendSysMessage ( "MaxCount==0 but IncrTime<>=0" );
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `(game_event_)npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignore" , item_id , vendor_entry );
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
VendorItemData const * vItems = GetNpcVendorItemList ( vendor_entry );
if ( ! vItems )
return true ; // later checks for non-empty lists
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( vItems -> FindItem ( item_id ))
{
if ( pl )
ChatHandler ( pl ). PSendSysMessage ( LANG_ITEM_ALREADY_IN_LIST , item_id );
else
2008-10-14 11:57:03 -05:00
sLog . outErrorDb ( "Table `(game_event_)npc_vendor` has duplicate items %u for vendor (Entry: %u), ignore" , item_id , vendor_entry );
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2010-02-23 21:09:55 -06:00
if ( vItems -> GetItemCount () >= MAX_VENDOR_ITEMS )
2008-10-11 14:16:25 -05:00
{
if ( pl )
ChatHandler ( pl ). SendSysMessage ( LANG_COMMAND_ADDVENDORITEMITEMS );
else
sLog . outErrorDb ( "Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore" , vItems -> GetItemCount (), MAX_VENDOR_ITEMS , vendor_entry );
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
void ObjectMgr :: LoadScriptNames ()
{
m_scriptNames . push_back ( "" );
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query (
2008-11-20 16:16:57 -06:00
"SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(script) FROM instance_template WHERE script <> ''" );
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( ! result )
2008-11-20 16:16:57 -06:00
{
2010-01-01 14:19:29 -06:00
barGoLink bar ( 1 );
2009-01-22 22:44:27 -06:00
bar . step ();
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outErrorDb ( ">> Loaded empty set of Script Names!" );
return ;
2008-11-20 16:16:57 -06:00
}
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
barGoLink bar ( result -> GetRowCount ());
2009-10-17 15:51:44 -07:00
2009-09-13 00:01:35 -07:00
//OnEvent Changes
m_scriptNames . push_back ( "scripted_on_events" );
uint32 count = 1 ;
2009-10-17 15:51:44 -07:00
2009-01-22 22:44:27 -06:00
do
{
bar . step ();
m_scriptNames . push_back (( * result )[ 0 ]. GetString ());
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
std :: sort ( m_scriptNames . begin (), m_scriptNames . end ());
2009-04-03 16:36:20 -06:00
sLog . outString ();
2009-01-22 22:44:27 -06:00
sLog . outString ( ">> Loaded %d Script Names" , count );
2008-11-20 16:16:57 -06:00
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
uint32 ObjectMgr :: GetScriptId ( const char * name )
{
// use binary search to find the script name in the sorted vector
// assume "" is the first element
if ( ! name ) return 0 ;
ScriptNameMap :: const_iterator itr =
std :: lower_bound ( m_scriptNames . begin (), m_scriptNames . end (), name );
2008-11-24 19:41:39 -06:00
if ( itr == m_scriptNames . end () || * itr != name ) return 0 ;
2008-11-20 16:16:57 -06:00
return itr - m_scriptNames . begin ();
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
void ObjectMgr :: CheckScripts ( ScriptMapMap const & scripts , std :: set < int32 >& ids )
{
2009-10-17 16:20:24 -07:00
for ( ScriptMapMap :: const_iterator itrMM = scripts . begin (); itrMM != scripts . end (); ++ itrMM )
2008-11-20 16:16:57 -06:00
{
2009-10-17 16:20:24 -07:00
for ( ScriptMap :: const_iterator itrM = itrMM -> second . begin (); itrM != itrMM -> second . end (); ++ itrM )
2008-11-20 16:16:57 -06:00
{
2009-04-17 15:16:19 -05:00
switch ( itrM -> second . command )
2008-11-20 16:16:57 -06:00
{
2009-04-17 15:16:19 -05:00
case SCRIPT_COMMAND_TALK :
{
if ( ! GetTrinityStringLocale ( itrM -> second . dataint ))
sLog . outErrorDb ( "Table `db_script_string` not has string id %u used db script (ID: %u)" , itrM -> second . dataint , itrMM -> first );
2009-10-17 15:51:44 -07:00
2010-01-16 19:18:53 +03:00
if ( ids . find ( itrM -> second . dataint ) != ids . end ())
2009-04-17 15:16:19 -05:00
ids . erase ( itrM -> second . dataint );
}
2008-11-20 16:16:57 -06:00
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
void ObjectMgr :: LoadDbScriptStrings ()
{
LoadTrinityStrings ( WorldDatabase , "db_script_string" , MIN_DB_SCRIPT_STRING_ID , MAX_DB_SCRIPT_STRING_ID );
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
std :: set < int32 > ids ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( int32 i = MIN_DB_SCRIPT_STRING_ID ; i < MAX_DB_SCRIPT_STRING_ID ; ++ i )
2008-11-20 16:16:57 -06:00
if ( GetTrinityStringLocale ( i ))
ids . insert ( i );
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
CheckScripts ( sQuestEndScripts , ids );
CheckScripts ( sQuestStartScripts , ids );
CheckScripts ( sSpellScripts , ids );
CheckScripts ( sGameObjectScripts , ids );
CheckScripts ( sEventScripts , ids );
2009-10-17 15:51:44 -07:00
2008-12-10 06:34:35 +02:00
CheckScripts ( sWaypointScripts , ids );
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( std :: set < int32 >:: const_iterator itr = ids . begin (); itr != ids . end (); ++ itr )
2008-11-20 16:16:57 -06:00
sLog . outErrorDb ( "Table `db_script_string` has unused string id %u" , * itr );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Functions for scripting access
2008-11-20 16:16:57 -06:00
uint32 GetAreaTriggerScriptId ( uint32 trigger_id )
2008-10-11 14:16:25 -05:00
{
2008-11-20 16:16:57 -06:00
return objmgr . GetAreaTriggerScriptId ( trigger_id );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
bool LoadTrinityStrings ( DatabaseType & db , char const * table , int32 start_value , int32 end_value )
2008-10-11 14:16:25 -05:00
{
2009-05-15 16:41:36 -05:00
// MAX_DB_SCRIPT_STRING_ID is max allowed negative value for scripts (scrpts can use only more deep negative values
// start/end reversed for negative values
if ( start_value > MAX_DB_SCRIPT_STRING_ID || end_value >= start_value )
2008-10-11 14:16:25 -05:00
{
2010-02-05 00:31:28 +01:00
sLog . outErrorDb ( "Table '%s' load attempted with range (%d - %d) reserved by Trinity, strings not loaded." , table , start_value , end_value + 1 );
2009-05-15 16:41:36 -05:00
return false ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-15 16:41:36 -05:00
return objmgr . LoadTrinityStrings ( db , table , start_value , end_value );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-02-05 00:31:28 +01:00
uint32 GetScriptId ( const char * name )
2008-11-20 16:16:57 -06:00
{
return objmgr . GetScriptId ( name );
}
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
ObjectMgr :: ScriptNameMap & GetScriptNames ()
{
return objmgr . GetScriptNames ();
}
2009-10-17 15:51:44 -07:00
2009-02-05 15:38:24 -06:00
GameObjectInfo const * GetGameObjectInfo ( uint32 id )
{
return objmgr . GetGameObjectInfo ( id );
}
2009-10-17 15:51:44 -07:00
2009-02-05 15:38:24 -06:00
CreatureInfo const * GetCreatureInfo ( uint32 id )
{
return objmgr . GetCreatureTemplate ( id );
}
2009-10-17 15:51:44 -07:00
2009-01-03 07:26:39 +02:00
void ObjectMgr :: LoadTransportEvents ()
{
2009-10-17 15:51:44 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT entry, waypoint_id, event_id FROM transport_events" );
2009-10-17 15:51:44 -07:00
2009-01-03 07:26:39 +02:00
if ( ! result )
{
barGoLink bar1 ( 1 );
bar1 . step ();
2009-02-12 09:23:56 -05:00
sLog . outString ( " \n >> Transport events table is empty \n " );
2009-01-03 07:26:39 +02:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-02-12 09:23:56 -05:00
barGoLink bar1 ( result -> GetRowCount () );
2009-10-17 15:51:44 -07:00
2009-01-03 07:26:39 +02:00
do
{
bar1 . step ();
2009-10-17 15:51:44 -07:00
2009-02-12 09:23:56 -05:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2009-02-12 09:23:56 -05:00
//Load event values
2009-01-03 07:26:39 +02:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
uint32 waypoint_id = fields [ 1 ]. GetUInt32 ();
2009-02-12 09:23:56 -05:00
uint32 event_id = fields [ 2 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-02-12 09:23:56 -05:00
uint32 event_count = ( entry * 100 ) + waypoint_id ;
TransportEventMap [ event_count ] = event_id ;
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-02-12 09:23:56 -05:00
sLog . outString ( " \n >> Loaded %u transport events \n " , result -> GetRowCount () );
2009-02-09 14:28:01 -05:00
}
2009-10-17 15:51:44 -07:00
2009-02-18 16:50:21 -06:00
CreatureInfo const * GetCreatureTemplateStore ( uint32 entry )
{
return sCreatureStorage . LookupEntry < CreatureInfo > ( entry );
}
2009-10-17 15:51:44 -07:00
2009-02-18 16:50:21 -06:00
Quest const * GetQuestTemplateStore ( uint32 entry )
{
return objmgr . GetQuestTemplate ( entry );
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
uint64 ObjectMgr :: GenerateGMTicketId ()
{
return ++ m_GMticketid ;
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
void ObjectMgr :: LoadGMTickets ()
{
2009-11-09 20:23:16 +01:00
if ( ! m_GMTicketList . empty ())
{
for ( GmTicketList :: const_iterator itr = m_GMTicketList . begin (); itr != m_GMTicketList . end (); ++ itr )
delete * itr ;
}
2009-06-15 23:58:29 +02:00
m_GMTicketList . clear ();
2010-03-02 21:00:33 -06:00
m_GMticketid = 0 ;
2009-10-17 16:20:24 -07:00
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = CharacterDatabase . Query ( "SELECT guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment FROM gm_tickets" );
2009-10-17 16:20:24 -07:00
2009-06-15 23:58:29 +02:00
if ( ! result )
{
2010-01-01 14:19:29 -06:00
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outString ( ">> GM Tickets table is empty, no tickets were loaded." );
2009-06-15 23:58:29 +02:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
uint16 count = 0 ;
barGoLink bar (( * result ). GetRowCount ());
GM_Ticket * ticket ;
do
{
Field * fields = result -> Fetch ();
ticket = new GM_Ticket ;
ticket -> guid = fields [ 0 ]. GetUInt64 ();
ticket -> playerGuid = fields [ 1 ]. GetUInt64 ();
ticket -> name = fields [ 2 ]. GetCppString ();
ticket -> message = fields [ 3 ]. GetCppString ();
ticket -> createtime = fields [ 4 ]. GetUInt64 ();
ticket -> map = fields [ 5 ]. GetUInt32 ();
ticket -> pos_x = fields [ 6 ]. GetFloat ();
ticket -> pos_y = fields [ 7 ]. GetFloat ();
ticket -> pos_z = fields [ 8 ]. GetFloat ();
ticket -> timestamp = fields [ 9 ]. GetUInt64 ();
ticket -> closed = fields [ 10 ]. GetUInt64 ();
ticket -> assignedToGM = fields [ 11 ]. GetUInt64 ();
ticket -> comment = fields [ 12 ]. GetCppString ();
++ count ;
bar . step ();
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
m_GMTicketList . push_back ( ticket );
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
} while ( result -> NextRow () );
2009-10-17 15:51:44 -07:00
2009-09-10 22:40:40 +02:00
result = CharacterDatabase . PQuery ( "SELECT MAX(guid) from gm_tickets" );
2009-10-17 15:51:44 -07:00
2009-11-09 20:23:16 +01:00
if ( result )
{
Field * fields = result -> Fetch ();
m_GMticketid = fields [ 0 ]. GetUInt64 ();
}
2010-01-01 14:19:29 -06:00
sLog . outString ( ">> Loaded %u GM Tickets from the database." , count );
2009-06-15 23:58:29 +02:00
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
void ObjectMgr :: AddOrUpdateGMTicket ( GM_Ticket & ticket , bool create )
{
if ( create )
m_GMTicketList . push_back ( & ticket );
2009-10-17 16:20:24 -07:00
_AddOrUpdateGMTicket ( ticket );
2009-06-15 23:58:29 +02:00
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
void ObjectMgr :: _AddOrUpdateGMTicket ( GM_Ticket & ticket )
{
2009-10-17 16:20:24 -07:00
std :: string msg ( ticket . message ), name ( ticket . name ), comment ( ticket . comment );
2009-06-15 23:58:29 +02:00
CharacterDatabase . escape_string ( msg );
CharacterDatabase . escape_string ( name );
CharacterDatabase . escape_string ( comment );
std :: ostringstream ss ;
2009-09-10 22:40:40 +02:00
ss << "REPLACE INTO gm_tickets (guid, playerGuid, name, message, createtime, map, posX, posY, posZ, timestamp, closed, assignedto, comment) VALUES('" ;
2009-06-15 23:58:29 +02:00
ss << ticket . guid << "', '" ;
ss << ticket . playerGuid << "', '" ;
ss << name << "', '" ;
ss << msg << "', '" ;
ss << ticket . createtime << "', '" ;
ss << ticket . map << "', '" ;
ss << ticket . pos_x << "', '" ;
ss << ticket . pos_y << "', '" ;
ss << ticket . pos_z << "', '" ;
ss << ticket . timestamp << "', '" ;
ss << ticket . closed << "', '" ;
ss << ticket . assignedToGM << "', '" ;
ss << comment << "');" ;
CharacterDatabase . BeginTransaction ();
CharacterDatabase . Execute ( ss . str (). c_str ());
CharacterDatabase . CommitTransaction ();
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
void ObjectMgr :: RemoveGMTicket ( GM_Ticket * ticket , int64 source , bool permanently )
{
2009-10-17 16:20:24 -07:00
for ( GmTicketList :: iterator i = m_GMTicketList . begin (); i != m_GMTicketList . end (); ++ i )
2009-06-19 20:07:29 +02:00
if (( * i ) -> guid == ticket -> guid )
2009-06-15 23:58:29 +02:00
{
if ( permanently )
{
2009-09-10 22:40:40 +02:00
CharacterDatabase . PExecute ( "DELETE FROM gm_tickets WHERE guid = '%u'" , ticket -> guid );
2009-06-15 23:58:29 +02:00
i = m_GMTicketList . erase ( i );
ticket = NULL ;
return ;
}
2009-06-21 21:46:15 +02:00
( * i ) -> closed = source ;
2009-06-22 02:23:12 +02:00
_AddOrUpdateGMTicket ( * ( * i ));
2009-06-15 23:58:29 +02:00
}
}
2009-10-17 15:51:44 -07:00
2009-06-15 23:58:29 +02:00
void ObjectMgr :: RemoveGMTicket ( uint64 ticketGuid , int64 source , bool permanently )
{
GM_Ticket * ticket = GetGMTicket ( ticketGuid );
assert ( ticket );
RemoveGMTicket ( ticket , source , permanently );
}
2009-10-17 15:51:44 -07:00
2010-03-03 02:48:31 +02:00
CreatureBaseStats const * ObjectMgr :: GetCreatureBaseStats ( uint8 level , uint8 unitClass )
2009-12-20 20:23:18 -07:00
{
2010-03-03 04:32:47 +02:00
CreatureBaseStatsMap :: const_iterator it = m_creatureBaseStatsMap . find ( MAKE_PAIR16 ( level , unitClass ) );
2009-12-20 20:23:18 -07:00
2010-03-03 04:32:47 +02:00
if ( it != m_creatureBaseStatsMap . end ())
return & ( it -> second );
struct DefaultCreatureBaseStats : public CreatureBaseStats
{
DefaultCreatureBaseStats ()
{
BaseArmor = 1 ;
for ( uint8 j = 0 ; j < MAX_CREATURE_BASE_HP ; ++ j )
BaseHealth [ j ] = 1 ;
BaseMana = 0 ;
}
};
static const DefaultCreatureBaseStats def_stats ;
return & def_stats ;
2009-12-20 20:23:18 -07:00
}
void ObjectMgr :: LoadCreatureClassLevelStats ()
{
2010-01-23 14:45:58 +01:00
QueryResult_AutoPtr result = WorldDatabase . Query ( "SELECT level, class, basehp0, basehp1, basehp2, basemana, basearmor FROM creature_classlevelstats" );
2009-12-20 20:23:18 -07:00
if ( ! result )
{
barGoLink bar ( 1 );
bar . step ();
sLog . outString ();
sLog . outString ( ">> Loaded 0 creature base stats. DB table `creature_classlevelstats` is empty." );
return ;
}
barGoLink bar ( result -> GetRowCount ());
uint32 counter = 0 ;
do
{
Field * fields = result -> Fetch ();
2010-03-03 04:32:47 +02:00
uint8 Level = fields [ 0 ]. GetUInt32 ();
uint8 Class = fields [ 1 ]. GetUInt8 ();
CreatureBaseStats stats ;
2010-01-10 22:02:03 +01:00
for ( uint8 i = 0 ; i < MAX_CREATURE_BASE_HP ; ++ i )
stats . BaseHealth [ i ] = fields [ i + 2 ]. GetUInt32 ();
stats . BaseMana = fields [ 5 ]. GetUInt32 ();
stats . BaseArmor = fields [ 6 ]. GetUInt32 ();
2009-12-20 20:23:18 -07:00
2010-03-03 04:32:47 +02:00
if ( Level > STRONG_MAX_LEVEL )
2009-12-20 20:23:18 -07:00
{
2010-01-10 22:02:03 +01:00
sLog . outErrorDb ( "Creature base stats for class %u has invalid level %u (max is %u) - set to %u" ,
2010-03-03 04:32:47 +02:00
Class , Level , STRONG_MAX_LEVEL , STRONG_MAX_LEVEL );
Level = STRONG_MAX_LEVEL ;
2009-12-20 20:23:18 -07:00
}
2010-03-03 04:32:47 +02:00
if ( ! Class || (( 1 << ( Class - 1 )) & CLASSMASK_ALL_CREATURES ) == 0 )
2010-01-10 22:02:03 +01:00
sLog . outErrorDb ( "Creature base stats for level %u has invalid class %u" ,
2010-03-03 04:32:47 +02:00
Level , Class );
2009-12-20 20:23:18 -07:00
2010-01-10 22:02:03 +01:00
for ( uint8 i = 0 ; i < MAX_CREATURE_BASE_HP ; ++ i )
2009-12-20 20:23:18 -07:00
{
2010-01-10 22:02:03 +01:00
if ( stats . BaseHealth [ i ] < 1 )
{
sLog . outErrorDb ( "Creature base stats for class %u, level %u has invalid zero base HP[%u] - set to 1" ,
2010-03-03 04:32:47 +02:00
Class , Level , i );
2010-01-10 22:02:03 +01:00
stats . BaseHealth [ i ] = 1 ;
}
2009-12-20 20:23:18 -07:00
}
2010-03-03 04:32:47 +02:00
m_creatureBaseStatsMap [ MAKE_PAIR16 ( Level , Class )] = stats ;
2009-12-20 20:23:18 -07:00
bar . step ();
++ counter ;
}
while ( result -> NextRow ());
2010-01-11 18:13:21 +01:00
for ( uint32 i = 0 ; i < sCreatureStorage . MaxEntry ; ++ i )
{
CreatureInfo const * info = sCreatureStorage . LookupEntry < CreatureInfo > ( i );
if ( ! info )
continue ;
2010-03-07 21:36:39 +02:00
for ( uint16 lvl = info -> minlevel ; lvl <= info -> maxlevel ; ++ lvl )
2010-01-11 18:13:21 +01:00
{
2010-03-07 03:45:22 +02:00
if ( m_creatureBaseStatsMap . find ( MAKE_PAIR16 ( lvl , info -> unit_class ) ) == m_creatureBaseStatsMap . end ())
sLog . outErrorDb ( "Missing base stats for creature class %u level %u" , info -> unit_class , lvl );
2010-01-11 18:13:21 +01:00
}
}
2009-12-20 20:23:18 -07:00
sLog . outString ();
sLog . outString ( ">> Loaded %u creature base stats." , counter );
}