2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "Database/DatabaseEnv.h"
21 #include "Database/SQLStorage.h"
24 #include "ObjectMgr.h"
25 #include "UpdateMask.h"
27 #include "WorldSession.h"
30 #include "ProgressBar.cpp"
31 #include "Policies/SingletonImp.h"
33 INSTANTIATE_SINGLETON_1(ObjectMgr
);
35 extern SQLStorage sItemStorage
;
36 extern SQLStorage sGOStorage
;
37 extern SQLStorage sCreatureStorage
;
38 extern SQLStorage sQuestsStorage
;
40 ObjectMgr::ObjectMgr()
50 ObjectMgr::~ObjectMgr()
53 for( QuestMap::iterator i
= mQuests
.begin( ); i
!= mQuests
.end( ); ++ i
)
59 for( GossipTextMap::iterator i
= mGossipText
.begin( ); i
!= mGossipText
.end( ); ++ i
)
65 for( AreaTriggerMap::iterator i
= mAreaTriggerMap
.begin( ); i
!= mAreaTriggerMap
.end( ); ++ i
)
69 mAreaTriggerMap
.clear( );
73 Group
* ObjectMgr::GetGroupByLeader(const uint64
&guid
) const
75 GroupSet::const_iterator itr
;
76 for (itr
= mGroupSet
.begin(); itr
!= mGroupSet
.end(); itr
++)
78 if ((*itr
)->GetLeaderGUID() == guid
)
87 Guild
* ObjectMgr::GetGuildById(const uint32 GuildId
) const
89 GuildSet::const_iterator itr
;
90 for (itr
= mGuildSet
.begin(); itr
!= mGuildSet
.end(); itr
++)
92 if ((*itr
)->GetId() == GuildId
)
101 CreatureInfo
*ObjectMgr::GetCreatureTemplate(uint32 id
)
103 return (sCreatureStorage
.MaxEntry
<=id
)?NULL
:(CreatureInfo
*)sCreatureStorage
.pIndex
[id
];
106 void ObjectMgr::LoadCreatureTemplates()
109 sCreatureStorage
.Load();
111 sLog
.outString( ">> Loaded %d creature definitions", sCreatureStorage
.RecordCount
);
112 sLog
.outString( "" );
115 PlayerCreateInfo
* ObjectMgr::GetPlayerCreateInfo(uint32 race
, uint32 class_
)
119 Field
*player_fields
, *items_fields
, *spells_fields
, *skills_fields
, *actions_fields
;
120 PlayerCreateInfo
*pPlayerCreateInfo
;
122 QueryResult
*player_result
= sDatabase
.PQuery("SELECT * FROM `playercreateinfo` WHERE `race` = '%u' AND `class` = '%u';", race
, class_
);
126 sLog
.outError("Warning: Can't get info for player creating with race %d and class %d (table 'playercreateinfo' is empty?)", race
, class_
);
130 pPlayerCreateInfo
= new PlayerCreateInfo
;
132 player_fields
= player_result
->Fetch();
134 pPlayerCreateInfo
->createId
= player_fields
[0].GetUInt8();
135 createId
= (uint32
)pPlayerCreateInfo
->createId
;
136 pPlayerCreateInfo
->race
= player_fields
[1].GetUInt8();
137 pPlayerCreateInfo
->class_
= player_fields
[2].GetUInt8();
138 pPlayerCreateInfo
->mapId
= player_fields
[3].GetUInt32();
139 pPlayerCreateInfo
->zoneId
= player_fields
[4].GetUInt32();
140 pPlayerCreateInfo
->positionX
= player_fields
[5].GetFloat();
141 pPlayerCreateInfo
->positionY
= player_fields
[6].GetFloat();
142 pPlayerCreateInfo
->positionZ
= player_fields
[7].GetFloat();
143 pPlayerCreateInfo
->displayId
= player_fields
[8].GetUInt16();
144 pPlayerCreateInfo
->strength
= player_fields
[9].GetUInt8();
145 pPlayerCreateInfo
->ability
= player_fields
[10].GetUInt8();
146 pPlayerCreateInfo
->stamina
= player_fields
[11].GetUInt8();
147 pPlayerCreateInfo
->intellect
= player_fields
[12].GetUInt8();
148 pPlayerCreateInfo
->spirit
= player_fields
[13].GetUInt8();
149 pPlayerCreateInfo
->basearmor
= player_fields
[14].GetUInt32();
150 pPlayerCreateInfo
->health
= player_fields
[15].GetUInt32();
151 pPlayerCreateInfo
->mana
= player_fields
[16].GetUInt32();
152 pPlayerCreateInfo
->rage
= player_fields
[17].GetUInt32();
153 pPlayerCreateInfo
->focus
= player_fields
[18].GetUInt32();
154 pPlayerCreateInfo
->energy
= player_fields
[19].GetUInt32();
155 pPlayerCreateInfo
->attackpower
= player_fields
[20].GetUInt32();
156 pPlayerCreateInfo
->mindmg
= player_fields
[21].GetFloat();
157 pPlayerCreateInfo
->maxdmg
= player_fields
[22].GetFloat();
158 pPlayerCreateInfo
->ranmindmg
= player_fields
[23].GetFloat();
159 pPlayerCreateInfo
->ranmaxdmg
= player_fields
[24].GetFloat();
161 delete player_result
;
163 QueryResult
*items_result
= sDatabase
.PQuery("SELECT * FROM `playercreateinfo_item` WHERE `createid` = '0' OR `createid` = '%u';", createId
);
167 if(!items_result
) break;
168 items_fields
= items_result
->Fetch();
169 pPlayerCreateInfo
->item_id
.push_back(items_fields
[1].GetUInt32());
170 pPlayerCreateInfo
->item_bagIndex
.push_back(items_fields
[2].GetUInt32());
171 pPlayerCreateInfo
->item_slot
.push_back(items_fields
[3].GetUInt8());
172 pPlayerCreateInfo
->item_amount
.push_back(items_fields
[4].GetUInt32());
173 } while (items_result
->NextRow());
177 QueryResult
*spells_result
= sDatabase
.PQuery("SELECT * FROM `playercreateinfo_spell` WHERE `createid` = '0' OR `createid` = '%u';", createId
);
181 if(!spells_result
) break;
182 spells_fields
= spells_result
->Fetch();
183 pPlayerCreateInfo
->spell
.push_back(spells_fields
[1].GetUInt16());
185 } while( spells_result
->NextRow() );
187 delete spells_result
;
189 QueryResult
*skills_result
= sDatabase
.PQuery("SELECT * FROM `playercreateinfo_skill` WHERE `createid` = '0' OR `createid` = '%u';", createId
);
193 if(!skills_result
) break;
194 skills_fields
= skills_result
->Fetch();
195 pPlayerCreateInfo
->skill
[0].push_back(skills_fields
[1].GetUInt16());
196 pPlayerCreateInfo
->skill
[1].push_back(skills_fields
[2].GetUInt16());
197 pPlayerCreateInfo
->skill
[2].push_back(skills_fields
[3].GetUInt16());
199 } while( skills_result
->NextRow() );
201 delete skills_result
;
203 QueryResult
*actions_result
= sDatabase
.PQuery("SELECT * FROM `playercreateinfo_action` WHERE `createid` = '0' OR `createid` = '%u';", createId
);
207 if(!actions_result
) break;
208 actions_fields
= actions_result
->Fetch();
209 pPlayerCreateInfo
->action
[0].push_back(actions_fields
[1].GetUInt16());
210 pPlayerCreateInfo
->action
[1].push_back(actions_fields
[2].GetUInt16());
211 pPlayerCreateInfo
->action
[2].push_back(actions_fields
[3].GetUInt16());
212 pPlayerCreateInfo
->action
[3].push_back(actions_fields
[4].GetUInt16());
214 } while( actions_result
->NextRow() );
216 delete actions_result
;
218 return pPlayerCreateInfo
;
221 uint64
ObjectMgr::GetPlayerGUIDByName(const char *name
) const
226 QueryResult
*result
= sDatabase
.PQuery("SELECT `guid` FROM `character` WHERE `name` = '%s';", name
);
230 guid
= (*result
)[0].GetUInt32();
238 bool ObjectMgr::GetPlayerNameByGUID(const uint64
&guid
, std::string
&name
) const
241 QueryResult
*result
= sDatabase
.PQuery("SELECT `name` FROM `character` WHERE `guid` = '%d';", GUID_LOPART(guid
));
245 name
= (*result
)[0].GetString();
253 void ObjectMgr::LoadAuctions()
255 QueryResult
*result
= sDatabase
.PQuery( "SELECT * FROM `auctionhouse`;" );
264 Field
*fields
= result
->Fetch();
266 aItem
= new AuctionEntry
;
267 aItem
->auctioneer
= fields
[0].GetUInt32();
268 aItem
->item
= fields
[1].GetUInt32();
269 aItem
->owner
= fields
[2].GetUInt32();
270 aItem
->buyout
= fields
[3].GetUInt32();
271 aItem
->time
= fields
[4].GetUInt32();
272 aItem
->bidder
= fields
[5].GetUInt32();
273 aItem
->bid
= fields
[6].GetUInt32();
274 aItem
->Id
= fields
[7].GetUInt32();
276 } while (result
->NextRow());
281 void ObjectMgr::LoadItemPrototypes()
283 sItemStorage
.Load ();
284 sLog
.outString( ">> Loaded %u item prototypes", sItemStorage
.RecordCount
);
288 void ObjectMgr::LoadAuctionItems()
290 QueryResult
*result
= sDatabase
.PQuery( "SELECT * `FROM auctioned_item`;" );
297 fields
= result
->Fetch();
298 Item
* item
= new Item
;
299 item
->LoadFromDB(fields
[0].GetUInt32(), 2);
302 while( result
->NextRow() );
307 void ObjectMgr::LoadMailedItems()
309 QueryResult
*result
= sDatabase
.PQuery( "SELECT * FROM `mail_item`;" );
316 fields
= result
->Fetch();
317 Item
* item
= new Item
;
318 item
->LoadFromDB(fields
[0].GetUInt32(), 3);
321 while( result
->NextRow() );
326 void ObjectMgr::LoadGuilds()
329 QueryResult
*result
= sDatabase
.PQuery( "SELECT `guildid` FROM `guild`;" );
339 sLog
.outString( "" );
340 sLog
.outString( ">> Loaded %d guild definitions", count
);
344 barGoLink
bar( result
->GetRowCount() );
348 Field
*fields
= result
->Fetch();
353 newguild
= new Guild
;
354 newguild
->LoadGuildFromDB(fields
[0].GetUInt32());
357 }while( result
->NextRow() );
359 sLog
.outString( "" );
360 sLog
.outString( ">> Loaded %d guild definitions", count
);
363 void ObjectMgr::LoadQuests()
365 sQuestsStorage
.Load ();
366 sLog
.outString( ">> Loaded %d quests definitions", sQuestsStorage
.RecordCount
);
367 sLog
.outString( "" );
370 void ObjectMgr::AddGossipText(GossipText
*pGText
)
372 ASSERT( pGText
->Text_ID
);
373 ASSERT( mGossipText
.find(pGText
->Text_ID
) == mGossipText
.end() );
374 mGossipText
[pGText
->Text_ID
] = pGText
;
377 GossipText
*ObjectMgr::GetGossipText(uint32 Text_ID
)
379 GossipTextMap::const_iterator itr
;
380 for (itr
= mGossipText
.begin(); itr
!= mGossipText
.end(); itr
++)
382 if(itr
->second
->Text_ID
== Text_ID
)
388 void ObjectMgr::LoadGossipText()
391 QueryResult
*result
= sDatabase
.PQuery( "SELECT * FROM `npc_text`;" );
394 if( !result
) return;
397 barGoLink
bar( result
->GetRowCount() );
404 Field
*fields
= result
->Fetch();
408 pGText
= new GossipText
;
409 pGText
->Text_ID
= fields
[cic
++].GetUInt32();
411 for (int i
=0; i
< 8; i
++)
413 pGText
->Options
[i
].Text_0
= fields
[cic
++].GetString();
414 pGText
->Options
[i
].Text_1
= fields
[cic
++].GetString();
416 pGText
->Options
[i
].Language
= fields
[cic
++].GetUInt32();
417 pGText
->Options
[i
].Probability
= fields
[cic
++].GetFloat();
419 pGText
->Options
[i
].Emotes
[0]._Delay
= fields
[cic
++].GetUInt32();
420 pGText
->Options
[i
].Emotes
[0]._Emote
= fields
[cic
++].GetUInt32();
422 pGText
->Options
[i
].Emotes
[1]._Delay
= fields
[cic
++].GetUInt32();
423 pGText
->Options
[i
].Emotes
[1]._Emote
= fields
[cic
++].GetUInt32();
425 pGText
->Options
[i
].Emotes
[2]._Delay
= fields
[cic
++].GetUInt32();
426 pGText
->Options
[i
].Emotes
[2]._Emote
= fields
[cic
++].GetUInt32();
429 if ( !pGText
->Text_ID
) continue;
430 AddGossipText( pGText
);
432 } while( result
->NextRow() );
434 sLog
.outString( "" );
435 sLog
.outString( ">> Loaded %d npc texts", count
);
439 ItemPage
*ObjectMgr::RetreiveItemPageText(uint32 Page_ID
)
442 QueryResult
*result
= sDatabase
.PQuery("SELECT * FROM `item_page` WHERE `id` = '%d';", Page_ID
);
444 if( !result
) return NULL
;
446 pIText
= new ItemPage
;
453 Field
*fields
= result
->Fetch();
455 pIText
->Page_ID
= fields
[cic
++].GetUInt32();
457 pIText
->PageText
= fields
[cic
++].GetString();
458 pIText
->Next_Page
= fields
[cic
++].GetUInt32();
460 if ( !pIText
->Page_ID
) break;
461 } while( result
->NextRow() );
467 void ObjectMgr::AddAreaTriggerPoint(AreaTriggerPoint
*pArea
)
469 ASSERT( pArea
->Trigger_ID
);
470 ASSERT( mAreaTriggerMap
.find(pArea
->Trigger_ID
) == mAreaTriggerMap
.end() );
472 mAreaTriggerMap
[pArea
->Trigger_ID
] = pArea
;
475 AreaTriggerPoint
*ObjectMgr::GetAreaTriggerQuestPoint(uint32 Trigger_ID
)
477 AreaTriggerMap::const_iterator itr
;
478 for (itr
= mAreaTriggerMap
.begin(); itr
!= mAreaTriggerMap
.end(); itr
++)
480 if(itr
->second
->Trigger_ID
== Trigger_ID
)
486 void ObjectMgr::LoadAreaTriggerPoints()
489 QueryResult
*result
= sDatabase
.PQuery( "SELECT * FROM `areatrigger_involvedrelation`;" );
490 AreaTriggerPoint
*pArea
;
492 if( !result
) return;
494 barGoLink
bar( result
->GetRowCount() );
502 pArea
= new AreaTriggerPoint
;
504 Field
*fields
= result
->Fetch();
506 pArea
->Trigger_ID
= fields
[0].GetUInt32();
507 pArea
->Quest_ID
= fields
[1].GetUInt32();
508 pArea
->Creature_ID
= fields
[2].GetUInt32();
510 AddAreaTriggerPoint( pArea
);
512 } while( result
->NextRow() );
514 sLog
.outString( "" );
515 sLog
.outString( ">> Loaded %d quest trigger points", count
);
519 bool ObjectMgr::GetGlobalTaxiNodeMask( uint32 curloc
, uint32
*Mask
)
522 QueryResult
*result
= sDatabase
.PQuery("SELECT `taxipath.destination` FROM `taxipath` WHERE `taxipath.source` = '%d' ORDER BY `destination` LIMIT 1;", curloc
);
528 Field
*fields
= result
->Fetch();
529 uint8 destination
= fields
[0].GetUInt8();
530 uint8 field
= (uint8
)((destination
- 1) / 32);
531 Mask
[field
] |= 1 << ( (destination
- 1 ) % 32 );
536 uint32
ObjectMgr::GetNearestTaxiNode( float x
, float y
, float z
, uint32 mapid
)
539 QueryResult
*result
= sDatabase
.PQuery("SELECT `taxinode.id`, SQRT(pow(`taxinode.position_x`-'%f',2)+pow(`taxinode.position_y`-'%f',2)+pow(`taxinode.position_z`-'%f',2)) AS `distance` FROM `taxinode` WHERE `taxinode.continent` = '%u' ORDER BY `distance` LIMIT 1;", x
, y
, z
, mapid
);
545 Field
*fields
= result
->Fetch();
546 return fields
[0].GetUInt8();
550 void ObjectMgr::GetTaxiPath( uint32 source
, uint32 destination
, uint32
&path
, uint32
&cost
)
553 QueryResult
*result
= sDatabase
.PQuery("SELECT `taxipath.price`, `taxipath.id` FROM `taxipath` WHERE `taxipath.source` = '%u' AND `taxipath.destination` = '%u';", source
, destination
);
561 Field
*fields
= result
->Fetch();
562 cost
= fields
[0].GetUInt32();
563 path
= fields
[1].GetUInt16();
566 uint16
ObjectMgr::GetTaxiMount( uint32 id
)
569 QueryResult
*result
= sDatabase
.PQuery("SELECT `taxinode.mount` FROM `taxinode WHERE `taxinode.id` = '%u';", id
);
576 Field
*fields
= result
->Fetch();
577 return fields
[0].GetUInt16();
581 void ObjectMgr::GetTaxiPathNodes( uint32 path
, Path
&pathnodes
)
584 QueryResult
*result
= sDatabase
.PQuery("SELECT `taxipathnode.position_x`,`taxipathnode.position_y`,`taxipathnode.position_z` FROM `taxipathnode` WHERE `taxipathnode.path` = '%u';", path
);
589 uint16 count
= result
->GetRowCount();
590 sLog
.outDebug(" ROW COUNT %u ",count
);
591 pathnodes
.Resize( count
);
596 Field
*fields
= result
->Fetch();
597 pathnodes
[ i
].x
= fields
[0].GetFloat();
598 pathnodes
[ i
].y
= fields
[1].GetFloat();
599 pathnodes
[ i
].z
= fields
[2].GetFloat();
601 } while( result
->NextRow() );
604 GraveyardTeleport
*ObjectMgr::GetClosestGraveYard(float x
, float y
, float z
, uint32 MapId
)
607 QueryResult
*result
= sDatabase
.PQuery("SELECT SQRT(POW('%f'-`position_x`,2)+POW('%f'-`position_y`,2)+POW('%f'-`position_z`,2)) AS `distance`,`position_x`,`position_y`,`position_z`,`map` FROM `graveyard` WHERE `map` = '%d' ORDER BY `distance` ASC LIMIT 1;", x
, y
, z
, MapId
);
612 Field
*fields
= result
->Fetch();
613 GraveyardTeleport
*pgrave
= new GraveyardTeleport
;
615 pgrave
->X
= fields
[1].GetFloat();
616 pgrave
->Y
= fields
[2].GetFloat();
617 pgrave
->Z
= fields
[3].GetFloat();
618 pgrave
->MapId
= fields
[4].GetUInt32();
623 AreaTrigger
*ObjectMgr::GetAreaTrigger(uint32 Trigger_ID
)
626 QueryResult
*result
= sDatabase
.PQuery("SELECT `id` FROM `areatrigger_template` WHERE `id` = '%d';", Trigger_ID
);
630 Field
*fields
= result
->Fetch();
631 uint32 totrigger
= fields
[0].GetUInt32();
635 QueryResult
*result1
= sDatabase
.PQuery("SELECT `target_map`,`target_position_x`,`target_position_y`,`target_position_z` FROM `areatrigger_template` WHERE `id` = '%d';", totrigger
);
638 Field
*fields1
= result1
->Fetch();
639 AreaTrigger
*at
= new AreaTrigger
;
641 at
->mapId
= fields1
[0].GetUInt32();
643 at
->X
= fields1
[1].GetFloat();
644 at
->Y
= fields1
[2].GetFloat();
645 at
->Z
= fields1
[3].GetFloat();
654 void ObjectMgr::LoadTeleportCoords()
657 QueryResult
*result
= sDatabase
.PQuery( "SELECT * FROM `areatrigger_template`;" );
666 barGoLink
bar( result
->GetRowCount() );
670 Field
*fields
= result
->Fetch();
676 pTC
= new TeleportCoords
;
677 pTC
->id
= fields
[0].GetUInt32();
678 //pTC->Name = fields[6].GetString();
679 pTC
->mapId
= fields
[5].GetUInt32();
680 pTC
->x
= fields
[1].GetFloat();
681 pTC
->y
= fields
[2].GetFloat();
682 pTC
->z
= fields
[3].GetFloat();
684 AddTeleportCoords(pTC
);
686 } while( result
->NextRow() );
690 sLog
.outString( "" );
691 sLog
.outString( ">> Loaded %d teleport definitions", count
);
694 void ObjectMgr::SetHighestGuids()
697 QueryResult
*result
= sDatabase
.Query( "SELECT MAX(`guid`) FROM `character`;" );
700 m_hiCharGuid
= (*result
)[0].GetUInt32()+1;
705 result
= sDatabase
.Query( "SELECT MAX(`guid`) FROM `creature`;" );
708 m_hiCreatureGuid
= (*result
)[0].GetUInt32()+1;
713 result
= sDatabase
.Query( "SELECT MAX(`guid`) FROM `item_instance`;" );
716 m_hiItemGuid
= (*result
)[0].GetUInt32()+1;
721 result
= sDatabase
.Query("SELECT MAX(`guid`) FROM `gameobject`;" );
724 m_hiGoGuid
= (*result
)[0].GetUInt32()+1;
729 result
= sDatabase
.Query("SELECT MAX(`id`) FROM `auctionhouse`;" );
732 m_auctionid
= (*result
)[0].GetUInt32()+1;
740 result
= sDatabase
.PQuery( "SELECT MAX(`id`) FROM `mail`;" );
743 m_mailid
= (*result
)[0].GetUInt32()+1;
752 result
= sDatabase
.PQuery( "SELECT MAX(`guid`) FROM `corpse`;" );
755 m_hiCorpseGuid
= (*result
)[0].GetUInt32()+1;
762 uint32
ObjectMgr::GenerateAuctionID()
765 return ++m_auctionid
;
768 uint32
ObjectMgr::GenerateMailID()
773 uint32
ObjectMgr::GenerateLowGuid(uint32 guidhigh
)
778 case HIGHGUID_ITEM
: return ++m_hiItemGuid
;
779 case HIGHGUID_UNIT
: return ++m_hiCreatureGuid
;
780 case HIGHGUID_PLAYER
: return ++m_hiCharGuid
;
781 case HIGHGUID_GAMEOBJECT
: return ++m_hiGoGuid
;
782 case HIGHGUID_CORPSE
: return ++m_hiCorpseGuid
;
783 case HIGHGUID_DYNAMICOBJECT
: return ++m_hiDoGuid
;
790 GameObjectInfo
*ObjectMgr::GetGameObjectInfo(uint32 id
)
793 if(sGOStorage
.MaxEntry
<=id
)
795 sLog
.outString("ERROR: There is no GO with proto %u id the DB",id
);
799 return (sGOStorage
.MaxEntry
<=id
)?NULL
:(GameObjectInfo
*)sGOStorage
.pIndex
[id
];
803 void ObjectMgr::LoadGameobjectInfo()
807 sLog
.outString( ">> Loaded %d game object templates", sGOStorage
.RecordCount
);
811 ItemPrototype
* ObjectMgr::GetItemPrototype(uint32 id
)
813 return (sItemStorage
.MaxEntry
<=id
)?NULL
:(ItemPrototype
*)sItemStorage
.pIndex
[id
];