root/trunk/src/arcemu-world/ObjectMgr.cpp @ 2860

Revision 2860, 85.5 kB (checked in by Vlack, 12 months ago)

Notice: Trunk is now 3.2.0

FIXED: Mail sending (by providing a missing item for the world database, this item is necessary for the client - for the item, thanks goes to Darkgrööm)
FIXED: Battleground selection crash (now the server will queue you on Isle of Conquest - note: this does not mean you can play on it, but it solves the instant crash when players selected it)
FIXED: Glyphs (till we properly implement dual spec)
FIXED: A9 target GUID sending (on flags & UPDATEFLAG_HAS_TARGET - thanks Alleycat)
FIXED: Re-enabled ground targeted spells (on m_targetMask & TARGET_FLAG_DEST_LOCATION - if a spell where you can select the area of its effect crashes the client in the future, we'll revise this part)
FIXED: A9 (actually just moved the already existing code pieces up/down to better suit the required format, but to know the format right, I had looked into Mangos code too, as I haven't got months to figure out the right structure)
FIXED: TaxiMgr::GetGlobalTaxiNodeMask? (index check, as with the new DBCs we have a "to" with value "-1", and when that's used as an uint, it'll result in an index of 255, while the structure is from 0 to 11).
ADDED: Override support (this extends the core with special features for special gameobjects, like what's required for trams and transports, which include features as: "override update fields", "never despawn on same map", "announce on greater range" and "push to player on map entry").
FIXED: static map object pushing (repaired the buffer handling error which duplicated buffer content in a pretty unique way).
ADDED: SQL fixes for Deeprun and Ulduar Trams (retail data, but it works right only with the override system).
UPDATED: UpdateFields?.h
UPDATED: DBCs (thanks Xuni)
UPDATED: Error codes (thanks Hopla)
FIXED: various packets, especially the following ones: character enumeration, mail list, group details (raid difficulty), movement-related packets
FIXED: The display of quest rewards the player can choose from on the quest page before accepting it.
FIXED: A nasty bug when un-equipping an item to a bag and not to the backpack. The problem was that I have missed 2 for loops where the visible items get nulled out on unequip, it erased 17 fields instead of just 2, so it made the character pretty much naked.

  • Property svn:eol-style set to native
  • Property ff set to
    *.cpp = svn:eol-style=native
    Makefile = svn:eol-style=native
    README = svn:eol-style=native
    CHANGELOG = svn:eol-style=native
    LICENSE = svn:eol-style=native
Line 
1/*
2 * ArcEmu MMORPG Server
3 * Copyright (C) 2005-2007 Ascent Team <http://www.ascentemu.com/>
4 * Copyright (C) 2008-2009 <http://www.ArcEmu.org/>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include "StdAfx.h"
22
23initialiseSingleton( ObjectMgr );
24
25const char * NormalTalkMessage = "DMSG";
26
27ObjectMgr::ObjectMgr()
28{
29        m_hiPetGuid = 0;
30        m_hiContainerGuid = 0;
31        m_hiItemGuid = 0;
32        m_hiGroupId = 1;
33        m_mailid = 0;
34        m_hiPlayerGuid = 1;
35        m_hiCorpseGuid = 0;
36        m_hiArenaTeamId=0;
37        m_hiGuildId=0;
38        m_ticketid = 0;
39        memset(m_InstanceBossInfoMap , 0, sizeof(InstanceBossInfoMap*) * NUM_MAPS);
40}
41
42
43ObjectMgr::~ObjectMgr()
44{
45        Log.Notice("ObjectMgr", "Deleting Corpses...");
46        CorpseCollectorUnload();
47
48        Log.Notice("ObjectMgr", "Deleting Itemsets...");
49        for(ItemSetContentMap::iterator i = mItemSets.begin(); i != mItemSets.end(); ++i)
50        {
51                delete i->second;
52        }
53        mItemSets.clear();
54
55        Log.Notice("ObjectMgr", "Deleting PlayerCreateInfo...");
56        for( PlayerCreateInfoMap::iterator i = mPlayerCreateInfo.begin( ); i != mPlayerCreateInfo.end( ); ++ i ) {
57                delete i->second;
58        }
59        mPlayerCreateInfo.clear( );
60
61        Log.Notice("ObjectMgr", "Deleting Guilds...");
62        for ( GuildMap::iterator i = mGuild.begin(); i != mGuild.end(); ++i ) {
63                delete i->second;
64        }
65
66        Log.Notice("ObjectMgr", "Deleting Vendors...");
67        for( VendorMap::iterator i = mVendors.begin( ); i != mVendors.end( ); ++ i )
68        {
69                delete i->second;
70        }
71
72        Log.Notice("ObjectMgr", "Deleting Spell Override...");
73        for(OverrideIdMap::iterator i = mOverrideIdMap.begin(); i != mOverrideIdMap.end(); ++i)
74        {
75                delete i->second;
76        }
77
78        Log.Notice("ObjectMgr", "Deleting Trainers...");
79        for( TrainerMap::iterator i = mTrainers.begin( ); i != mTrainers.end( ); ++ i) {
80                Trainer * t = i->second;
81                if(t->UIMessage && t->UIMessage != (char*)NormalTalkMessage)
82                        delete [] t->UIMessage;
83                delete t;
84        }
85
86        Log.Notice("ObjectMgr", "Deleting Level Information...");
87        for( LevelInfoMap::iterator i = mLevelInfo.begin(); i != mLevelInfo.end(); ++i)
88        {
89                LevelMap * l = i->second;
90                for(LevelMap::iterator i2 = l->begin(); i2 != l->end(); ++i2)
91                {
92                        delete i2->second;
93                }
94                l->clear();
95                delete l;
96        }
97
98        Log.Notice("ObjectMgr", "Deleting Waypoint Cache...");
99        for(HM_NAMESPACE::hash_map<uint32, WayPointMap*>::iterator i = m_waypoints.begin(); i != m_waypoints.end(); ++i)
100        {
101                for(WayPointMap::iterator i2 = i->second->begin(); i2 != i->second->end(); ++i2)
102                        if((*i2))
103                                delete (*i2);
104
105                delete i->second;
106        }
107
108        Log.Notice("ObjectMgr", "Deleting timed emote Cache...");
109        for(HM_NAMESPACE::hash_map<uint32, TimedEmoteList*>::iterator i = m_timedemotes.begin(); i != m_timedemotes.end(); ++i)
110        {
111                for(TimedEmoteList::iterator i2 = i->second->begin(); i2 != i->second->end(); ++i2)
112                        if((*i2))
113                        {
114                                delete [] (*i2)->msg;
115                                delete (*i2);
116                        }
117
118                delete i->second;
119        }
120
121        Log.Notice("ObjectMgr", "Deleting NPC Say Texts...");
122        for(uint32 i = 0 ; i < NUM_MONSTER_SAY_EVENTS ; ++i)
123        {
124                NpcMonsterSay * p;
125                for(MonsterSayMap::iterator itr = mMonsterSays[i].begin(); itr != mMonsterSays[i].end(); ++itr)
126                {
127                        p = itr->second;
128                        for(uint32 j = 0; j < p->TextCount; ++j)
129                                free((char*)p->Texts[j]);
130                        delete [] p->Texts;
131                        free((char*)p->MonsterName);
132                        delete p;
133                }
134
135                mMonsterSays[i].clear();
136        }
137
138        Log.Notice("ObjectMgr", "Deleting Charters...");
139        for(int i = 0; i < NUM_CHARTER_TYPES; ++i)
140        {
141                for(HM_NAMESPACE::hash_map<uint32, Charter*>::iterator itr =  m_charters[i].begin(); itr != m_charters[i].end(); ++itr)
142                {
143                        delete itr->second;
144                }
145        }
146
147        Log.Notice("ObjectMgr", "Deleting Reputation Tables...");
148        for(ReputationModMap::iterator itr = this->m_reputation_creature.begin(); itr != m_reputation_creature.end(); ++itr)
149        {
150                ReputationModifier * mod = itr->second;
151                mod->mods.clear();
152                delete mod;
153        }
154        for(ReputationModMap::iterator itr = this->m_reputation_faction.begin(); itr != m_reputation_faction.end(); ++itr)
155        {
156                ReputationModifier * mod = itr->second;
157                mod->mods.clear();
158                delete mod;
159        }
160
161        for(HM_NAMESPACE::hash_map<uint32,InstanceReputationModifier*>::iterator itr = this->m_reputation_instance.begin(); itr != this->m_reputation_instance.end(); ++itr)
162        {
163                InstanceReputationModifier * mod = itr->second;
164                mod->mods.clear();
165                delete mod;
166        }
167
168        Log.Notice("ObjectMgr", "Deleting Groups...");
169        for(GroupMap::iterator itr = m_groups.begin(); itr != m_groups.end();)
170        {
171                Group* pGroup = itr->second;
172                ++itr;
173
174                if( pGroup != NULL )
175                {
176                        for( uint32 i = 0; i < pGroup->GetSubGroupCount(); ++i )
177                        {
178                                SubGroup* pSubGroup = pGroup->GetSubGroup( i );
179                                if( pSubGroup != NULL )
180                                {
181                                        pSubGroup->Disband();
182                                }
183                        }
184                        delete pGroup;
185                }
186        }
187
188        Log.Notice("ObjectMgr", "Deleting Player Information...");
189        for(HM_NAMESPACE::hash_map<uint32, PlayerInfo*>::iterator itr = m_playersinfo.begin(); itr != m_playersinfo.end(); ++itr)
190        {
191                itr->second->m_Group=NULL;
192                free(itr->second->name);
193                delete itr->second;
194        }
195
196        Log.Notice("ObjectMgr", "Deleting GM Tickets...");
197        for(GmTicketList::iterator itr = GM_TicketList.begin(); itr != GM_TicketList.end(); ++itr)
198                delete (*itr);
199
200        Log.Notice("ObjectMgr", "Deleting Boss Information...");
201        for(int i=0; i<NUM_MAPS; i++)
202        {
203                if(this->m_InstanceBossInfoMap[i] != NULL)
204                {
205                        for(InstanceBossInfoMap::iterator itr = this->m_InstanceBossInfoMap[i]->begin(); itr != m_InstanceBossInfoMap[i]->end(); ++itr)
206                                delete (*itr).second;
207                        delete this->m_InstanceBossInfoMap[i];
208                        this->m_InstanceBossInfoMap[i] = NULL;
209                }
210        }
211
212        Log.Notice("ObjectMgr", "Deleting Arena Teams...");
213        for(HM_NAMESPACE::hash_map<uint32, ArenaTeam*>::iterator itr = m_arenaTeams.begin(); itr != m_arenaTeams.end(); ++itr) {
214                delete (*itr).second;
215        }
216       
217        Log.Notice("ObjectMgr", "Deleting Profession Discoveries...");
218        std::set<ProfessionDiscovery*>::iterator itr = ProfessionDiscoveryTable.begin();
219        for ( ; itr != ProfessionDiscoveryTable.end(); itr++ )
220                delete (*itr);
221
222        Log.Notice("ObjectMgr", "Cleanup BroadCastStorages...");
223        m_BCEntryStorage.clear();
224
225}
226
227//
228// Groups
229//
230
231Group * ObjectMgr::GetGroupByLeader(Player* pPlayer)
232{
233        GroupMap::iterator itr;
234        Group * ret=NULL;
235        m_groupLock.AcquireReadLock();
236        for(itr = m_groups.begin(); itr != m_groups.end(); ++itr)
237        {
238                if(itr->second->GetLeader()==pPlayer->getPlayerInfo())
239                {
240                        ret = itr->second;
241                        break;
242                }
243        }
244
245        m_groupLock.ReleaseReadLock();
246        return ret;
247}
248
249Group * ObjectMgr::GetGroupById(uint32 id)
250{
251        GroupMap::iterator itr;
252        Group * ret=NULL;
253        m_groupLock.AcquireReadLock();
254        itr = m_groups.find(id);
255        if(itr!=m_groups.end())
256                ret=itr->second;
257
258        m_groupLock.ReleaseReadLock();
259        return ret;
260}
261
262//
263// Player names
264//
265void ObjectMgr::DeletePlayerInfo( uint32 guid )
266{
267        PlayerInfo * pl;
268        HM_NAMESPACE::hash_map<uint32,PlayerInfo*>::iterator i;
269        PlayerNameStringIndexMap::iterator i2;
270        playernamelock.AcquireWriteLock();
271        i=m_playersinfo.find(guid);
272        if(i==m_playersinfo.end())
273        {
274                playernamelock.ReleaseWriteLock();
275                return;
276        }
277
278        pl=i->second;
279        if(pl->m_Group)
280        {
281                pl->m_Group->RemovePlayer(pl);
282                pl->m_Group = NULL;
283        }
284
285        if(pl->guild)
286        {
287                if(pl->guild->GetGuildLeader()==pl->guid)
288                        pl->guild->Disband();
289                else
290                        pl->guild->RemoveGuildMember(pl,NULL);
291        }
292
293        string pnam = string(pl->name);
294        arcemu_TOLOWER(pnam);
295        i2 = m_playersInfoByName.find(pnam);
296        if( i2 != m_playersInfoByName.end() && i2->second == pl )
297                m_playersInfoByName.erase( i2 );
298
299        free(pl->name);
300        delete i->second;
301        m_playersinfo.erase(i);
302
303        playernamelock.ReleaseWriteLock();
304}
305
306PlayerInfo *ObjectMgr::GetPlayerInfo( uint32 guid )
307{
308        HM_NAMESPACE::hash_map<uint32,PlayerInfo*>::iterator i;
309        PlayerInfo * rv;
310        playernamelock.AcquireReadLock();
311        i=m_playersinfo.find(guid);
312        if(i!=m_playersinfo.end())
313                rv = i->second;
314        else
315                rv = NULL;
316        playernamelock.ReleaseReadLock();
317        return rv;
318}
319
320void ObjectMgr::AddPlayerInfo(PlayerInfo *pn)
321{
322        playernamelock.AcquireWriteLock();
323        m_playersinfo[pn->guid] =  pn ;
324        string pnam = string(pn->name);
325        arcemu_TOLOWER(pnam);
326        m_playersInfoByName[pnam] = pn;
327        playernamelock.ReleaseWriteLock();
328}
329
330void ObjectMgr::RenamePlayerInfo(PlayerInfo * pn, const char * oldname, const char * newname)
331{
332        playernamelock.AcquireWriteLock();
333        string oldn = string(oldname);
334        arcemu_TOLOWER(oldn);
335
336        PlayerNameStringIndexMap::iterator itr = m_playersInfoByName.find( oldn );
337        if( itr != m_playersInfoByName.end() && itr->second == pn )
338        {
339                string newn = string(newname);
340                arcemu_TOLOWER(newn);
341                m_playersInfoByName.erase( itr );
342                m_playersInfoByName[newn] = pn;
343        }
344
345        playernamelock.ReleaseWriteLock();
346}
347
348void ObjectMgr::LoadSpellSkills()
349{
350        uint32 i;
351//      int total = sSkillStore.GetNumRows();
352
353        for(i = 0; i < dbcSkillLineSpell.GetNumRows(); i++)
354        {
355                skilllinespell *sp = dbcSkillLineSpell.LookupRow(i);
356                if (sp)
357                {
358                        mSpellSkills[sp->spell] = sp;
359                }
360        }
361        Log.Notice("ObjectMgr", "%u spell skills loaded.", mSpellSkills.size());
362}
363
364skilllinespell* ObjectMgr::GetSpellSkill(uint32 id)
365{
366        return mSpellSkills[id];
367}
368
369SpellEntry* ObjectMgr::GetNextSpellRank( SpellEntry * sp, uint32 level )
370{
371        // Looks for next spell rank
372        if( sp == NULL )
373                return NULL;
374
375        skilllinespell* skill = GetSpellSkill( sp->Id );
376        if( skill != NULL && skill->next > 0 )
377        {
378                SpellEntry* sp1 = dbcSpell.LookupEntry( skill->next );
379                if( sp1->baseLevel <= level ) // check level
380                        return GetNextSpellRank( sp1, level ); // recursive for higher ranks
381        }
382        return sp;
383}
384
385void ObjectMgr::LoadPlayersInfo()
386{
387        PlayerInfo * pn;
388        QueryResult *result = CharacterDatabase.Query("SELECT guid,name,race,class,level,gender,zoneId,timestamp,acct FROM characters");
389        uint32 period, c;
390        if(result)
391        {
392                period = (result->GetRowCount() / 20) + 1;
393                c = 0;
394                do
395                {
396                        Field *fields = result->Fetch();
397                        pn=new PlayerInfo;
398                        pn->guid = fields[0].GetUInt32();
399                        pn->name = strdup(fields[1].GetString());
400                        pn->race = fields[2].GetUInt8();
401                        pn->cl = fields[3].GetUInt8();
402                        pn->lastLevel = fields[4].GetUInt32();
403                        pn->gender = fields[5].GetUInt8();
404                        pn->lastZone=fields[6].GetUInt32();
405                        pn->lastOnline=fields[7].GetUInt32();
406                        pn->acct = fields[8].GetUInt32();
407                        pn->m_Group=0;
408                        pn->subGroup=0;
409                        pn->m_loggedInPlayer=NULL;
410                        pn->guild=NULL;
411                        pn->guildRank=NULL;
412                        pn->guildMember=NULL;
413#ifdef VOICE_CHAT
414                        pn->groupVoiceId = -1;
415#endif
416                        // Raid & heroic Instance IDs
417                        // Must be done before entering world...
418                        QueryResult *result2 = CharacterDatabase.Query("SELECT `instanceid`, `mode`, `mapid` FROM `instanceids` WHERE `playerguid` = %u", pn->guid);
419                        if(result2)
420                        {
421                                PlayerInstanceMap::iterator itr;
422                                do
423                                {
424                                        uint32 instanceId = result2->Fetch()[0].GetUInt32();
425                                        uint32 mode = result2->Fetch()[1].GetUInt32();
426                                        uint32 mapId = result2->Fetch()[2].GetUInt32();
427                                        if(mode >= NUM_INSTANCE_MODES || mapId >= NUM_MAPS)
428                                                continue;
429
430                                        pn->savedInstanceIdsLock.Acquire();
431                                        itr = pn->savedInstanceIds[mode].find(mapId);
432                                        if(itr == pn->savedInstanceIds[mode].end())
433                                                pn->savedInstanceIds[mode].insert(PlayerInstanceMap::value_type(mapId, instanceId));
434                                        else
435                                                (*itr).second = instanceId;
436
437                                        //TODO: Instances not loaded yet ~.~
438                                        //if(!sInstanceMgr.InstanceExists(mapId, pn->m_savedInstanceIds[mapId][mode]))
439                                        //{
440                                        //      pn->m_savedInstanceIds[mapId][mode] = 0;
441                                        //      CharacterDatabase.Execute("DELETE FROM `instanceids` WHERE `mapId` = %u AND `instanceId` = %u AND `mode` = %u", mapId, instanceId, mode);
442                                        //}
443
444                                        pn->savedInstanceIdsLock.Release();
445                                } while (result2->NextRow());
446                                delete result2;
447                        }
448
449                        if(pn->race==RACE_HUMAN||pn->race==RACE_DWARF||pn->race==RACE_GNOME||pn->race==RACE_NIGHTELF||pn->race==RACE_DRAENEI)
450                                pn->team = 0;
451                        else
452                                pn->team = 1;
453
454                        if( GetPlayerInfoByName(pn->name) != NULL )
455                        {
456                                // gotta rename him
457                                char temp[300];
458                                snprintf(temp, 300, "%s__%X__", pn->name, pn->guid);
459                                Log.Notice("ObjectMgr", "Renaming duplicate player %s to %s. (%u)", pn->name,temp,pn->guid);
460                                CharacterDatabase.WaitExecute("UPDATE characters SET name = \"%s\", forced_rename_pending = 1 WHERE guid = %u",
461                                        CharacterDatabase.EscapeString(string(temp)).c_str(), pn->guid);
462
463                                free(pn->name);
464                                pn->name = strdup(temp);
465                        }
466
467                        string lpn=string(pn->name);
468                        arcemu_TOLOWER(lpn);
469                        m_playersInfoByName[lpn] = pn;
470
471                        //this is startup -> no need in lock -> don't use addplayerinfo
472                         m_playersinfo[(uint32)pn->guid]=pn;
473
474                         if( !((++c) % period) )
475                                 Log.Notice("PlayerInfo", "Done %u/%u, %u%% complete.", c, result->GetRowCount(), float2int32( (float(c) / float(result->GetRowCount()))*100.0f ));
476                } while( result->NextRow() );
477
478                delete result;
479        }
480        Log.Notice("ObjectMgr", "%u players loaded.", m_playersinfo.size());
481        LoadGuilds();
482}
483
484PlayerInfo* ObjectMgr::GetPlayerInfoByName(const char * name)
485{
486        string lpn=string(name);
487        arcemu_TOLOWER(lpn);
488        PlayerNameStringIndexMap::iterator i;
489        PlayerInfo *rv = NULL;
490        playernamelock.AcquireReadLock();
491
492        i=m_playersInfoByName.find(lpn);
493        if( i != m_playersInfoByName.end() )
494                rv = i->second;
495
496        playernamelock.ReleaseReadLock();
497        return rv;
498}
499#ifdef ENABLE_ACHIEVEMENTS
500void ObjectMgr::LoadCompletedAchievements()
501{
502        QueryResult *result = WorldDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
503
504        if(!result)
505        return;
506 do
507        {
508                Field *fields = result->Fetch();
509                allCompletedAchievements.insert(fields[0].GetUInt32());
510        } while(result->NextRow());
511 delete result;
512}
513#endif
514void ObjectMgr::LoadPlayerCreateInfo()
515{
516        QueryResult *result = WorldDatabase.Query( "SELECT * FROM playercreateinfo" );
517
518        if( !result )
519        {
520                Log.Error("MySQL","Query failed: SELECT * FROM playercreateinfo");
521                return;
522        }
523
524        PlayerCreateInfo *pPlayerCreateInfo;
525
526        do
527        {
528                Field *fields = result->Fetch();
529                if(result->GetFieldCount() != 25)
530                {
531                        Log.Error("MySQL","Wrong field count in table playercreateinfo (got %lu, need 25).  You may need to update your database.", result->GetFieldCount());
532                        delete result;
533                        return;
534                }
535                pPlayerCreateInfo = new PlayerCreateInfo;
536
537                pPlayerCreateInfo->index = fields[0].GetUInt8();
538                pPlayerCreateInfo->race = fields[1].GetUInt8();
539                pPlayerCreateInfo->factiontemplate = fields[2].GetUInt32();
540                pPlayerCreateInfo->class_ = fields[3].GetUInt8();
541                pPlayerCreateInfo->mapId = fields[4].GetUInt32();
542                pPlayerCreateInfo->zoneId = fields[5].GetUInt32();
543                pPlayerCreateInfo->positionX = fields[6].GetFloat();
544                pPlayerCreateInfo->positionY = fields[7].GetFloat();
545                pPlayerCreateInfo->positionZ = fields[8].GetFloat();
546                pPlayerCreateInfo->displayId = fields[9].GetUInt16();
547                pPlayerCreateInfo->strength = fields[10].GetUInt8();
548                pPlayerCreateInfo->ability = fields[11].GetUInt8();
549                pPlayerCreateInfo->stamina = fields[12].GetUInt8();
550                pPlayerCreateInfo->intellect = fields[13].GetUInt8();
551                pPlayerCreateInfo->spirit = fields[14].GetUInt8();
552                pPlayerCreateInfo->health = fields[15].GetUInt32();
553                pPlayerCreateInfo->mana = fields[16].GetUInt32();
554                pPlayerCreateInfo->rage = fields[17].GetUInt32();
555                pPlayerCreateInfo->focus = fields[18].GetUInt32();
556                pPlayerCreateInfo->energy = fields[19].GetUInt32();
557                pPlayerCreateInfo->attackpower = fields[20].GetUInt32();
558                pPlayerCreateInfo->mindmg = fields[21].GetFloat();
559                pPlayerCreateInfo->maxdmg = fields[22].GetFloat();
560                pPlayerCreateInfo->introid = fields[23].GetUInt32();
561
562                string taxiMaskStr = fields[24].GetString();
563                vector<string> tokens = StrSplit(taxiMaskStr, " ");
564
565                memset(pPlayerCreateInfo->taximask, 0, sizeof(pPlayerCreateInfo->taximask));
566                int index;
567                vector<string>::iterator iter;
568                for (iter = tokens.begin(), index = 0; (index < 12) && (iter != tokens.end()); ++iter, ++index)
569                {
570                        pPlayerCreateInfo->taximask[index] = atol((*iter).c_str());
571                }
572
573                QueryResult *sk_sql = WorldDatabase.Query(
574                        "SELECT * FROM playercreateinfo_skills WHERE indexid=%u",pPlayerCreateInfo->index);
575
576                if(sk_sql)
577                {
578                        do
579                        {
580                                Field *fields = sk_sql->Fetch();
581                                CreateInfo_SkillStruct tsk;
582                                tsk.skillid = fields[1].GetUInt32();
583                                tsk.currentval = fields[2].GetUInt32();
584                                tsk.maxval = fields[3].GetUInt32();
585                                pPlayerCreateInfo->skills.push_back(tsk);
586                        } while(sk_sql->NextRow());
587                        delete sk_sql;
588                }
589                QueryResult *sp_sql = WorldDatabase.Query(
590                        "SELECT * FROM playercreateinfo_spells WHERE indexid=%u",pPlayerCreateInfo->index);
591
592                if(sp_sql)
593                {
594                        do
595                        {
596                                pPlayerCreateInfo->spell_list.insert(sp_sql->Fetch()[1].GetUInt32());
597                        } while(sp_sql->NextRow());
598                        delete sp_sql;
599                }
600
601                QueryResult *items_sql = WorldDatabase.Query(
602                        "SELECT * FROM playercreateinfo_items WHERE indexid=%u",pPlayerCreateInfo->index);
603
604                if(items_sql)
605                {
606                        do
607                        {
608                                Field *fields = items_sql->Fetch();
609                                CreateInfo_ItemStruct itm;
610                                itm.protoid = fields[1].GetUInt32();
611                                itm.slot = fields[2].GetUInt8();
612                                itm.amount = fields[3].GetUInt32();
613                                pPlayerCreateInfo->items.push_back(itm);
614                        } while(items_sql->NextRow());
615                   delete items_sql;
616                }
617
618                QueryResult *bars_sql = WorldDatabase.Query(
619                        "SELECT * FROM playercreateinfo_bars WHERE class=%u",pPlayerCreateInfo->class_ );
620
621                if(bars_sql)
622                {
623                        do
624                        {
625                                Field *fields = bars_sql->Fetch();
626                                CreateInfo_ActionBarStruct bar;
627                                bar.button = fields[2].GetUInt32();
628                                bar.action = fields[3].GetUInt32();
629                                bar.type = fields[4].GetUInt32();
630                                bar.misc = fields[5].GetUInt32();
631                                pPlayerCreateInfo->actionbars.push_back(bar);
632                        } while(bars_sql->NextRow());
633                        delete bars_sql;
634                }
635
636                mPlayerCreateInfo[pPlayerCreateInfo->index] = pPlayerCreateInfo;
637        } while( result->NextRow() );
638
639        delete result;
640
641        Log.Notice("ObjectMgr", "%u player create infos loaded.", mPlayerCreateInfo.size());
642        GenerateLevelUpInfo();
643}
644
645// DK:LoadGuilds()
646void ObjectMgr::LoadGuilds()
647{
648        QueryResult *result = CharacterDatabase.Query( "SELECT * FROM guilds" );
649        if(result)
650        {
651                uint32 period = (result->GetRowCount() / 20) + 1;
652                uint32 c = 0;
653                do
654                {
655                        Guild * pGuild = Guild::Create();
656                        if(!pGuild->LoadFromDB(result->Fetch()))
657                        {
658                                delete pGuild;
659                        }
660                        else
661                                mGuild.insert(make_pair(pGuild->GetGuildId(), pGuild));
662
663                        if( !((++c) % period) )
664                                Log.Notice("Guilds", "Done %u/%u, %u%% complete.", c, result->GetRowCount(), float2int32( (float(c) / float(result->GetRowCount()))*100.0f ));
665
666                } while(result->NextRow());
667                delete result;
668        }
669        Log.Notice("ObjectMgr", "%u guilds loaded.", mGuild.size());
670}
671
672Corpse* ObjectMgr::LoadCorpse(uint32 guid)
673{
674        Corpse *pCorpse;
675        QueryResult *result = CharacterDatabase.Query("SELECT * FROM Corpses WHERE guid =%u ", guid );
676
677        if( !result )
678                return NULL;
679
680        do
681        {
682                Field *fields = result->Fetch();
683                pCorpse = new Corpse(HIGHGUID_TYPE_CORPSE,fields[0].GetUInt32());
684                pCorpse->SetPosition(fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat());
685                pCorpse->SetZoneId(fields[5].GetUInt32());
686                pCorpse->SetMapId(fields[6].GetUInt32());
687                pCorpse->LoadValues( fields[7].GetString());
688                if(pCorpse->GetUInt32Value(CORPSE_FIELD_DISPLAY_ID) == 0)
689                {
690                        delete pCorpse;
691                        continue;
692                }
693
694                pCorpse->SetLoadedFromDB(true);
695                pCorpse->SetInstanceID(fields[8].GetUInt32());
696                pCorpse->AddToWorld();
697         } while( result->NextRow() );
698
699        delete result;
700
701        return pCorpse;
702}
703
704
705//------------------------------------------------------
706// Live corpse retreival.
707// comments: I use the same tricky method to start from the last corpse instead of the first
708//------------------------------------------------------
709Corpse *ObjectMgr::GetCorpseByOwner(uint32 ownerguid)
710{
711        CorpseMap::const_iterator itr;
712        Corpse *rv = NULL;
713        _corpseslock.Acquire();
714        for (itr = m_corpses.begin();itr != m_corpses.end(); ++itr)
715        {
716                if(itr->second->GetUInt32Value(CORPSE_FIELD_OWNER) == ownerguid)
717                {
718                        rv = itr->second;
719                        break;
720                }
721        }
722        _corpseslock.Release();
723
724
725        return rv;
726}
727
728void ObjectMgr::DelinkPlayerCorpses(Player *pOwner)
729{
730        //dupe protection agaisnt crashs
731        Corpse * c;
732        c=this->GetCorpseByOwner(pOwner->GetLowGUID());
733        if(!c)return;
734        sEventMgr.AddEvent(c, &Corpse::Delink, EVENT_CORPSE_SPAWN_BONES, 1, 1, 0);
735        CorpseAddEventDespawn(c);
736}
737
738void ObjectMgr::LoadGMTickets()
739{
740        QueryResult *result = CharacterDatabase.Query( "SELECT `guid`, `playerGuid`, `name`, `level`, `map`, `posX`, `posY`, `posZ`, `message`, `timestamp`, `deleted`, `assignedto`, `comment` FROM gm_tickets WHERE deleted=0" );
741
742        GM_Ticket *ticket;
743        if(result == 0)
744                return;
745
746        do
747        {
748                Field *fields = result->Fetch();
749
750                ticket = new GM_Ticket;
751                ticket->guid = fields[0].GetUInt64();
752                ticket->playerGuid = fields[1].GetUInt64();
753                ticket->name = fields[2].GetString();
754                ticket->level = fields[3].GetUInt32();
755                ticket->map = fields[4].GetUInt32();
756                ticket->posX = fields[5].GetFloat();
757                ticket->posY = fields[6].GetFloat();
758                ticket->posZ = fields[7].GetFloat();
759                ticket->message = fields[8].GetString();
760                ticket->timestamp = fields[9].GetUInt32();
761                ticket->deleted = fields[10].GetBool();
762                ticket->assignedToPlayer = fields[11].GetUInt64();
763                ticket->comment = fields[12].GetString();
764
765                AddGMTicket(ticket, true);
766
767        } while( result->NextRow() );
768
769        Log.Notice("ObjectMgr", "%u active GM Tickets loaded.", result->GetRowCount());
770        delete result;
771}
772
773void ObjectMgr::LoadInstanceBossInfos()
774{
775        char *p, *q, *trash;
776        MapInfo * mapInfo;
777        QueryResult * result = WorldDatabase.Query("SELECT `mapid`, `creatureid`, `trash`, `trash_respawn_override` FROM `instance_bosses`");
778
779        if(result == NULL)
780                return;
781
782        uint32 cnt = 0;
783        do
784        {
785                InstanceBossInfo * bossInfo = new InstanceBossInfo();
786                bossInfo->mapid = (uint32)result->Fetch()[0].GetUInt32();
787
788                mapInfo = WorldMapInfoStorage.LookupEntry(bossInfo->mapid);
789                if(mapInfo == NULL || mapInfo->type == INSTANCE_NULL)
790                {
791                        sLog.outDetail("Not loading boss information for map %u! (continent or unknown map)", bossInfo->mapid);
792                        delete bossInfo;
793                        continue;
794                }
795                if(bossInfo->mapid >= NUM_MAPS)
796                {
797                        sLog.outDetail("Not loading boss information for map %u! (map id out of range)", bossInfo->mapid);
798                        delete bossInfo;
799                        continue;
800                }
801
802                bossInfo->creatureid = (uint32)result->Fetch()[1].GetUInt32();
803                trash = strdup(result->Fetch()[2].GetString());
804                q = trash;
805                p = strchr(q, ' ');
806                while(p)
807                {
808                        *p = 0;
809                        uint32 val = atoi(q);
810                        if(val)
811                                bossInfo->trash.insert(val);
812                        q = p + 1;
813                        p = strchr(q, ' ');
814                }
815                free(trash);
816                bossInfo->trashRespawnOverride = (uint32)result->Fetch()[3].GetUInt32();
817
818
819                if(this->m_InstanceBossInfoMap[bossInfo->mapid] == NULL)
820                        this->m_InstanceBossInfoMap[bossInfo->mapid] = new InstanceBossInfoMap;
821                this->m_InstanceBossInfoMap[bossInfo->mapid]->insert(InstanceBossInfoMap::value_type(bossInfo->creatureid, bossInfo));
822                cnt++;
823        } while(result->NextRow());
824       
825        delete result;
826        Log.Notice("ObjectMgr", "%u boss information loaded.", cnt);
827}
828
829void ObjectMgr::SaveGMTicket(GM_Ticket* ticket, QueryBuffer * buf)
830{
831        std::stringstream ss;
832        ss << "REPLACE INTO gm_tickets (`guid`, `playerGuid`, `name`, `level`, `map`, `posX`, `posY`, `posZ`, `message`, `timestamp`, `deleted`, `assignedto`, `comment`) VALUES(";
833        ss << ticket->guid << ", ";
834        ss << ticket->playerGuid << ", '";
835        ss << CharacterDatabase.EscapeString(ticket->name) << "', ";
836        ss << ticket->level << ", ";
837        ss << ticket->map << ", ";
838        ss << ticket->posX << ", ";
839        ss << ticket->posY << ", ";
840        ss << ticket->posZ << ", '";
841        ss << CharacterDatabase.EscapeString(ticket->message) << "', ";
842        ss << ticket->timestamp << ", ";
843        ss << ticket->deleted << ", ";
844        ss << ticket->assignedToPlayer << ", '";
845        ss << CharacterDatabase.EscapeString(ticket->comment) << "');";
846
847        if(buf == NULL)
848                CharacterDatabase.ExecuteNA(ss.str( ).c_str( ));
849        else
850                buf->AddQueryStr(ss.str());
851}
852
853void ObjectMgr::SetHighestGuids()
854{
855        QueryResult *result;
856
857        result = CharacterDatabase.Query( "SELECT MAX(guid) FROM characters" );
858        if( result )
859        {
860                m_hiPlayerGuid = result->Fetch()[0].GetUInt32();
861                delete result;
862        }
863
864        result = CharacterDatabase.Query("SELECT MAX(guid) FROM playeritems");
865        if( result )
866        {
867                m_hiItemGuid = (uint32)result->Fetch()[0].GetUInt32();
868                delete result;
869        }
870
871        result = CharacterDatabase.Query( "SELECT MAX(guid) FROM corpses" );
872        if( result )
873        {
874                m_hiCorpseGuid = result->Fetch()[0].GetUInt32();
875                delete result;
876        }
877
878        result = WorldDatabase.Query("SELECT MAX(id) FROM creature_spawns");
879        if(result)
880        {
881                m_hiCreatureSpawnId = result->Fetch()[0].GetUInt32();
882                delete result;
883        }
884
885        result = WorldDatabase.Query("SELECT MAX(id) FROM gameobject_spawns");
886        if(result)
887        {
888                m_hiGameObjectSpawnId = result->Fetch()[0].GetUInt32();
889                delete result;
890        }
891
892        result = CharacterDatabase.Query("SELECT MAX(group_id) FROM groups");
893        if(result)
894        {
895                m_hiGroupId = result->Fetch()[0].GetUInt32();
896                delete result;
897        }
898
899        result = CharacterDatabase.Query("SELECT MAX(charterId) FROM charters");
900        if(result)
901        {
902                m_hiCharterId = result->Fetch()[0].GetUInt32();
903                delete result;
904        }
905
906        result = CharacterDatabase.Query("SELECT MAX(guildId) FROM guilds");
907        if(result)
908        {
909                m_hiGuildId = result->Fetch()[0].GetUInt32();
910                delete result;
911        }
912
913        result = CharacterDatabase.Query("SELECT MAX(guid) FROM gm_tickets");
914        if(result)
915        {
916                m_ticketid = result->Fetch()[0].GetUInt64() + 1;
917                delete result;
918        }
919
920        Log.Notice("ObjectMgr", "HighGuid(CORPSE) = %u", m_hiCorpseGuid);
921        Log.Notice("ObjectMgr", "HighGuid(PLAYER) = %u", m_hiPlayerGuid);
922        Log.Notice("ObjectMgr", "HighGuid(GAMEOBJ) = %u", m_hiGameObjectSpawnId);
923        Log.Notice("ObjectMgr", "HighGuid(UNIT) = %u", m_hiCreatureSpawnId);
924        Log.Notice("ObjectMgr", "HighGuid(ITEM) = %u", m_hiItemGuid);
925        Log.Notice("ObjectMgr", "HighGuid(CONTAINER) = %u", m_hiContainerGuid);
926        Log.Notice("ObjectMgr", "HighGuid(GROUP) = %u", m_hiGroupId);
927        Log.Notice("ObjectMgr", "HighGuid(CHARTER) = %u", m_hiCharterId);
928        Log.Notice("ObjectMgr", "HighGuid(GUILD) = %u", m_hiGuildId);
929        Log.Notice("ObjectMgr", "HighGuid(TICKET) = %u", m_ticketid - 1);
930}
931
932uint64 ObjectMgr::GenerateTicketID()
933{
934        return m_ticketid++;
935}
936
937uint32 ObjectMgr::GenerateMailID()
938{
939        return m_mailid++;
940}
941uint32 ObjectMgr::GenerateLowGuid(uint32 guidhigh)
942{
943        ASSERT(guidhigh == HIGHGUID_TYPE_ITEM || guidhigh == HIGHGUID_TYPE_CONTAINER || guidhigh == HIGHGUID_TYPE_PLAYER);
944
945        uint32 ret;
946        if(guidhigh == HIGHGUID_TYPE_ITEM)
947        {
948                m_guidGenMutex.Acquire();
949                ret = ++m_hiItemGuid;
950                m_guidGenMutex.Release();
951        }else if(guidhigh==HIGHGUID_TYPE_PLAYER)
952        {
953                m_playerguidlock.Acquire();
954                ret = ++m_hiPlayerGuid;
955                m_playerguidlock.Release();
956        }else{
957                m_guidGenMutex.Acquire();
958                ret = ++m_hiContainerGuid;
959                m_guidGenMutex.Release();
960        }
961        return ret;
962}
963
964void ObjectMgr::ProcessGameobjectQuests()
965{
966        /*if(!mGameObjectNames.size())
967                return;
968
969        int total = mGameObjectNames.size();
970        std::set<Quest*> tmp;
971        for(HM_NAMESPACE::hash_map<uint32, Quest*>::iterator itr = sQuestMgr.Begin(); itr != sQuestMgr.End(); ++itr)
972        {
973                Quest *qst = itr->second;
974                if(qst->count_required_item > 0 ||
975                        qst->required_mobtype[0] == QUEST_MOB_TYPE_GAMEOBJECT ||
976                        qst->required_mobtype[1] == QUEST_MOB_TYPE_GAMEOBJECT ||
977                        qst->required_mobtype[2] == QUEST_MOB_TYPE_GAMEOBJECT ||
978                        qst->required_mobtype[3] == QUEST_MOB_TYPE_GAMEOBJECT )
979                {
980                        tmp.insert(qst);
981                }
982        }
983        std::vector<GameObjectInfo*> gos;
984        gos.reserve(5000);
985        for(GameObjectNameMap::iterator it0 = mGameObjectNames.begin(); it0 != mGameObjectNames.end(); ++it0)
986        {
987                GameObjectInfo *gon = it0->second;
988                gos.push_back(it0->second);
989        }
990
991        int c = 0;
992        total = gos.size();
993        for(std::vector<GameObjectInfo*>::iterator it0 = gos.begin(); it0 != gos.end(); ++it0)
994        {
995                GameObjectInfo *gon = (*it0);
996
997                map<uint32, std::set<uint32> >* golootlist = &(LootMgr::getSingleton().quest_loot_go);
998                map<uint32, std::set<uint32> >::iterator it2 = golootlist->find(gon->ID);
999                //// QUEST PARSING
1000                for(std::set<Quest*>::iterator itr = tmp.begin(); itr != tmp.end(); ++itr)
1001                {
1002                        Quest *qst = *itr;
1003                        int max = qst->count_required_mob;
1004                        if(qst->count_required_item > max)
1005                                max = qst->count_required_item;
1006
1007                        if(max > 0)
1008                        {
1009                                for(int i = 0; i < max; ++i)
1010                                {
1011                                        if(qst->required_mob[i] > 0)
1012                                        {
1013                                                if(qst->required_mob[i] == gon->ID &&
1014                                                qst->required_mobtype[i] == QUEST_MOB_TYPE_GAMEOBJECT)
1015                                                {
1016                                                        gon->goMap.insert( GameObjectGOMap::value_type( qst, qst->required_mobcount[i] ) );
1017                                                        sDatabase.WaitExecute("INSERT INTO gameobject_quest_pickup_binding VALUES(%u, %u, %u)",
1018                                                                gon->ID, qst->id, qst->required_mobcount[i]);
1019                                                }
1020                                        }
1021                                        if(qst->required_itemcount[i] > 0 && it2 != golootlist->end())
1022                                        {
1023                                                // check our loot template for this item
1024                                                for(std::set<uint32>::iterator it4 = it2->second.begin(); it4 != it2->second.end(); ++it4)
1025                                                {
1026                                                        if((*it4) == qst->required_item[i])
1027                                                        {
1028                                                                //GOQuestItem it;
1029                                                                //it.itemid = qst->required_item[i];
1030                                                                //it.requiredcount = qst->required_itemcount[i];
1031                                                                //gon->itemMap.insert( GameObjectItemMap::value_type( qst, it ) );
1032                                                                //gon->itemMap[qst].insert(it);
1033                                                                gon->itemMap[qst].insert( std::map<uint32, uint32>::value_type( qst->required_item[i], qst->required_itemcount[i]) );
1034                                                                sDatabase.WaitExecute("INSERT INTO gameobject_quest_item_binding VALUES(%u, %u, %u, %u)",
1035                                                                        gon->ID, qst->id, qst->required_item[i], qst->required_itemcount[i]);
1036                                                        }
1037                                                }
1038                                        }
1039                                }
1040                        }
1041                }
1042                c++;
1043                if(!(c % 150))
1044                        SetProgressBar(c, total, "Binding");
1045        }
1046        ClearProgressBar();*/
1047        QueryResult * result  = WorldDatabase.Query("SELECT * FROM gameobject_quest_item_binding");
1048        QueryResult * result2 = WorldDatabase.Query("SELECT * FROM gameobject_quest_pickup_binding");
1049
1050        GameObjectInfo * gon;
1051        Quest * qst;
1052
1053        if(result)
1054        {
1055                do
1056                {
1057                        Field * fields = result->Fetch();
1058                        gon = GameObjectNameStorage.LookupEntry(fields[0].GetUInt32());
1059                        qst = QuestStorage.LookupEntry(fields[1].GetUInt32());
1060                        if(gon && qst)
1061                                gon->itemMap[qst].insert( make_pair( fields[2].GetUInt32(), fields[3].GetUInt32() ) );
1062
1063                } while(result->NextRow());
1064                delete result;
1065        }
1066
1067
1068        if(result2)
1069        {
1070                do
1071                {
1072                        Field * fields = result2->Fetch();
1073                        gon = GameObjectNameStorage.LookupEntry(fields[0].GetUInt32());
1074                        qst = QuestStorage.LookupEntry(fields[1].GetUInt32());
1075                        if(gon && qst)
1076                                gon->goMap.insert( make_pair( qst, fields[2].GetUInt32() ) );
1077
1078                } while(result2->NextRow());
1079                delete result2;
1080        }
1081
1082        result = WorldDatabase.Query("SELECT * FROM npc_gossip_textid");
1083        if(result)
1084        {
1085                uint32 entry, text;
1086                do
1087                {
1088                        entry = result->Fetch()[0].GetUInt32();
1089                        text  = result->Fetch()[1].GetUInt32();
1090
1091                        mNpcToGossipText[entry] = text;
1092
1093                } while(result->NextRow());
1094                delete result;
1095        }
1096        Log.Notice("ObjectMgr", "%u NPC Gossip TextIds loaded.", mNpcToGossipText.size());
1097}
1098
1099Player* ObjectMgr::GetPlayer(const char* name, bool caseSensitive)
1100{
1101        Player * rv = NULL;
1102        PlayerStorageMap::const_iterator itr;
1103        _playerslock.AcquireReadLock();
1104
1105        if(!caseSensitive)
1106        {
1107                std::string strName = name;
1108                arcemu_TOLOWER(strName);
1109                for (itr = _players.begin(); itr != _players.end(); ++itr)
1110                {
1111                        if(!stricmp(itr->second->GetNameString()->c_str(), strName.c_str()))
1112                        {
1113                                rv = itr->second;
1114                                break;
1115                        }
1116                }
1117        }
1118        else
1119        {
1120                for (itr = _players.begin(); itr != _players.end(); ++itr)
1121                {
1122                        if(!strcmp(itr->second->GetName(), name))
1123                        {
1124                                rv = itr->second;
1125                                break;
1126                        }
1127                }
1128        }
1129
1130        _playerslock.ReleaseReadLock();
1131
1132        return rv;
1133}
1134
1135Player* ObjectMgr::GetPlayer(uint32 guid)
1136{
1137        Player * rv;
1138
1139        _playerslock.AcquireReadLock();
1140        PlayerStorageMap::const_iterator itr = _players.find(guid);
1141        rv = (itr != _players.end()) ? itr->second : NULL;
1142        _playerslock.ReleaseReadLock();
1143
1144        return rv;
1145}
1146
1147PlayerCreateInfo* ObjectMgr::GetPlayerCreateInfo(uint8 race, uint8 class_) const
1148{
1149        PlayerCreateInfoMap::const_iterator itr;
1150        for (itr = mPlayerCreateInfo.begin(); itr != mPlayerCreateInfo.end(); itr++)
1151        {
1152                if( (itr->second->race == race) && (itr->second->class_ == class_) )
1153                        return itr->second;
1154        }
1155        return NULL;
1156}
1157
1158void ObjectMgr::AddGuild(Guild *pGuild)
1159{
1160        ASSERT( pGuild );
1161        mGuild[pGuild->GetGuildId()] = pGuild;
1162}
1163
1164uint32 ObjectMgr::GetTotalGuildCount()
1165{
1166        return (uint32)mGuild.size();
1167}
1168
1169bool ObjectMgr::RemoveGuild(uint32 guildId)
1170{
1171        GuildMap::iterator i = mGuild.find(guildId);
1172        if (i == mGuild.end())
1173        {
1174                return false;
1175        }
1176
1177
1178        mGuild.erase(i);
1179        return true;
1180}
1181
1182Guild* ObjectMgr::GetGuild(uint32 guildId)
1183{
1184        GuildMap::const_iterator itr = mGuild.find(guildId);
1185        if(itr == mGuild.end())
1186                return NULL;
1187        return itr->second;
1188}
1189
1190Guild* ObjectMgr::GetGuildByLeaderGuid(uint64 leaderGuid)
1191{
1192        GuildMap::const_iterator itr;
1193        for (itr = mGuild.begin();itr != mGuild.end(); itr++)
1194        {
1195                if( itr->second->GetGuildLeader() == leaderGuid )
1196                        return itr->second;
1197        }
1198        return NULL;
1199}
1200
1201Guild* ObjectMgr::GetGuildByGuildName(std::string guildName)
1202{
1203        GuildMap::const_iterator itr;
1204        for (itr = mGuild.begin();itr != mGuild.end(); itr++)
1205        {
1206                if( itr->second->GetGuildName() == guildName )
1207                        return itr->second;
1208        }
1209        return NULL;
1210}
1211
1212
1213void ObjectMgr::AddGMTicket(GM_Ticket *ticket, bool startup)
1214{
1215        ASSERT( ticket );
1216        GM_TicketList.push_back(ticket);
1217
1218        // save
1219        if(!startup)
1220                SaveGMTicket(ticket, NULL);
1221}
1222
1223void ObjectMgr::UpdateGMTicket(GM_Ticket *ticket)
1224{
1225        SaveGMTicket(ticket, NULL);
1226}
1227
1228void ObjectMgr::DeleteGMTicketPermanently(uint64 ticketGuid)
1229{
1230        for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
1231        {
1232                if((*i)->guid == ticketGuid)
1233                {
1234                        i = GM_TicketList.erase(i);
1235                }
1236                else
1237                {
1238                        ++i;
1239                }
1240        }
1241
1242        // kill from db
1243        CharacterDatabase.Execute("DELETE FROM gm_tickets WHERE guid=%u", ticketGuid);
1244}
1245
1246void ObjectMgr::DeleteAllRemovedGMTickets()
1247{
1248        for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
1249        {
1250                if((*i)->deleted)
1251                {
1252                        i = GM_TicketList.erase(i);
1253                }
1254                else
1255                {
1256                        ++i;
1257                }
1258        }
1259
1260        CharacterDatabase.Execute("DELETE FROM gm_tickets WHERE deleted=1");
1261}
1262
1263void ObjectMgr::RemoveGMTicketByPlayer(uint64 playerGuid)
1264{
1265        for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
1266        {
1267                if((*i)->playerGuid == playerGuid && !(*i)->deleted)
1268                {
1269                        (*i)->deleted = true;
1270                        SaveGMTicket((*i), NULL);
1271                }
1272                ++i;
1273        }
1274}
1275
1276void ObjectMgr::RemoveGMTicket(uint64 ticketGuid)
1277{
1278        for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
1279        {
1280                if((*i)->guid == ticketGuid && !(*i)->deleted)
1281                {
1282                        (*i)->deleted = true;
1283                        SaveGMTicket((*i), NULL);
1284                }
1285                ++i;
1286        }
1287}
1288
1289GM_Ticket* ObjectMgr::GetGMTicketByPlayer(uint64 playerGuid)
1290{
1291        for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
1292        {
1293                if((*i)->playerGuid == playerGuid && !(*i)->deleted)
1294                {
1295                        return (*i);
1296                }
1297                ++i;
1298        }
1299        return NULL;
1300}
1301
1302GM_Ticket* ObjectMgr::GetGMTicket(uint64 ticketGuid)
1303{
1304        for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
1305        {
1306                if((*i)->guid == ticketGuid)
1307                {
1308                        return (*i);
1309                }
1310                ++i;
1311        }
1312        return NULL;
1313}
1314
1315//std::list<GM_Ticket*>* ObjectMgr::GetGMTicketsByPlayer(uint64 playerGuid)
1316//{
1317//      std::list<GM_Ticket*>* list = new std::list<GM_Ticket*>();
1318//      for(GmTicketList::iterator i = GM_TicketList.begin(); i != GM_TicketList.end();)
1319//      {
1320//              if((*i)->playerGuid == playerGuid)
1321//              {
1322//                      list->push_back((*i));
1323//              }
1324//              ++i;
1325//      }
1326//      return list;
1327//}
1328
1329void ObjectMgr::LoadVendors()
1330{
1331        HM_NAMESPACE::hash_map<uint32, std::vector<CreatureItem>*>::const_iterator itr;
1332        std::vector<CreatureItem> *items;
1333        CreatureItem itm;
1334
1335        QueryResult *result = WorldDatabase.Query("SELECT * FROM vendors");
1336        if( result != NULL )
1337        {
1338                if( result->GetFieldCount() < 6 )
1339                {
1340                        Log.Notice("ObjectMgr", "Invalid format in vendors (%u/6) columns, not enough data to proceed.\n", result->GetFieldCount() );
1341                        delete result;
1342                        return;
1343                }
1344                else if( result->GetFieldCount() > 6 )
1345                {
1346                        Log.Notice("ObjectMgr", "Invalid format in vendors (%u/6) columns, loading anyway because we have enough data\n", result->GetFieldCount() );
1347                }
1348
1349                ItemExtendedCostEntry * ec = NULL;
1350                do
1351                {
1352                        Field* fields = result->Fetch();
1353
1354                        itr = mVendors.find( fields[0].GetUInt32() );
1355
1356                        if( itr == mVendors.end() )
1357                        {
1358                                items = new std::vector<CreatureItem>;
1359                                mVendors[fields[0].GetUInt32()] = items;
1360                        }
1361                        else
1362                        {
1363                                items = itr->second;
1364                        }
1365
1366                        itm.itemid = fields[1].GetUInt32();
1367                        itm.amount = fields[2].GetUInt32();
1368                        itm.available_amount = fields[3].GetUInt32();
1369                        itm.max_amount = fields[3].GetUInt32();
1370                        itm.incrtime = fields[4].GetUInt32();
1371                        if ( fields[5].GetUInt32() > 0 )
1372                        {
1373                                ec = dbcItemExtendedCost.LookupEntryForced( fields[5].GetUInt32() );
1374                                if ( ec == NULL )
1375                                        Log.Warning("LoadVendors", "Extendedcost for item %u references nonexistent EC %u", fields[1].GetUInt32(), fields[5].GetUInt32() );
1376                        }
1377                        else
1378                                ec = NULL;
1379                        itm.extended_cost = ec;
1380                        items->push_back( itm );
1381                }
1382                while( result->NextRow() );
1383
1384                delete result;
1385        }
1386        Log.Notice("ObjectMgr", "%u vendors loaded.", mVendors.size());
1387}
1388
1389void ObjectMgr::ReloadVendors()
1390{
1391        mVendors.clear();
1392        LoadVendors();
1393}
1394
1395std::vector<CreatureItem>* ObjectMgr::GetVendorList(uint32 entry)
1396{
1397        return mVendors[entry];
1398}
1399
1400void ObjectMgr::LoadTotemSpells()
1401{
1402        std::stringstream query;
1403        QueryResult *result = WorldDatabase.Query( "SELECT * FROM totemspells" );
1404
1405        if(!result)
1406        {
1407                return;
1408        }
1409
1410        //TotemSpells *ts = NULL;
1411        SpellEntry * sp;
1412        uint32 spellid;
1413
1414        do
1415        {
1416                Field *fields = result->Fetch();
1417                spellid = fields[1].GetUInt32();
1418                sp = dbcSpell.LookupEntry(spellid);
1419                if(!spellid || !sp) continue;
1420
1421                m_totemSpells.insert( TotemSpellMap::value_type( fields[0].GetUInt32(), sp ));
1422        } while( result->NextRow() );
1423
1424        delete result;
1425        Log.Notice("ObjectMgr", "%u totem spells loaded.", m_totemSpells.size());
1426}
1427
1428SpellEntry* ObjectMgr::GetTotemSpell(uint32 spellId)
1429{
1430        return m_totemSpells[spellId];
1431}
1432
1433void ObjectMgr::LoadAIThreatToSpellId()
1434{
1435        QueryResult *result = WorldDatabase.Query( "SELECT * FROM ai_threattospellid" );
1436
1437        if(!result)
1438        {
1439                return;
1440        }
1441
1442        SpellEntry * sp;
1443
1444        do
1445        {
1446                Field *fields = result->Fetch();
1447                sp = dbcSpell.LookupEntryForced( fields[0].GetUInt32() );
1448                if( sp != NULL )
1449                {
1450                        sp->ThreatForSpell = fields[1].GetUInt32();
1451                        sp->ThreatForSpellCoef = fields[2].GetFloat();
1452                }
1453                else
1454                        Log.Warning("AIThreatSpell", "Cannot apply to spell %u; spell is nonexistent.", fields[0].GetUInt32());
1455
1456        } while( result->NextRow() );
1457
1458        delete result;
1459}
1460
1461void ObjectMgr::LoadSpellProcs()
1462{
1463        SpellEntry* sp;
1464        QueryResult * result = WorldDatabase.Query("SELECT * FROM spell_proc");
1465        if(result)
1466        {
1467                do
1468                {
1469                        Field * f = result->Fetch();
1470                        uint32 spe_spellId = f[0].GetUInt32();
1471                        uint32 spe_NameHash = f[1].GetUInt32();
1472
1473                        if( spe_spellId )
1474                        {
1475                                sp = dbcSpell.LookupEntryForced( spe_spellId );
1476                                if( sp != NULL )
1477                                {
1478                                        int x;
1479                                        for( x = 0; x < 3; ++x )
1480                                                if( sp->ProcOnNameHash[x] == 0 )
1481                                                        break;
1482
1483                                        if( x != 3 )
1484                                        {
1485                                                sp->ProcOnNameHash[x] = spe_NameHash;
1486                                        }
1487                                        else
1488                                                sLog.outError( "Wrong ProcOnNameHash for Spell: %u!", spe_spellId );
1489
1490                                        sp->procFlags = f[2].GetUInt32();
1491
1492                                        if( f[3].GetUInt32() == 1 )
1493                                                sp->procFlags |= PROC_TARGET_SELF;
1494                                        if( f[4].GetInt32() >= 0 )
1495                                                sp->procChance = f[4].GetUInt32();
1496                                        if( f[5].GetInt32() >= 0 )
1497                                                sp->procCharges = f[5].GetInt32();
1498
1499                                        sp->proc_interval = f[6].GetUInt32();
1500
1501                                        if( f[7].GetInt32() >= 0 )
1502                                                sp->EffectTriggerSpell[0] = f[7].GetUInt32();
1503                                        if( f[8].GetInt32() >= 0 )
1504                                                sp->EffectTriggerSpell[1] = f[8].GetUInt32();
1505                                        if( f[9].GetInt32() >= 0 )
1506                                                sp->EffectTriggerSpell[2] = f[9].GetUInt32();
1507                                }
1508                        }
1509
1510                }while(result->NextRow());
1511                delete result;
1512        }
1513}
1514
1515void ObjectMgr::LoadSpellEffectsOverride()
1516{
1517        SpellEntry* sp;
1518        QueryResult * result = WorldDatabase.Query("SELECT * FROM spell_effects_override");
1519        if(result)
1520        {
1521                do
1522                {
1523                        Field * f = result->Fetch();
1524                        uint32 seo_SpellId = f[0].GetUInt32();
1525                        uint32 seo_EffectId = f[1].GetUInt32();
1526                        uint32 seo_Disable = f[2].GetUInt32();
1527                        uint32 seo_Effect = f[3].GetUInt32();
1528                        uint32 seo_BasePoints = f[4].GetUInt32();
1529                        uint32 seo_ApplyAuraName = f[5].GetUInt32();
1530                        //uint32 seo_SpellGroupRelation = f[6].GetUInt32();
1531                        uint32 seo_MiscValue = f[7].GetUInt32();
1532                        uint32 seo_TriggerSpell = f[8].GetUInt32();
1533                        uint32 seo_ImplicitTargetA = f[9].GetUInt32();
1534                        uint32 seo_ImplicitTargetB = f[10].GetUInt32();
1535
1536                        if( seo_SpellId )
1537                        {
1538                                sp = dbcSpell.LookupEntryForced( seo_SpellId );
1539                                if( sp != NULL )
1540                                {
1541                                        if( seo_Disable )
1542                                                sp->Effect[seo_EffectId] = 0;
1543
1544                                        if( seo_Effect )
1545                                                sp->Effect[seo_EffectId] = seo_Effect;
1546
1547                                        if( seo_BasePoints )
1548                                                sp->EffectBasePoints[seo_EffectId] = seo_BasePoints;
1549
1550                                        if( seo_ApplyAuraName )
1551                                                sp->EffectApplyAuraName[seo_EffectId] = seo_ApplyAuraName;
1552
1553//                                      if( seo_SpellGroupRelation )
1554//                                              sp->EffectSpellGroupRelation[seo_EffectId] = seo_SpellGroupRelation;
1555
1556                                        if( seo_MiscValue )
1557                                                sp->EffectMiscValue[seo_EffectId] = seo_MiscValue;
1558
1559                                        if( seo_TriggerSpell )
1560                                                sp->EffectTriggerSpell[seo_EffectId] = seo_TriggerSpell;
1561
1562                                        if( seo_ImplicitTargetA )
1563                                                sp->EffectImplicitTargetA[seo_EffectId] = seo_ImplicitTargetA;
1564
1565                                        if( seo_ImplicitTargetB )
1566                                                sp->EffectImplicitTargetB[seo_EffectId] = seo_ImplicitTargetB;
1567                                }
1568                        }
1569
1570                }while(result->NextRow());
1571                delete result;
1572        }
1573}
1574
1575Item * ObjectMgr::CreateItem(uint32 entry,Player * owner)
1576{
1577        ItemPrototype * proto = ItemPrototypeStorage.LookupEntry(entry);
1578        if(proto == 0) return 0;
1579
1580        if(proto->InventoryType == INVTYPE_BAG)
1581        {
1582                Container * pContainer = new Container(HIGHGUID_TYPE_CONTAINER,GenerateLowGuid(HIGHGUID_TYPE_CONTAINER));
1583                pContainer->Create( entry, owner);
1584                pContainer->SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1);
1585                return pContainer;
1586        }
1587        else
1588        {
1589                Item * pItem = ItemPool.PooledNew();
1590                if (!pItem)
1591                        return NULL;
1592                pItem->Init(HIGHGUID_TYPE_ITEM,GenerateLowGuid(HIGHGUID_TYPE_ITEM));
1593                pItem->Create(entry, owner);
1594                pItem->SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1);
1595                return pItem;
1596        }
1597}
1598
1599Item * ObjectMgr::LoadItem(uint64 guid)
1600{
1601        QueryResult * result = CharacterDatabase.Query("SELECT * FROM playeritems WHERE guid = %u", GUID_LOPART(guid));
1602        Item * pReturn = 0;
1603
1604        if(result)
1605        {
1606                ItemPrototype * pProto = ItemPrototypeStorage.LookupEntry(result->Fetch()[2].GetUInt32());
1607                if(!pProto)
1608                        return NULL;
1609
1610                if(pProto->InventoryType == INVTYPE_BAG)
1611                {
1612                        Container * pContainer = new Container(HIGHGUID_TYPE_CONTAINER,(uint32)guid);
1613                        pContainer->LoadFromDB(result->Fetch());
1614                        pReturn = pContainer;
1615                }
1616                else
1617                {
1618                        Item * pItem = ItemPool.PooledNew();
1619                        if (!pItem)
1620                                return NULL;
1621                        pItem->Init(HIGHGUID_TYPE_ITEM,(uint32)guid);
1622                        pItem->LoadFromDB(result->Fetch(), 0, false);
1623                        pReturn = pItem;
1624                }
1625                delete result;
1626        }
1627
1628        return pReturn;
1629}
1630
1631Item * ObjectMgr::LoadExternalItem(uint64 guid)
1632{
1633        QueryResult * result = CharacterDatabase.Query("SELECT * FROM playeritems_external WHERE guid = %u", GUID_LOPART(guid));
1634        Item * pReturn = 0;
1635
1636        if(result)
1637        {
1638                ItemPrototype * pProto = ItemPrototypeStorage.LookupEntry(result->Fetch()[2].GetUInt32());
1639                if(!pProto)
1640                        return NULL;
1641
1642                if(pProto->InventoryType == INVTYPE_BAG)
1643                {
1644                        Container * pContainer = new Container(HIGHGUID_TYPE_CONTAINER,(uint32)guid);
1645                        pContainer->LoadFromDB(result->Fetch());
1646                        pReturn = pContainer;
1647                }
1648                else
1649                {
1650                        Item * pItem = ItemPool.PooledNew();
1651                        if (!pItem)
1652                                return NULL;
1653                        pItem->Init(HIGHGUID_TYPE_ITEM,(uint32)guid);
1654                        pItem->LoadFromDB(result->Fetch(), 0, false);
1655                        pReturn = pItem;
1656                }
1657                delete result;
1658        }
1659
1660        return pReturn;
1661}
1662
1663void ObjectMgr::LoadCorpses(MapMgr * mgr)
1664{
1665        Corpse *pCorpse = NULL;
1666
1667        QueryResult *result = CharacterDatabase.Query("SELECT * FROM corpses WHERE instanceId = %u", mgr->GetInstanceID());
1668
1669        if(result)
1670        {
1671                do
1672                {
1673                        Field *fields = result->Fetch();
1674                        pCorpse = new Corpse(HIGHGUID_TYPE_CORPSE,fields[0].GetUInt32());
1675                        pCorpse->SetPosition(fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat());
1676                        pCorpse->SetZoneId(fields[5].GetUInt32());
1677                        pCorpse->SetMapId(fields[6].GetUInt32());
1678                        pCorpse->SetInstanceID(fields[7].GetUInt32());
1679                        pCorpse->LoadValues( fields[8].GetString());
1680                        if(pCorpse->GetUInt32Value(CORPSE_FIELD_DISPLAY_ID) == 0)
1681                        {
1682                                delete pCorpse;
1683                                continue;
1684                        }
1685
1686                        pCorpse->PushToWorld(mgr);
1687                } while( result->NextRow() );
1688
1689                delete result;
1690        }
1691}
1692
1693#ifdef ENABLE_ACHIEVEMENTS
1694AchievementCriteriaEntryList const& ObjectMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type)
1695{
1696    return m_AchievementCriteriasByType[type];
1697}
1698
1699void ObjectMgr::LoadAchievementCriteriaList()
1700{
1701        for (uint32 rowId = 0; rowId<dbcAchievementCriteriaStore.GetNumRows(); ++rowId)
1702        {
1703                AchievementCriteriaEntry const* criteria = dbcAchievementCriteriaStore.LookupRow(rowId);
1704                if(!criteria)
1705                        continue;
1706
1707                m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
1708        }
1709}
1710#endif
1711std::list<ItemPrototype*>* ObjectMgr::GetListForItemSet(uint32 setid)
1712{
1713        return mItemSets[setid];
1714}
1715
1716void ObjectMgr::CorpseAddEventDespawn(Corpse *pCorpse)
1717{
1718        if(!pCorpse->IsInWorld())
1719                delete pCorpse;
1720        else
1721                sEventMgr.AddEvent(pCorpse->GetMapMgr(), &MapMgr::EventCorpseDespawn, pCorpse->GetGUID(), EVENT_CORPSE_DESPAWN, 600000, 1,0);
1722}
1723
1724void ObjectMgr::DespawnCorpse(uint64 Guid)
1725{
1726        Corpse * pCorpse = objmgr.GetCorpse((uint32)Guid);
1727        if(pCorpse == 0)        // Already Deleted
1728                return;
1729
1730        pCorpse->Despawn();
1731        delete pCorpse;
1732}
1733
1734void ObjectMgr::CorpseCollectorUnload()
1735{
1736        CorpseMap::const_iterator itr;
1737        _corpseslock.Acquire();
1738        for (itr = m_corpses.begin(); itr != m_corpses.end();)
1739        {
1740                Corpse * c =itr->second;
1741                ++itr;
1742                if(c->IsInWorld())
1743                        c->RemoveFromWorld(false);
1744                delete c;
1745        }
1746        m_corpses.clear();
1747        _corpseslock.Release();
1748}
1749
1750GossipMenu::GossipMenu(uint64 Creature_Guid, uint32 Text_Id) : TextId(Text_Id), CreatureGuid(Creature_Guid)
1751{
1752
1753}
1754
1755void GossipMenu::AddItem(uint8 Icon, const char* Text, int32 Id /* = -1 */, int8 Extra /* = 0 */)
1756{
1757        GossipMenuItem Item;
1758        Item.Icon = Icon;
1759        Item.Extra = Extra;
1760        Item.Text = Text;
1761        Item.m_gBoxMessage = "";
1762        Item.m_gBoxMoney = 0;
1763        Item.Id = (uint32)Menu.size();
1764        if(Id > 0)
1765                Item.IntId = Id;
1766        else
1767                Item.IntId = Item.Id;
1768
1769        Menu.push_back(Item);
1770}
1771
1772void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded)
1773{
1774        GossipMenuItem Item;
1775        Item.Icon = Icon;
1776        Item.Extra = Coded;
1777        Item.Text = Message.c_str();
1778        Item.m_gBoxMessage = BoxMessage;
1779        Item.m_gBoxMoney = BoxMoney;
1780        Item.Id = (uint32)Menu.size();
1781        Item.IntId = Item.Id;
1782
1783        Menu.push_back(Item);
1784}
1785
1786void GossipMenu::AddItem(GossipMenuItem* GossipItem)
1787{
1788        Menu.push_back(*GossipItem);
1789}
1790
1791void GossipMenu::BuildPacket(WorldPacket& Packet)
1792{
1793        Packet << CreatureGuid;
1794        Packet << uint32(0);                    // some new menu type in 2.4?
1795        Packet << TextId;
1796        Packet << uint32(Menu.size());
1797
1798        for(std::vector<GossipMenuItem>::iterator iter = Menu.begin();
1799                iter != Menu.end(); ++iter)
1800        {
1801                Packet << iter->Id;
1802                Packet << iter->Icon;
1803                Packet << iter->Extra;
1804                Packet << uint32(iter->m_gBoxMoney);    // money required to open menu, 2.0.3
1805                Packet << iter->Text;
1806                Packet << iter->m_gBoxMessage;          // accept text (related to money) pop up box, 2.0.3
1807        }
1808}
1809
1810void GossipMenu::SendTo(Player* Plr)
1811{
1812        WorldPacket data(SMSG_GOSSIP_MESSAGE, Menu.size() * 50 + 12);
1813        BuildPacket(data);
1814        data << uint32(0);  // 0 quests obviously
1815        Plr->GetSession()->SendPacket(&data);
1816}
1817
1818void ObjectMgr::CreateGossipMenuForPlayer(GossipMenu** Location, uint64 Guid, uint32 TextID, Player* Plr)
1819{
1820        GossipMenu *Menu = new GossipMenu(Guid, TextID);
1821        ASSERT(Menu);
1822
1823        if(Plr->CurrentGossipMenu != NULL)
1824                delete Plr->CurrentGossipMenu;
1825
1826        Plr->CurrentGossipMenu = Menu;
1827        *Location = Menu;
1828}
1829
1830GossipMenuItem GossipMenu::GetItem(uint32 Id)
1831{
1832        if(Id >= Menu.size())
1833        {
1834                GossipMenuItem k;
1835                k.IntId = 1;
1836                return k;
1837        } else {
1838                return Menu[Id];
1839        }
1840}
1841
1842uint32 ObjectMgr::GetGossipTextForNpc(uint32 ID)
1843{
1844        return mNpcToGossipText[ID];
1845}
1846
1847void ObjectMgr::LoadTrainers()
1848{
1849        QueryResult * result = WorldDatabase.Query("SELECT * FROM trainer_defs");
1850        QueryResult * result2;
1851        Field * fields2;
1852        const char * temp;
1853        size_t len;
1854
1855        LoadDisabledSpells();
1856
1857        if(!result)
1858                return;
1859
1860
1861        do
1862        {
1863                Field * fields = result->Fetch();
1864                uint32 entry = fields[0].GetUInt32();
1865                Trainer * tr = new Trainer;
1866                tr->RequiredSkill = fields[1].GetUInt32();
1867                tr->RequiredSkillLine = fields[2].GetUInt32();
1868                tr->RequiredClass = fields[3].GetUInt32();
1869                tr->RequiredRace  = fields[4].GetUInt32();
1870                tr->RequiredRepFaction = fields[5].GetUInt32();
1871                tr->RequiredRepValue   = fields[6].GetUInt32();
1872                tr->TrainerType = fields[7].GetUInt32();
1873                tr->Can_Train_Gossip_TextId = fields[9].GetUInt32();
1874                tr->Cannot_Train_GossipTextId = fields[10].GetUInt32();
1875                tr->UIMessage = (char*)NormalTalkMessage;
1876                if(!tr->Can_Train_Gossip_TextId)
1877                        tr->Can_Train_Gossip_TextId=1;
1878                if(!tr->Cannot_Train_GossipTextId)
1879                        tr->Cannot_Train_GossipTextId=1;
1880
1881                temp = fields[8].GetString();
1882                len=strlen(temp);
1883                if(len)
1884                {
1885                        tr->UIMessage = new char[len+1];
1886                        strcpy(tr->UIMessage, temp);
1887                        tr->UIMessage[len] = 0;
1888                }
1889
1890                //now load the spells
1891                result2 = WorldDatabase.Query("SELECT * FROM trainer_spells where entry='%u'",entry);
1892                if(!result2)
1893                {
1894                        Log.Error("LoadTrainers", "Trainer with no spells, entry %u.", entry);
1895                        if(tr->UIMessage != NormalTalkMessage)
1896                                delete [] tr->UIMessage;
1897                        delete tr;
1898                        continue;
1899                }
1900                if(result2->GetFieldCount() != 10)
1901                {
1902                        Log.LargeErrorMessage(LARGERRORMESSAGE_WARNING, "Trainers table format is invalid. Please update your database.");
1903                        delete tr;
1904                        return;
1905                }
1906                else
1907                {
1908                        do
1909                        {
1910                                fields2 = result2->Fetch();
1911                                TrainerSpell ts;
1912                                bool abrt=false;
1913                                uint32 CastSpellID=fields2[1].GetUInt32();
1914                                uint32 LearnSpellID=fields2[2].GetUInt32();
1915
1916                                ts.pCastSpell = NULL;
1917                                ts.pLearnSpell = NULL;
1918                                ts.pCastRealSpell = NULL;
1919
1920                                if( CastSpellID != 0 )
1921                                {
1922                                        ts.pCastSpell = dbcSpell.LookupEntryForced( CastSpellID );
1923                                        if( ts.pCastSpell )
1924                                        {
1925                                                for( int k = 0; k < 3; ++k )
1926                                                {
1927                                                        if( ts.pCastSpell->Effect[k] == SPELL_EFFECT_LEARN_SPELL )
1928                                                        {
1929                                                                ts.pCastRealSpell = dbcSpell.LookupEntryForced(ts.pCastSpell->EffectTriggerSpell[k]);
1930                                                                if( ts.pCastRealSpell == NULL )
1931                                                                {
1932                                                                        Log.Warning("Trainers", "Trainer %u contains cast spell %u that is non-teaching\n", entry, CastSpellID);
1933                                                                        abrt = true;
1934                                                                }
1935                                                                break;
1936                                                        }
1937                                                }
1938                                        }
1939
1940                                        if( abrt )
1941                                                continue;
1942                                }
1943
1944                                if( LearnSpellID != 0 )
1945                                {
1946                                        ts.pLearnSpell = dbcSpell.LookupEntryForced( LearnSpellID );
1947                                }
1948
1949                                if( ts.pCastSpell == NULL && ts.pLearnSpell == NULL )
1950                                {
1951                                        Log.Warning("LoadTrainers", "Trainer %u without valid spells (%u/%u).", entry, CastSpellID, LearnSpellID);
1952                                        continue; //omg a bad spell !
1953                                }
1954
1955                                if( ts.pCastSpell && !ts.pCastRealSpell)
1956                                        continue;
1957
1958                                ts.Cost = fields2[3].GetUInt32();
1959                                ts.RequiredSpell = fields2[4].GetUInt32();
1960                                ts.RequiredSkillLine = fields2[5].GetUInt32();
1961                                ts.RequiredSkillLineValue = fields2[6].GetUInt32();
1962                                ts.RequiredLevel = fields2[7].GetUInt32();
1963                                ts.DeleteSpell = fields2[8].GetUInt32();
1964                                ts.IsProfession = (fields2[9].GetUInt32() != 0) ? true : false;
1965                                tr->Spells.push_back(ts);
1966                        }
1967                        while(result2->NextRow());
1968                        delete result2;
1969
1970                        tr->SpellCount = (uint32)tr->Spells.size();
1971
1972                        //and now we insert it to our lookup table
1973                        if(!tr->SpellCount)
1974                        {
1975                                if(tr->UIMessage != NormalTalkMessage)
1976                                        delete [] tr->UIMessage;
1977                                delete tr;
1978                                continue;
1979                        }
1980
1981                        mTrainers.insert( TrainerMap::value_type( entry, tr ) );
1982                }
1983
1984        } while(result->NextRow());
1985        delete result;
1986        Log.Notice("ObjectMgr", "%u trainers loaded.", mTrainers.size());
1987}
1988
1989Trainer* ObjectMgr::GetTrainer(uint32 Entry)
1990{
1991        TrainerMap::iterator iter = mTrainers.find(Entry);
1992        if(iter == mTrainers.end())
1993                return NULL;
1994
1995        return iter->second;
1996}
1997
1998void ObjectMgr::GenerateLevelUpInfo()
1999{
2000        // Generate levelup information for each class.
2001        PlayerCreateInfo * PCI;
2002        for(uint32 Class = WARRIOR; Class <= DRUID; ++Class)
2003        {
2004                // These are empty.
2005                        if(Class == 10)
2006                                continue;
2007
2008                // Search for a playercreateinfo.
2009                for(uint32 Race = RACE_HUMAN; Race <= RACE_DRAENEI; ++Race )
2010                {
2011                        PCI = GetPlayerCreateInfo(static_cast<uint8>( Race ), static_cast<uint8>( Class ));
2012
2013                        if(PCI == 0)
2014                                continue;   // Class not valid for this race.
2015
2016                        // Generate each level's information
2017                        uint32 MaxLevel = sWorld.m_genLevelCap + 1;
2018                        LevelInfo* lvl=0, lastlvl;
2019                        lastlvl.HP = PCI->health;
2020                        lastlvl.Mana = PCI->mana;
2021                        lastlvl.Stat[0] = PCI->strength;
2022                        lastlvl.Stat[1] = PCI->ability;
2023                        lastlvl.Stat[2] = PCI->stamina;
2024                        lastlvl.Stat[3] = PCI->intellect;
2025                        lastlvl.Stat[4] = PCI->spirit;
2026                        lastlvl.XPToNextLevel = 400;
2027                        LevelMap * lMap = new LevelMap;
2028
2029                        // Create first level.
2030                        lvl = new LevelInfo;
2031                        *lvl = lastlvl;
2032
2033                        // Insert into map
2034                        lMap->insert( LevelMap::value_type( 1, lvl ) );
2035
2036                        uint32 val;
2037                        for(uint32 Level = 2; Level < MaxLevel; ++Level)
2038                        {
2039                                lvl = new LevelInfo;
2040
2041                                // Calculate Stats
2042                                for(uint32 s = 0; s < 5; ++s)
2043                                {
2044                                        val = GainStat(static_cast<uint16>( Level ), static_cast<uint8>( Class ), static_cast<uint8>( s ));
2045                                        lvl->Stat[s] = lastlvl.Stat[s] + val;
2046                                }
2047
2048                                // Calculate HP/Mana
2049                                uint32 TotalHealthGain = 0;
2050                                uint32 TotalManaGain = 0;
2051
2052                                switch(Class)
2053                                {
2054                                case WARRIOR:
2055                                        if(Level<13)TotalHealthGain+=19;
2056                                        else if(Level <36) TotalHealthGain+=Level+6;
2057//                                      else if(Level >60) TotalHealthGain+=Level+100;
2058                                        else if(Level >60) TotalHealthGain+=Level+206;
2059                                        else TotalHealthGain+=2*Level-30;
2060                                        break;
2061                                case HUNTER:
2062                                        if(Level<13)TotalHealthGain+=17;
2063//                                      else if(Level >60) TotalHealthGain+=Level+45;
2064                                        else if(Level >60) TotalHealthGain+=Level+161;
2065                                        else TotalHealthGain+=Level+4;
2066
2067                                        if(Level<11)TotalManaGain+=29;
2068                                        else if(Level<27)TotalManaGain+=Level+18;
2069//                                      else if(Level>60)TotalManaGain+=Level+20;
2070                                        else if(Level>60)TotalManaGain+=Level+150;
2071                                        else TotalManaGain+=45;
2072                                        break;
2073                                case ROGUE:
2074                                        if(Level <15)TotalHealthGain+=17;
2075//                                      else if(Level >60) TotalHealthGain+=Level+110;
2076                                        else if(Level >60) TotalHealthGain+=Level+191;
2077                                        else TotalHealthGain+=Level+2;
2078                                        break;
2079                                case DRUID:
2080                                        if(Level < 17)TotalHealthGain+=17;
2081//                                      else if(Level >60) TotalHealthGain+=Level+55;
2082                                        else if(Level >60) TotalHealthGain+=Level+176;
2083                                        else TotalHealthGain+=Level;
2084
2085                                        if(Level < 26)TotalManaGain+=Level+20;
2086//                                      else if(Level>60)TotalManaGain+=Level+25;
2087                                        else if(Level>60)TotalManaGain+=Level+150;
2088                                        else TotalManaGain+=45;
2089                                        break;
2090                                case MAGE:
2091                                        if(Level < 23)TotalHealthGain+=15;
2092//                                      else if(Level >60) TotalHealthGain+=Level+40;
2093                                        else if(Level >60) TotalHealthGain+=Level+190;
2094                                        else TotalHealthGain+=Level-8;
2095
2096                                        if(Level <28)TotalManaGain+=Level+23;
2097//                                      else if(Level>60)TotalManaGain+=Level+26;
2098                                        else if(Level>60)TotalManaGain+=Level+115;
2099                                        else TotalManaGain+=51;
2100                                        break;
2101                                case SHAMAN:
2102                                        if(Level <16)TotalHealthGain+=17;
2103//                                      else if(Level >60) TotalHealthGain+=Level+75;
2104                                        else if(Level >60) TotalHealthGain+=Level+157;
2105                                        else TotalHealthGain+=Level+1;
2106
2107                                        if(Level<22)TotalManaGain+=Level+19;
2108//                                      else if(Level>60)TotalManaGain+=Level+70;
2109                                        else if(Level>60)TotalManaGain+=Level+175;
2110                                        else TotalManaGain+=49;
2111                                        break;
2112                                case WARLOCK:
2113                                        if(Level <17)TotalHealthGain+=17;
2114//                                      else if(Level >60) TotalHealthGain+=Level+50;
2115                                        else if(Level >60) TotalHealthGain+=Level+192;
2116                                        else TotalHealthGain+=Level-2;
2117
2118                                        if(Level< 30)TotalManaGain+=Level+21;
2119//                                      else if(Level>60)TotalManaGain+=Level+25;
2120                                        else if(Level>60)TotalManaGain+=Level+121;
2121                                        else TotalManaGain+=51;
2122                                        break;
2123                                case PALADIN:
2124                                        if(Level < 14)TotalHealthGain+=18;
2125//                                      else if(Level >60) TotalHealthGain+=Level+55;
2126                                        else if(Level >60) TotalHealthGain+=Level+167;
2127                                        else TotalHealthGain+=Level+4;
2128
2129                                        if(Level<30)TotalManaGain+=Level+17;
2130//                                      else if(Level>60)TotalManaGain+=Level+100;
2131                                        else if(Level>60)TotalManaGain+=Level+131;
2132                                        else TotalManaGain+=42;
2133                                        break;
2134                                case PRIEST:
2135                                        if(Level <21)TotalHealthGain+=15;
2136//                                      else if(Level >60) TotalHealthGain+=Level+40;
2137                                        else if(Level >60) TotalHealthGain+=Level+157;
2138                                        else TotalHealthGain+=Level-6;
2139
2140                                        if(Level <22)TotalManaGain+=Level+22;
2141                                        else if(Level <32)TotalManaGain+=Level+37;
2142//                                      else if(Level>60)TotalManaGain+=Level+35;
2143                                        else if(Level>60)TotalManaGain+=Level+207;
2144                                        else TotalManaGain+=54;
2145                                        break;
2146                                case DEATHKNIGHT: // Based on 55-56 more testing will be done.
2147                                        if(Level < 60)TotalHealthGain+=92;
2148                                        /*else if(Level <60) TotalHealthGain+=??;
2149                                        else if(Level <70) TotalHealthGain+=??;*/
2150                                        else TotalHealthGain+=92;
2151                                        break;
2152                                }
2153
2154                                // Apply HP/Mana
2155                                lvl->HP = lastlvl.HP + TotalHealthGain;
2156                                lvl->Mana = lastlvl.Mana + TotalManaGain;
2157
2158                                // Calculate next level XP
2159                                uint32 nextLvlXP = 0;
2160/*                              if( Level > 0 && Level <= 30 )
2161                                {
2162                                        nextLvlXP = ((int)((((double)(8 * Level * ((Level * 5) + 45)))/100)+0.5))*100;
2163                                }
2164                                else if( Level == 31 )
2165                                {
2166                                        nextLvlXP = ((int)((((double)(((8 * Level) + 3) * ((Level * 5) + 45)))/100)+0.5))*100;
2167                                }
2168                                else if( Level == 32 )
2169                                {
2170                                        nextLvlXP = ((int)((((double)(((8 * Level) + 6) * ((Level * 5) + 45)))/100)+0.5))*100;
2171                                }
2172                                else
2173                                {
2174                                        nextLvlXP = ((int)((((double)(((8 * Level) + ((Level - 30) * 5)) * ((Level * 5) + 45)))/100)+0.5))*100;
2175                                }*/
2176
2177                                //this is a fixed table taken from 2.3.0 wow. This can;t get more blizzlike with the "if" cases ;)
2178                                if( ( Level - 1 ) < MAX_PREDEFINED_NEXTLEVELXP )
2179                                {
2180                                        nextLvlXP = NextLevelXp[( Level - 1 )];
2181                                }
2182                                else
2183                                {
2184                                        // 2.2
2185                                        //double MXP = 45 + ( 5 * level );
2186                                        // 2.3
2187                                        double MXP = 235 + ( 5 * Level );
2188                                        double DIFF = Level < 29 ? 0.0 : Level < 30 ? 1.0 : Level < 31 ? 3.0 : Level < 32 ? 6.0 : 5.0 * ( double( Level ) - 30.0 );
2189                                        double XP = ( ( 8.0 * double( Level ) ) + DIFF ) * MXP;
2190                                        nextLvlXP = (int)( ( XP / 100.0 ) + 0.5 ) * 100;
2191                                }
2192
2193                                lvl->XPToNextLevel = nextLvlXP;
2194                                lastlvl = *lvl;
2195                                lastlvl.HP = lastlvl.HP;
2196
2197                                // Apply to map.
2198                                lMap->insert( LevelMap::value_type( Level, lvl ) );
2199                        }
2200
2201                        // Now that our level map is full, let's create the class/race pair
2202                        pair<uint32, uint32> p;
2203                        p.first = Race;
2204                        p.second = Class;
2205
2206                        // Insert back into the main map.
2207                        mLevelInfo.insert( LevelInfoMap::value_type( p, lMap ) );
2208                }
2209        }
2210        Log.Notice("ObjectMgr", "%u level up information generated.", mLevelInfo.size());
2211}
2212
2213LevelInfo* ObjectMgr::GetLevelInfo(uint32 Race, uint32 Class, uint32 Level)
2214{
2215        // Iterate levelinfo map until we find the right class+race.
2216        LevelInfoMap::iterator itr = mLevelInfo.begin();
2217        for(; itr != mLevelInfo.end(); ++itr )
2218        {
2219                if( itr->first.first == Race && itr->first.second == Class)
2220                {
2221                        // We got a match.
2222                        // Let's check that our level is valid first.
2223                        if( Level > sWorld.m_genLevelCap ) // too far.
2224                                Level = sWorld.m_genLevelCap;
2225
2226                        // Pull the level information from the second map.
2227                        LevelMap::iterator it2 = itr->second->find( Level );
2228                        ASSERT( it2 != itr->second->end() );
2229
2230                        return it2->second;
2231                }
2232        }
2233
2234        return NULL;
2235}
2236
2237void ObjectMgr::LoadDefaultPetSpells()
2238{
2239        QueryResult * result = WorldDatabase.Query("SELECT * FROM petdefaultspells");
2240        if(result)
2241        {
2242                do
2243                {
2244                        Field * f = result->Fetch();
2245                        uint32 Entry = f[0].GetUInt32();
2246                        uint32 spell = f[1].GetUInt32();
2247                        SpellEntry * sp = dbcSpell.LookupEntry(spell);
2248
2249                        if(spell && Entry && sp)
2250                        {
2251                                PetDefaultSpellMap::iterator itr = mDefaultPetSpells.find(Entry);
2252                                if(itr != mDefaultPetSpells.end())
2253                                        itr->second.insert(sp);
2254                                else
2255                                {
2256                                        set<SpellEntry*> s;
2257                                        s.insert(sp);
2258                                        mDefaultPetSpells[Entry] = s;
2259                                }
2260                        }
2261                } while(result->NextRow());
2262
2263                delete result;
2264        }
2265}
2266
2267set<SpellEntry*>* ObjectMgr::GetDefaultPetSpells(uint32 Entry)
2268{
2269        PetDefaultSpellMap::iterator itr = mDefaultPetSpells.find(Entry);
2270        if(itr == mDefaultPetSpells.end())
2271                return 0;
2272
2273        return &(itr->second);
2274}
2275
2276void ObjectMgr::LoadPetSpellCooldowns()
2277{
2278        DBCFile dbc;
2279
2280        if( !dbc.open( "DBC/CreatureSpellData.dbc" ) )
2281        {
2282                Log.Error( "ObjectMgr", "Cannot find file ./DBC/CreatureSpellData.dbc" );
2283                return;
2284        }
2285
2286        uint32 SpellId;
2287        uint32 Cooldown;
2288        for(uint32 i = 0; i < dbc.getRecordCount(); ++i)
2289        {
2290                for(uint32 j = 0; j < 3; ++j)
2291                {
2292                        SpellId = dbc.getRecord(i).getUInt(1 + j);
2293                        Cooldown = dbc.getRecord(i).getUInt(5 + j);
2294                        Cooldown *= 10;
2295                        if(SpellId)
2296                        {
2297                                PetSpellCooldownMap::iterator itr = mPetSpellCooldowns.find(SpellId);
2298                                if(itr == mPetSpellCooldowns.end())
2299                                {
2300                                        if( Cooldown )
2301                                                mPetSpellCooldowns.insert( make_pair(SpellId, Cooldown) );
2302                                }
2303                                else
2304                                {
2305                                        uint32 SP2 = mPetSpellCooldowns[SpellId];
2306                                        ASSERT(Cooldown == SP2);
2307                                }
2308                        }
2309                }
2310        }
2311}
2312
2313uint32 ObjectMgr::GetPetSpellCooldown(uint32 SpellId)
2314{
2315        PetSpellCooldownMap::iterator itr = mPetSpellCooldowns.find( SpellId );
2316        if( itr != mPetSpellCooldowns.end() )
2317                return itr->second;
2318
2319        SpellEntry* sp = dbcSpell.LookupEntry( SpellId );
2320        return sp->CategoryRecoveryTime + sp->StartRecoveryTime;
2321}
2322
2323void ObjectMgr::LoadSpellOverride()
2324{
2325//      int i = 0;
2326        std::stringstream query;
2327        QueryResult *result = WorldDatabase.Query( "SELECT DISTINCT overrideId FROM spelloverride" );
2328
2329        if(!result)
2330        {
2331                return;
2332        }
2333
2334//      int num = 0;
2335//      uint32 total =(uint32) result->GetRowCount();
2336        SpellEntry * sp;
2337        uint32 spellid;
2338
2339        do
2340        {
2341                Field *fields = result->Fetch();
2342                query.rdbuf()->str("");
2343                query << "SELECT spellId FROM spelloverride WHERE overrideId = ";
2344                query << fields[0].GetUInt32();
2345                QueryResult *resultIn = WorldDatabase.Query(query.str().c_str());
2346                std::list<SpellEntry*>* list = new std::list<SpellEntry*>;
2347                if(resultIn)
2348                {
2349                        do
2350                        {
2351                                Field *fieldsIn = resultIn->Fetch();
2352                                spellid = fieldsIn[0].GetUInt32();
2353                                sp = dbcSpell.LookupEntry(spellid);
2354                                if(!spellid || !sp)
2355                                        continue;
2356                                list->push_back(sp);
2357                        }while(resultIn->NextRow());
2358                        delete resultIn;
2359                }
2360                if(list->size() == 0)
2361                        delete list;
2362                else
2363                        mOverrideIdMap.insert( OverrideIdMap::value_type( fields[0].GetUInt32(), list ));
2364        } while( result->NextRow() );
2365        delete result;
2366        Log.Notice("ObjectMgr", "%u spell overrides loaded.", mOverrideIdMap.size());
2367}
2368
2369void ObjectMgr::SetVendorList(uint32 Entry, std::vector<CreatureItem>* list_)
2370{
2371        mVendors[Entry] = list_;
2372}
2373
2374void ObjectMgr::LoadCreatureTimedEmotes()
2375{
2376        QueryResult *result = WorldDatabase.Query("SELECT * FROM creature_timed_emotes order by `rowid` asc");
2377        if(!result)return;
2378
2379        do
2380        {
2381                Field *fields = result->Fetch();
2382                spawn_timed_emotes* te = new spawn_timed_emotes;
2383                te->type = fields[2].GetUInt8();
2384                te->value = fields[3].GetUInt32();
2385                char *str = ( char* ) fields[4].GetString();
2386                if ( str )
2387                {
2388                        uint32 len = ( int ) strlen ( str ) ;
2389                        te->msg = new char[ len+1 ];
2390                        memcpy ( te->msg, str, len+1 );
2391                }
2392                else te->msg = NULL;
2393                te->msg_type = static_cast<uint8>( fields[5].GetUInt32() );
2394                te->msg_lang = static_cast<uint8>( fields[6].GetUInt32() );
2395                te->expire_after = fields[7].GetUInt32();
2396
2397                HM_NAMESPACE::hash_map<uint32,TimedEmoteList*>::const_iterator i;
2398                uint32 spawnid=fields[0].GetUInt32();
2399                i=m_timedemotes.find(spawnid);
2400                if(i==m_timedemotes.end())
2401                {
2402                        TimedEmoteList* m=new TimedEmoteList;
2403                        m->push_back( te );
2404                        m_timedemotes[spawnid]=m;
2405                }else
2406                {
2407                        i->second->push_back( te );
2408                }
2409        }while( result->NextRow() );
2410
2411        Log.Notice("ObjectMgr", "%u timed emotes cached.", result->GetRowCount());
2412        delete result;
2413}
2414
2415TimedEmoteList*ObjectMgr::GetTimedEmoteList(uint32 spawnid)
2416{
2417        HM_NAMESPACE::hash_map<uint32,TimedEmoteList*>::const_iterator i;
2418        i=m_timedemotes.find(spawnid);
2419        if(i!=m_timedemotes.end())
2420        {
2421                TimedEmoteList * m=i->second;
2422                return m;
2423        }
2424        else return NULL;
2425}
2426
2427void ObjectMgr::LoadCreatureWaypoints()
2428{
2429        QueryResult *result = WorldDatabase.Query("SELECT * FROM creature_waypoints");
2430        if(!result)return;
2431
2432        do
2433        {
2434                Field *fields = result->Fetch();
2435                WayPoint* wp = new WayPoint;
2436                wp->id = fields[1].GetUInt32();
2437                wp->x = fields[2].GetFloat();
2438                wp->y = fields[3].GetFloat();
2439                wp->z = fields[4].GetFloat();
2440                wp->waittime = fields[5].GetUInt32();
2441                wp->flags = fields[6].GetUInt32();
2442                wp->forwardemoteoneshot = fields[7].GetBool();
2443                wp->forwardemoteid = fields[8].GetUInt32();
2444                wp->backwardemoteoneshot = fields[9].GetBool();
2445                wp->backwardemoteid = fields[10].GetUInt32();
2446                wp->forwardskinid = fields[11].GetUInt32();
2447                wp->backwardskinid = fields[12].GetUInt32();
2448
2449                HM_NAMESPACE::hash_map<uint32,WayPointMap*>::const_iterator i;
2450                uint32 spawnid=fields[0].GetUInt32();
2451                i=m_waypoints.find(spawnid);
2452                if(i==m_waypoints.end())
2453                {
2454                        WayPointMap* m=new WayPointMap;
2455                        if(m->size() <= wp->id)
2456                                m->resize(wp->id+1);
2457                        (*m)[wp->id]=wp;
2458                        m_waypoints[spawnid]=m;
2459                }else
2460                {
2461                        if(i->second->size() <= wp->id)
2462                                i->second->resize(wp->id+1);
2463
2464                        (*(i->second))[wp->id]=wp;
2465                }
2466        }while( result->NextRow() );
2467
2468        Log.Notice("ObjectMgr", "%u waypoints cached.", result->GetRowCount());
2469        delete result;
2470}
2471
2472WayPointMap*ObjectMgr::GetWayPointMap(uint32 spawnid)
2473{
2474        HM_NAMESPACE::hash_map<uint32,WayPointMap*>::const_iterator i;
2475        i=m_waypoints.find(spawnid);
2476        if(i!=m_waypoints.end())
2477        {
2478                WayPointMap * m=i->second;
2479                // we don't wanna erase from the map, because some are used more
2480                // than once (for instances)
2481
2482                //m_waypoints.erase(i);
2483                return m;
2484        }
2485        else return NULL;
2486}
2487
2488Pet * ObjectMgr::CreatePet( uint32 entry )
2489{
2490        uint32 guid;
2491        m_petlock.Acquire();
2492        guid =++m_hiPetGuid;
2493        m_petlock.Release();
2494        return new Pet( ( ( uint64 )HIGHGUID_TYPE_PET << 32 ) | ( ( uint64 )entry << 24 ) | guid );
2495}
2496
2497Player * ObjectMgr::CreatePlayer()
2498{
2499        uint32 guid;
2500        m_playerguidlock.Acquire();
2501        guid =++m_hiPlayerGuid;
2502        m_playerguidlock.Release();
2503        return new Player(guid);
2504}
2505
2506void ObjectMgr::AddPlayer(Player * p)//add it to global storage
2507{
2508        _playerslock.AcquireWriteLock();
2509        _players[p->GetLowGUID()] = p;
2510        _playerslock.ReleaseWriteLock();
2511}
2512
2513void ObjectMgr::RemovePlayer(Player * p)
2514{
2515        _playerslock.AcquireWriteLock();
2516        _players.erase(p->GetLowGUID());
2517        _playerslock.ReleaseWriteLock();
2518
2519}
2520
2521Corpse * ObjectMgr::CreateCorpse()
2522{
2523        uint32 guid;
2524        m_corpseguidlock.Acquire();
2525        guid =++m_hiCorpseGuid;
2526        m_corpseguidlock.Release();
2527        return new Corpse(HIGHGUID_TYPE_CORPSE,guid);
2528}
2529
2530void ObjectMgr::AddCorpse(Corpse * p)//add it to global storage
2531{
2532        _corpseslock.Acquire();
2533        m_corpses[p->GetLowGUID()]=p;
2534        _corpseslock.Release();
2535}
2536
2537void ObjectMgr::RemoveCorpse(Corpse * p)
2538{
2539        _corpseslock.Acquire();
2540        m_corpses.erase(p->GetLowGUID());
2541        _corpseslock.Release();
2542}
2543
2544Corpse * ObjectMgr::GetCorpse(uint32 corpseguid)
2545{
2546        Corpse * rv;
2547        _corpseslock.Acquire();
2548        CorpseMap::const_iterator itr = m_corpses.find(corpseguid);
2549        rv = (itr != m_corpses.end()) ? itr->second : 0;
2550        _corpseslock.Release();
2551        return rv;
2552}
2553
2554Transporter * ObjectMgr::GetTransporter(uint32 guid)
2555{
2556        Transporter * rv;
2557        _TransportLock.Acquire();
2558        HM_NAMESPACE::hash_map<uint32, Transporter*>::const_iterator itr = mTransports.find(guid);
2559        rv = (itr != mTransports.end()) ? itr->second : 0;
2560        _TransportLock.Release();
2561        return rv;
2562}
2563
2564void ObjectMgr::AddTransport(Transporter *pTransporter)
2565{
2566        _TransportLock.Acquire();
2567        mTransports[pTransporter->GetUIdFromGUID()]=pTransporter;
2568        _TransportLock.Release();
2569}
2570
2571Transporter * ObjectMgr::GetTransporterByEntry(uint32 entry)
2572{
2573        Transporter * rv = 0;
2574        _TransportLock.Acquire();
2575        HM_NAMESPACE::hash_map<uint32, Transporter*>::iterator itr = mTransports.begin();
2576        for(; itr != mTransports.end(); ++itr)
2577        {
2578                if(itr->second->GetEntry() == entry)
2579                {
2580                        rv = itr->second;
2581                        break;
2582                }
2583        }
2584        _TransportLock.Release();
2585        return rv;
2586}
2587
2588void ObjectMgr::LoadGuildCharters()
2589{
2590        m_hiCharterId = 0;
2591        QueryResult * result = CharacterDatabase.Query("SELECT * FROM charters");
2592        if(!result) return;
2593        do
2594        {
2595                Charter * c = new Charter(result->Fetch());
2596                m_charters[c->CharterType].insert(make_pair(c->GetID(), c));
2597                if(c->GetID() > m_hiCharterId)
2598                        m_hiCharterId = c->GetID();
2599        } while(result->NextRow());
2600        delete result;
2601        Log.Notice("ObjectMgr", "%u charters loaded.", m_charters[0].size());
2602}
2603
2604Charter * ObjectMgr::GetCharter(uint32 CharterId, CharterTypes Type)
2605{
2606        Charter * rv;
2607        HM_NAMESPACE::hash_map<uint32,Charter*>::iterator itr;
2608        m_charterLock.AcquireReadLock();
2609        itr = m_charters[Type].find(CharterId);
2610        rv = (itr == m_charters[Type].end()) ? 0 : itr->second;
2611        m_charterLock.ReleaseReadLock();
2612        return rv;
2613}
2614
2615Charter * ObjectMgr::CreateCharter(uint32 LeaderGuid, CharterTypes Type)
2616{
2617        m_charterLock.AcquireWriteLock();
2618        Charter * c = new Charter(++m_hiCharterId, LeaderGuid, Type);
2619        m_charters[c->CharterType].insert(make_pair(c->GetID(), c));
2620        m_charterLock.ReleaseWriteLock();
2621        return c;
2622}
2623
2624Charter::Charter(Field * fields)
2625{
2626        uint32 f = 0;
2627        CharterId = fields[f++].GetUInt32();
2628        CharterType = fields[f++].GetUInt32();
2629        LeaderGuid = fields[f++].GetUInt32();
2630        GuildName = fields[f++].GetString();
2631        ItemGuid = fields[f++].GetUInt64();
2632        SignatureCount = 0;
2633        Slots = GetNumberOfSlotsByType();
2634        Signatures = new uint32[Slots];
2635
2636        for(uint32 i = 0; i < Slots; ++i)
2637        {
2638                Signatures[i] = fields[f++].GetUInt32();
2639                if(Signatures[i])
2640                        ++SignatureCount;
2641        }
2642}
2643
2644void Charter::AddSignature(uint32 PlayerGuid)
2645{
2646        if(SignatureCount >= Slots)
2647                return;
2648
2649        SignatureCount++;
2650        uint32 i;
2651        for(i = 0; i < Slots; ++i)
2652        {
2653                if(Signatures[i] == 0)
2654                {
2655                        Signatures[i] = PlayerGuid;
2656                        break;
2657                }
2658        }
2659
2660        assert(i != Slots);
2661}
2662
2663void Charter::RemoveSignature(uint32 PlayerGuid)
2664{
2665        for(uint32 i = 0; i < Slots; ++i)
2666        {
2667                if(Signatures[i] == PlayerGuid)
2668                {
2669                        Signatures[i] = 0;
2670                        SignatureCount--;
2671                        SaveToDB();
2672                        break;
2673                }
2674        }
2675}
2676
2677
2678void Charter::Destroy()
2679{
2680        if( Slots == 0 )                        // ugly hack because of f*cked memory
2681                return;
2682
2683        //meh remove from objmgr
2684        objmgr.RemoveCharter(this);
2685        // Kill the players with this (in db/offline)
2686        CharacterDatabase.Execute( "DELETE FROM charters WHERE charterId = %u", CharterId );
2687        Player * p;
2688#ifdef WIN32
2689        __try {
2690#endif
2691        for( uint32 i = 0; i < Slots; ++i )
2692        {
2693                if(!Signatures[i])
2694                        continue;
2695                p =  objmgr.GetPlayer( Signatures[i] );
2696                if( p != NULL)
2697                        p->m_charters[CharterType] = 0;
2698        }
2699#ifdef WIN32
2700        } __except(EXCEPTION_EXECUTE_HANDLER)
2701        {
2702                return;
2703        }
2704#endif
2705
2706        // click, click, boom!
2707        delete this;
2708}
2709
2710void Charter::SaveToDB()
2711{
2712        /*CharacterDatabase.Execute(
2713                "REPLACE INTO charters VALUES(%u,%u,'%s',"I64FMTD",%u,%u,%u,%u,%u,%u,%u,%u,%u)",
2714                CharterId,LeaderGuid,GuildName.c_str(),ItemGuid,Signatures[0],Signatures[1],
2715                Signatures[2],Signatures[3],Signatures[4],Signatures[5],
2716                Signatures[6],Signatures[7],Signatures[8]);*/
2717        std::stringstream ss;
2718        uint32 i;
2719        ss << "REPLACE INTO charters VALUES(" << CharterId << "," << CharterType << "," << LeaderGuid << ",'" << GuildName << "'," << ItemGuid;
2720
2721        for(i = 0; i < Slots; ++i)
2722                ss << "," << Signatures[i];
2723
2724        for(; i < 9; ++i)
2725                ss << ",0";
2726
2727        ss << ")";
2728        CharacterDatabase.Execute(ss.str().c_str());
2729}
2730
2731Charter * ObjectMgr::GetCharterByItemGuid(uint64 guid)
2732{
2733        m_charterLock.AcquireReadLock();
2734        for(int i = 0; i < NUM_CHARTER_TYPES; ++i)
2735        {
2736                HM_NAMESPACE::hash_map<uint32, Charter*>::iterator itr = m_charters[i].begin();
2737                for(; itr != m_charters[i].end(); ++itr)
2738                {
2739                        if(itr->second->ItemGuid == guid)
2740                        {
2741                                m_charterLock.ReleaseReadLock();
2742                                return itr->second;
2743                        }
2744                }
2745        }
2746        m_charterLock.ReleaseReadLock();
2747        return NULL;
2748}
2749
2750Charter * ObjectMgr::GetCharterByGuid(uint64 playerguid, CharterTypes type)
2751{
2752        m_charterLock.AcquireReadLock();
2753        for(int i = 0; i < NUM_CHARTER_TYPES; ++i)
2754        {
2755                HM_NAMESPACE::hash_map<uint32, Charter*>::iterator itr = m_charters[i].begin();
2756                for(; itr != m_charters[i].end(); ++itr)
2757                {
2758                        if(playerguid == itr->second->LeaderGuid)
2759                        {
2760                                m_charterLock.ReleaseReadLock();
2761                                return itr->second;
2762                        }
2763
2764                        for(uint32 j = 0; j < itr->second->SignatureCount; ++j)
2765                        {
2766                                if(itr->second->Signatures[j] == playerguid)
2767                                {
2768                                        m_charterLock.ReleaseReadLock();
2769                                        return itr->second;
2770                                }
2771                        }
2772                }
2773        }
2774        m_charterLock.ReleaseReadLock();
2775        return NULL;
2776}
2777
2778Charter * ObjectMgr::GetCharterByName(string &charter_name, CharterTypes Type)
2779{
2780        Charter * rv = 0;
2781        m_charterLock.AcquireReadLock();
2782        HM_NAMESPACE::hash_map<uint32, Charter*>::iterator itr = m_charters[Type].begin();
2783        for(; itr != m_charters[Type].end(); ++itr)
2784        {
2785                if(itr->second->GuildName == charter_name)
2786                {
2787                        rv = itr->second;
2788                        break;
2789                }
2790        }
2791
2792        m_charterLock.ReleaseReadLock();
2793        return rv;
2794}
2795
2796void ObjectMgr::RemoveCharter(Charter * c)
2797{
2798        if( c == NULL )
2799                return;
2800        if( c->CharterType > NUM_CHARTER_TYPES )
2801        {
2802                Log.Notice("ObjectMgr", "Charter %u cannot be destroyed as type %u is not a sane type value.", c->CharterId, c->CharterType );
2803                return;
2804        }
2805        m_charterLock.AcquireWriteLock();
2806        m_charters[c->CharterType].erase(c->CharterId);
2807        m_charterLock.ReleaseWriteLock();
2808}
2809
2810void ObjectMgr::LoadReputationModifierTable(const char * tablename, ReputationModMap * dmap)
2811{
2812        QueryResult * result = WorldDatabase.Query("SELECT * FROM %s", tablename);
2813        ReputationModMap::iterator itr;
2814        ReputationModifier * modifier;
2815        ReputationMod mod;
2816
2817        if(result)
2818        {
2819                do
2820                {
2821                        mod.faction[0] = result->Fetch()[1].GetUInt32();
2822                        mod.faction[1] = result->Fetch()[2].GetUInt32();
2823                        mod.value = result->Fetch()[3].GetInt32();
2824                        mod.replimit = result->Fetch()[4].GetUInt32();
2825
2826                        itr = dmap->find(result->Fetch()[0].GetUInt32());
2827                        if(itr == dmap->end())
2828                        {
2829                                modifier = new ReputationModifier;
2830                                modifier->entry = result->Fetch()[0].GetUInt32();
2831                                modifier->mods.push_back(mod);
2832                                dmap->insert( ReputationModMap::value_type( result->Fetch()[0].GetUInt32(), modifier ) );
2833                        }
2834                        else
2835                        {
2836                                itr->second->mods.push_back(mod);
2837                        }
2838                } while(result->NextRow());
2839                delete result;
2840        }
2841        Log.Notice("ObjectMgr", "%u reputation modifiers on %s.", dmap->size(), tablename);
2842}
2843
2844void ObjectMgr::LoadReputationModifiers()
2845{
2846        LoadReputationModifierTable("reputation_creature_onkill", &m_reputation_creature);
2847        LoadReputationModifierTable("reputation_faction_onkill", &m_reputation_faction);
2848        LoadInstanceReputationModifiers();
2849}
2850
2851ReputationModifier * ObjectMgr::GetReputationModifier(uint32 entry_id, uint32 faction_id)
2852{
2853        // first, try fetching from the creature table (by faction is a fallback)
2854        ReputationModMap::iterator itr = m_reputation_creature.find(entry_id);
2855        if(itr != m_reputation_creature.end())
2856                return itr->second;
2857
2858        // fetch from the faction table
2859        itr = m_reputation_faction.find(faction_id);
2860        if(itr != m_reputation_faction.end())
2861                return itr->second;
2862
2863        // no data. fallback to default -5 value.
2864        return 0;
2865}
2866
2867void ObjectMgr::LoadMonsterSay()
2868{
2869        QueryResult * result = WorldDatabase.Query("SELECT * FROM npc_monstersay");
2870        if(!result) return;
2871
2872        uint32 Entry, Event;
2873        Field * fields = result->Fetch();
2874        do
2875        {
2876                Entry = fields[0].GetUInt32();
2877                Event = fields[1].GetUInt32();
2878
2879                if(Event >= NUM_MONSTER_SAY_EVENTS)
2880                        continue;
2881
2882                if( mMonsterSays[Event].find( Entry ) != mMonsterSays[Event].end() )
2883                {
2884                        sLog.outError("Duplicate monstersay event %u for entry %u, skipping", Event, Entry      );
2885                        continue;
2886                }
2887
2888                NpcMonsterSay * ms = new NpcMonsterSay;
2889                ms->Chance = fields[2].GetFloat();
2890                ms->Language = fields[3].GetUInt32();
2891                ms->Type = fields[4].GetUInt32();
2892                ms->MonsterName = fields[5].GetString() ? strdup(fields[5].GetString()) : strdup("None");
2893
2894                char * texts[5];
2895                char * text;
2896                uint32 textcount = 0;
2897
2898                for(uint32 i = 0; i < 5; ++i)
2899                {
2900                        text = (char*)fields[6+i].GetString();
2901                        if(!text) continue;
2902                        if(strlen(fields[6+i].GetString()) < 5)
2903                                continue;
2904
2905                        texts[textcount] = strdup(fields[6+i].GetString());
2906
2907                        // check for ;
2908                        if(texts[textcount][strlen(texts[textcount])-1] == ';')
2909                                texts[textcount][strlen(texts[textcount])-1] = 0;
2910
2911                        ++textcount;
2912                }
2913
2914                if(!textcount)
2915                {
2916                        free(((char*)ms->MonsterName));
2917                        delete ms;
2918                        continue;
2919                }
2920
2921                ms->Texts = new const char*[textcount];
2922                memcpy(ms->Texts, texts, sizeof(char*) * textcount);
2923                ms->TextCount = textcount;
2924
2925                mMonsterSays[Event].insert( make_pair( Entry, ms ) );
2926
2927        } while(result->NextRow());
2928        Log.Notice("ObjectMgr", "%u monster say events loaded.", result->GetRowCount());
2929        delete result;
2930}
2931
2932void ObjectMgr::HandleMonsterSayEvent(Creature * pCreature, MONSTER_SAY_EVENTS Event)
2933{
2934        MonsterSayMap::iterator itr = mMonsterSays[Event].find(pCreature->GetEntry());
2935        if(itr == mMonsterSays[Event].end())
2936                return;
2937
2938        NpcMonsterSay * ms = itr->second;
2939        if(Rand(ms->Chance))
2940        {
2941                // chance successful.
2942                int choice = (ms->TextCount == 1) ? 0 : RandomUInt(ms->TextCount - 1);
2943                const char * text = ms->Texts[choice];
2944                // check for special variables $N=name $C=class $R=race $G=gender
2945                // $G is followed by male_string:female_string;
2946                string newText = text;
2947                static const char* races[12] = {"None","Human","Orc","Dwarf","Night Elf","Undead","Tauren","Gnome","Troll","None","Blood Elf","Draenei"};
2948                static const char* classes[12] = {"None","Warrior", "Paladin", "Hunter", "Rogue", "Priest", "Death Knight", "Shaman", "Mage", "Warlock", "None", "Druid"};
2949                char* test=strstr((char*)text,"$R");
2950                if(test==NULL)
2951                        test = strstr((char*)text,"$r");
2952                if(test != NULL)
2953                {
2954                        uint64 targetGUID = pCreature->GetUInt64Value(UNIT_FIELD_TARGET);
2955                        Unit* CurrentTarget = pCreature->GetMapMgr()->GetUnit(targetGUID);
2956                        if(CurrentTarget)
2957                        {
2958                                uint32 testOfs = test-text;
2959                                newText.replace(testOfs, 2, races[CurrentTarget->getRace()]);
2960                        }
2961                }
2962                test = strstr((char*)text,"$N");
2963                if(test==NULL)
2964                        test = strstr((char*)text,"$n");
2965                if(test != NULL)
2966                {
2967                        uint64 targetGUID = pCreature->GetUInt64Value(UNIT_FIELD_TARGET);
2968                        Unit* CurrentTarget = pCreature->GetMapMgr()->GetUnit(targetGUID);
2969                        if(CurrentTarget && CurrentTarget->IsPlayer())
2970                        {
2971                                uint32 testOfs = test-text;
2972                                newText.replace(testOfs, 2, ((Player*)CurrentTarget)->GetName());
2973                        }
2974                }
2975                test = strstr((char*)text,"$C");
2976                if(test==NULL)
2977                        test = strstr((char*)text,"$c");
2978                if(test != NULL)
2979                {
2980                        uint64 targetGUID = pCreature->GetUInt64Value(UNIT_FIELD_TARGET);
2981                        Unit* CurrentTarget = pCreature->GetMapMgr()->GetUnit(targetGUID);
2982                        if(CurrentTarget)
2983                        {
2984                                uint32 testOfs = test-text;
2985                                newText.replace(testOfs, 2, classes[CurrentTarget->getClass()]);
2986                        }
2987                }
2988                test = strstr((char*)text,"$G");
2989                if(test==NULL)
2990                        test = strstr((char*)text,"$g");
2991                if(test != NULL)
2992                {
2993                        uint64 targetGUID = pCreature->GetUInt64Value(UNIT_FIELD_TARGET);
2994                        Unit* CurrentTarget = pCreature->GetMapMgr()->GetUnit(targetGUID);
2995                        if(CurrentTarget)
2996                        {
2997                                char* g0 = test+2;
2998                                char* g1 = strchr(g0,':');
2999                                if(g1)
3000                                {
3001                                        char* gEnd = strchr(g1,';');
3002                                        if(gEnd)
3003                                        {
3004                                                *g1 = 0x00;
3005                                                ++g1;
3006                                                *gEnd = 0x00;
3007                                                ++gEnd;
3008                                                *test = 0x00;
3009                                                newText = text;
3010                                                newText += (CurrentTarget->getGender()==0) ? g0 : g1;
3011                                                newText += gEnd;
3012                                        }
3013                                }
3014                        }
3015                }
3016
3017                pCreature->SendChatMessage(static_cast<uint8>( ms->Type ), ms->Language, newText.c_str());
3018        }
3019}
3020
3021bool ObjectMgr::HasMonsterSay(uint32 Entry, MONSTER_SAY_EVENTS Event)
3022{
3023        MonsterSayMap::iterator itr = mMonsterSays[Event].find(Entry);
3024        if(itr == mMonsterSays[Event].end())
3025                return false;
3026
3027        return true;
3028}
3029
3030void ObjectMgr::LoadInstanceReputationModifiers()
3031{
3032        QueryResult * result = WorldDatabase.Query("SELECT * FROM reputation_instance_onkill");
3033        if(!result) return;
3034
3035        do
3036        {
3037                Field * fields = result->Fetch();
3038                InstanceReputationMod mod;
3039                mod.mapid = fields[0].GetUInt32();
3040                mod.mob_rep_reward = fields[1].GetInt32();
3041                mod.mob_rep_limit = fields[2].GetUInt32();
3042                mod.boss_rep_reward = fields[3].GetInt32();
3043                mod.boss_rep_limit = fields[4].GetUInt32();
3044                mod.faction[0] = fields[5].GetUInt32();
3045                mod.faction[1] = fields[6].GetUInt32();
3046
3047                HM_NAMESPACE::hash_map<uint32, InstanceReputationModifier*>::iterator itr = m_reputation_instance.find(mod.mapid);
3048                if(itr == m_reputation_instance.end())
3049                {
3050                        InstanceReputationModifier * m = new InstanceReputationModifier;
3051                        m->mapid = mod.mapid;
3052                        m->mods.push_back(mod);
3053                        m_reputation_instance.insert( make_pair( m->mapid, m ) );
3054                }
3055                else
3056                        itr->second->mods.push_back(mod);
3057
3058        } while(result->NextRow());
3059        delete result;
3060        Log.Notice("ObjectMgr", "%u instance reputation modifiers loaded.", m_reputation_instance.size());
3061}
3062
3063bool ObjectMgr::HandleInstanceReputationModifiers(Player * pPlayer, Unit * pVictim)
3064{
3065        uint32 team = pPlayer->GetTeam();
3066        bool is_boss;
3067        if(pVictim->GetTypeId() != TYPEID_UNIT)
3068                return false;
3069
3070        HM_NAMESPACE::hash_map<uint32, InstanceReputationModifier*>::iterator itr = m_reputation_instance.find(pVictim->GetMapId());
3071        if(itr == m_reputation_instance.end())
3072                return false;
3073
3074        is_boss = 0;//static_cast< Creature* >( pVictim )->GetCreatureInfo() ? ((Creature*)pVictim)->GetCreatureInfo()->Rank : 0;
3075        if( !is_boss && static_cast< Creature* >( pVictim )->GetProto() && static_cast< Creature* >( pVictim )->GetProto()->boss )
3076                is_boss = 1;
3077
3078        // Apply the bonuses as normal.
3079        int32 replimit;
3080        int32 value;
3081
3082        for(vector<InstanceReputationMod>::iterator i = itr->second->mods.begin(); i !=  itr->second->mods.end(); ++i)
3083        {
3084                if(!(*i).faction[team])
3085                        continue;
3086
3087                if(is_boss)
3088                {
3089                        value = i->boss_rep_reward;
3090                        replimit = i->boss_rep_limit;
3091                }
3092                else
3093                {
3094                        value = i->mob_rep_reward;
3095                        replimit = i->mob_rep_limit;
3096                }
3097
3098                if(!value || (replimit && pPlayer->GetStanding(i->faction[team]) >= replimit))
3099                        continue;
3100
3101                //value *= sWorld.getRate(RATE_KILLREPUTATION);
3102                value = float2int32(float(value) * sWorld.getRate(RATE_KILLREPUTATION));
3103                pPlayer->ModStanding(i->faction[team], value);
3104        }
3105
3106        return true;
3107}
3108
3109void ObjectMgr::LoadDisabledSpells()
3110{
3111        QueryResult * result = WorldDatabase.Query("SELECT * FROM spell_disable");
3112        if(result)
3113        {
3114                do
3115                {
3116                        m_disabled_spells.insert( result->Fetch()[0].GetUInt32() );
3117                } while(result->NextRow());
3118                delete result;
3119        }
3120
3121        Log.Notice("ObjectMgr", "%u disabled spells.", m_disabled_spells.size());
3122}
3123
3124void ObjectMgr::ReloadDisabledSpells()
3125{
3126        m_disabled_spells.clear();
3127        LoadDisabledSpells();
3128}
3129
3130void ObjectMgr::LoadGroups()
3131{
3132        QueryResult * result = CharacterDatabase.Query("SELECT * FROM groups");
3133        if(result)
3134        {
3135                if(result->GetFieldCount() != 52)
3136                {
3137                        Log.LargeErrorMessage(LARGERRORMESSAGE_WARNING, "groups table format is invalid. Please update your database.");
3138                        return;
3139                }
3140                do
3141                {
3142                        Group * g = new Group(false);
3143                        g->LoadFromDB(result->Fetch());
3144                } while(result->NextRow());
3145                delete result;
3146        }
3147
3148        Log.Notice("ObjectMgr", "%u groups loaded.", this->m_groups.size());
3149}
3150
3151void ObjectMgr::LoadArenaTeams()
3152{
3153        QueryResult * result = CharacterDatabase.Query("SELECT * FROM arenateams");
3154        if(result != NULL)
3155        {
3156                if(result->GetFieldCount() != 22)
3157                {
3158                        Log.LargeErrorMessage(LARGERRORMESSAGE_WARNING, "arenateams table format is invalid. Please update your database.");
3159                        return;
3160                }
3161                do
3162                {
3163                        ArenaTeam * team = new ArenaTeam(result->Fetch());
3164                        AddArenaTeam(team);
3165                        if(team->m_id > m_hiArenaTeamId)
3166                                m_hiArenaTeamId=team->m_id;
3167
3168                } while(result->NextRow());
3169                delete result;
3170        }
3171
3172        /* update the ranking */
3173        UpdateArenaTeamRankings();
3174}
3175
3176ArenaTeam * ObjectMgr::GetArenaTeamByGuid(uint32 guid, uint32 Type)
3177{
3178        m_arenaTeamLock.Acquire();
3179        for(HM_NAMESPACE::hash_map<uint32,ArenaTeam*>::iterator itr = m_arenaTeamMap[Type].begin(); itr != m_arenaTeamMap[Type].end(); ++itr)
3180        {
3181                if(itr->second->HasMember(guid))
3182                {
3183                        m_arenaTeamLock.Release();
3184                        return itr->second;
3185                }
3186        }
3187        m_arenaTeamLock.Release();
3188        return NULL;
3189}
3190
3191ArenaTeam * ObjectMgr::GetArenaTeamById(uint32 id)
3192{
3193        HM_NAMESPACE::hash_map<uint32, ArenaTeam*>::iterator itr;
3194        m_arenaTeamLock.Acquire();
3195        itr = m_arenaTeams.find(id);
3196        m_arenaTeamLock.Release();
3197        return (itr == m_arenaTeams.end()) ? NULL : itr->second;
3198}
3199
3200ArenaTeam * ObjectMgr::GetArenaTeamByName(string & name, uint32 Type)
3201{
3202        m_arenaTeamLock.Acquire();
3203        for(HM_NAMESPACE::hash_map<uint32, ArenaTeam*>::iterator itr = m_arenaTeams.begin(); itr != m_arenaTeams.end(); ++itr)
3204        {
3205                if(!strnicmp(itr->second->m_name.c_str(), name.c_str(), name.size()))
3206                {
3207                        m_arenaTeamLock.Release();
3208                        return itr->second;
3209                }
3210        }
3211        m_arenaTeamLock.Release();
3212        return NULL;
3213}
3214
3215void ObjectMgr::RemoveArenaTeam(ArenaTeam * team)
3216{
3217        m_arenaTeamLock.Acquire();
3218        m_arenaTeams.erase(team->m_id);
3219        m_arenaTeamMap[team->m_type].erase(team->m_id);
3220        m_arenaTeamLock.Release();
3221}
3222
3223void ObjectMgr::AddArenaTeam(ArenaTeam * team)
3224{
3225        m_arenaTeamLock.Acquire();
3226        m_arenaTeams[team->m_id] = team;
3227        m_arenaTeamMap[team->m_type].insert(make_pair(team->m_id,team));
3228        m_arenaTeamLock.Release();
3229}
3230
3231class ArenaSorter
3232{
3233public:
3234        bool operator()(ArenaTeam* const & a,ArenaTeam* const & b)
3235        {
3236                return (a->m_stat_rating > b->m_stat_rating);
3237        }
3238                bool operator()(ArenaTeam*& a, ArenaTeam*& b)
3239                {
3240                                return (a->m_stat_rating > b->m_stat_rating);
3241                }
3242};
3243
3244void ObjectMgr::UpdateArenaTeamRankings()
3245{
3246        m_arenaTeamLock.Acquire();
3247        for(uint32 i = 0; i < NUM_ARENA_TEAM_TYPES; ++i)
3248        {
3249                vector<ArenaTeam*> ranking;
3250
3251                for(HM_NAMESPACE::hash_map<uint32,ArenaTeam*>::iterator itr = m_arenaTeamMap[i].begin(); itr != m_arenaTeamMap[i].end(); ++itr)
3252                        ranking.push_back(itr->second);
3253
3254                std::sort(ranking.begin(), ranking.end(), ArenaSorter());
3255                uint32 rank = 1;
3256                for(vector<ArenaTeam*>::iterator itr = ranking.begin(); itr != ranking.end(); ++itr)
3257                {
3258                        if((*itr)->m_stat_ranking != rank)
3259                        {
3260                                (*itr)->m_stat_ranking = rank;
3261                                (*itr)->SaveToDB();
3262                        }
3263                        ++rank;
3264                }
3265        }
3266        m_arenaTeamLock.Release();
3267}
3268
3269void ObjectMgr::ResetArenaTeamRatings()
3270{
3271        m_arenaTeamLock.Acquire();
3272        for(uint32 i = 0; i < NUM_ARENA_TEAM_TYPES; ++i)
3273        {
3274                for(HM_NAMESPACE::hash_map<uint32,ArenaTeam*>::iterator itr = m_arenaTeamMap[i].begin(); itr != m_arenaTeamMap[i].end(); ++itr)
3275                {
3276                        ArenaTeam *team = itr->second;
3277                        if(team)
3278                        {
3279                                team->m_stat_gamesplayedseason = 0;
3280                                team->m_stat_gamesplayedweek = 0;
3281                                team->m_stat_gameswonseason = 0;
3282                                team->m_stat_gameswonweek = 0;
3283                                team->m_stat_rating = 1500;
3284                                for(uint32 j = 0; j < team->m_memberCount; ++j)
3285                                {
3286                                        team->m_members[j].Played_ThisSeason = 0;
3287                                        team->m_members[j].Played_ThisWeek = 0;
3288                                        team->m_members[j].Won_ThisSeason = 0;
3289                                        team->m_members[j].Won_ThisWeek = 0;
3290                                        team->m_members[j].PersonalRating = 1500;
3291                                }
3292                                team->SaveToDB();
3293                        }
3294                }
3295        }
3296        m_arenaTeamLock.Release();
3297
3298        UpdateArenaTeamRankings();
3299}
3300
3301void ObjectMgr::UpdateArenaTeamWeekly()
3302{       // reset weekly matches count for all teams and all members
3303        m_arenaTeamLock.Acquire();
3304        for(uint32 i = 0; i < NUM_ARENA_TEAM_TYPES; ++i)
3305        {
3306                for(HM_NAMESPACE::hash_map<uint32,ArenaTeam*>::iterator itr = m_arenaTeamMap[i].begin(); itr != m_arenaTeamMap[i].end(); ++itr)
3307                {
3308                        ArenaTeam *team = itr->second;
3309                        if(team)
3310                        {
3311                                team->m_stat_gamesplayedweek = 0;
3312                                team->m_stat_gameswonweek = 0;
3313                                for(uint32 j = 0; j < team->m_memberCount; ++j)
3314                                {
3315                                        team->m_members[j].Played_ThisWeek = 0;
3316                                        team->m_members[j].Won_ThisWeek = 0;
3317                                }
3318                                team->SaveToDB();
3319                        }
3320                }
3321        }
3322        m_arenaTeamLock.Release();
3323}
3324
3325void ObjectMgr::ResetDailies()
3326{
3327        _playerslock.AcquireReadLock();
3328        PlayerStorageMap::iterator itr = _players.begin();
3329        for(; itr != _players.end(); itr++)
3330        {
3331                Player * pPlayer = itr->second;
3332                pPlayer->DailyMutex.Acquire();
3333                pPlayer->m_finishedDailies.clear();
3334                pPlayer->DailyMutex.Release();
3335        }
3336        _playerslock.ReleaseReadLock();
3337}
3338
3339#ifdef VOICE_CHAT
3340void ObjectMgr::GroupVoiceReconnected()
3341{
3342        m_groupLock.AcquireReadLock();
3343        for(GroupMap::iterator itr = m_groups.begin(); itr != m_groups.end(); ++itr)
3344                itr->second->VoiceSessionReconnected();
3345        m_groupLock.ReleaseReadLock();
3346}
3347#endif
Note: See TracBrowser for help on using the browser.