| 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 | |
|---|
| 23 | initialiseSingleton( ObjectMgr ); |
|---|
| 24 | |
|---|
| 25 | const char * NormalTalkMessage = "DMSG"; |
|---|
| 26 | |
|---|
| 27 | ObjectMgr::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 | |
|---|
| 43 | ObjectMgr::~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 | |
|---|
| 231 | Group * 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 | |
|---|
| 249 | Group * 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 | // |
|---|
| 265 | void 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 | |
|---|
| 306 | PlayerInfo *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 | |
|---|
| 320 | void 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 | |
|---|
| 330 | void 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 | |
|---|
| 348 | void 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 | |
|---|
| 364 | skilllinespell* ObjectMgr::GetSpellSkill(uint32 id) |
|---|
| 365 | { |
|---|
| 366 | return mSpellSkills[id]; |
|---|
| 367 | } |
|---|
| 368 | |
|---|
| 369 | SpellEntry* 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 | |
|---|
| 385 | void 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 | |
|---|
| 484 | PlayerInfo* 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 |
|---|
| 500 | void 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 |
|---|
| 514 | void 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() |
|---|
| 646 | void 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 | |
|---|
| 672 | Corpse* 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 | //------------------------------------------------------ |
|---|
| 709 | Corpse *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 | |
|---|
| 728 | void 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 | |
|---|
| 738 | void 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 | |
|---|
| 773 | void 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 | |
|---|
| 829 | void 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 | |
|---|
| 853 | void 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 | |
|---|
| 932 | uint64 ObjectMgr::GenerateTicketID() |
|---|
| 933 | { |
|---|
| 934 | return m_ticketid++; |
|---|
| 935 | } |
|---|
| 936 | |
|---|
| 937 | uint32 ObjectMgr::GenerateMailID() |
|---|
| 938 | { |
|---|
| 939 | return m_mailid++; |
|---|
| 940 | } |
|---|
| 941 | uint32 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 | |
|---|
| 964 | void 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 | |
|---|
| 1099 | Player* 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 | |
|---|
| 1135 | Player* 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 | |
|---|
| 1147 | PlayerCreateInfo* 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 | |
|---|
| 1158 | void ObjectMgr::AddGuild(Guild *pGuild) |
|---|
| 1159 | { |
|---|
| 1160 | ASSERT( pGuild ); |
|---|
| 1161 | mGuild[pGuild->GetGuildId()] = pGuild; |
|---|
| 1162 | } |
|---|
| 1163 | |
|---|
| 1164 | uint32 ObjectMgr::GetTotalGuildCount() |
|---|
| 1165 | { |
|---|
| 1166 | return (uint32)mGuild.size(); |
|---|
| 1167 | } |
|---|
| 1168 | |
|---|
| 1169 | bool 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 | |
|---|
| 1182 | Guild* 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 | |
|---|
| 1190 | Guild* 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 | |
|---|
| 1201 | Guild* 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 | |
|---|
| 1213 | void 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 | |
|---|
| 1223 | void ObjectMgr::UpdateGMTicket(GM_Ticket *ticket) |
|---|
| 1224 | { |
|---|
| 1225 | SaveGMTicket(ticket, NULL); |
|---|
| 1226 | } |
|---|
| 1227 | |
|---|
| 1228 | void 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 | |
|---|
| 1246 | void 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 | |
|---|
| 1263 | void 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 | |
|---|
| 1276 | void 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 | |
|---|
| 1289 | GM_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 | |
|---|
| 1302 | GM_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 | |
|---|
| 1329 | void 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 | |
|---|
| 1389 | void ObjectMgr::ReloadVendors() |
|---|
| 1390 | { |
|---|
| 1391 | mVendors.clear(); |
|---|
| 1392 | LoadVendors(); |
|---|
| 1393 | } |
|---|
| 1394 | |
|---|
| 1395 | std::vector<CreatureItem>* ObjectMgr::GetVendorList(uint32 entry) |
|---|
| 1396 | { |
|---|
| 1397 | return mVendors[entry]; |
|---|
| 1398 | } |
|---|
| 1399 | |
|---|
| 1400 | void 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 | |
|---|
| 1428 | SpellEntry* ObjectMgr::GetTotemSpell(uint32 spellId) |
|---|
| 1429 | { |
|---|
| 1430 | return m_totemSpells[spellId]; |
|---|
| 1431 | } |
|---|
| 1432 | |
|---|
| 1433 | void 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 | |
|---|
| 1461 | void 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 | |
|---|
| 1515 | void 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 | |
|---|
| 1575 | Item * 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 | |
|---|
| 1599 | Item * 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 | |
|---|
| 1631 | Item * 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 | |
|---|
| 1663 | void 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 |
|---|
| 1694 | AchievementCriteriaEntryList const& ObjectMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type) |
|---|
| 1695 | { |
|---|
| 1696 | return m_AchievementCriteriasByType[type]; |
|---|
| 1697 | } |
|---|
| 1698 | |
|---|
| 1699 | void 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 |
|---|
| 1711 | std::list<ItemPrototype*>* ObjectMgr::GetListForItemSet(uint32 setid) |
|---|
| 1712 | { |
|---|
| 1713 | return mItemSets[setid]; |
|---|
| 1714 | } |
|---|
| 1715 | |
|---|
| 1716 | void 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 | |
|---|
| 1724 | void 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 | |
|---|
| 1734 | void 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 | |
|---|
| 1750 | GossipMenu::GossipMenu(uint64 Creature_Guid, uint32 Text_Id) : TextId(Text_Id), CreatureGuid(Creature_Guid) |
|---|
| 1751 | { |
|---|
| 1752 | |
|---|
| 1753 | } |
|---|
| 1754 | |
|---|
| 1755 | void 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 | |
|---|
| 1772 | void 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 | |
|---|
| 1786 | void GossipMenu::AddItem(GossipMenuItem* GossipItem) |
|---|
| 1787 | { |
|---|
| 1788 | Menu.push_back(*GossipItem); |
|---|
| 1789 | } |
|---|
| 1790 | |
|---|
| 1791 | void 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 | |
|---|
| 1810 | void 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 | |
|---|
| 1818 | void 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 | |
|---|
| 1830 | GossipMenuItem 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 | |
|---|
| 1842 | uint32 ObjectMgr::GetGossipTextForNpc(uint32 ID) |
|---|
| 1843 | { |
|---|
| 1844 | return mNpcToGossipText[ID]; |
|---|
| 1845 | } |
|---|
| 1846 | |
|---|
| 1847 | void 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 | |
|---|
| 1989 | Trainer* 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 | |
|---|
| 1998 | void 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 | |
|---|
| 2213 | LevelInfo* 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 | |
|---|
| 2237 | void 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 | |
|---|
| 2267 | set<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 | |
|---|
| 2276 | void 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 | |
|---|
| 2313 | uint32 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 | |
|---|
| 2323 | void 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 | |
|---|
| 2369 | void ObjectMgr::SetVendorList(uint32 Entry, std::vector<CreatureItem>* list_) |
|---|
| 2370 | { |
|---|
| 2371 | mVendors[Entry] = list_; |
|---|
| 2372 | } |
|---|
| 2373 | |
|---|
| 2374 | void 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 | |
|---|
| 2415 | TimedEmoteList*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 | |
|---|
| 2427 | void 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 | |
|---|
| 2472 | WayPointMap*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 | |
|---|
| 2488 | Pet * 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 | |
|---|
| 2497 | Player * 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 | |
|---|
| 2506 | void ObjectMgr::AddPlayer(Player * p)//add it to global storage |
|---|
| 2507 | { |
|---|
| 2508 | _playerslock.AcquireWriteLock(); |
|---|
| 2509 | _players[p->GetLowGUID()] = p; |
|---|
| 2510 | _playerslock.ReleaseWriteLock(); |
|---|
| 2511 | } |
|---|
| 2512 | |
|---|
| 2513 | void ObjectMgr::RemovePlayer(Player * p) |
|---|
| 2514 | { |
|---|
| 2515 | _playerslock.AcquireWriteLock(); |
|---|
| 2516 | _players.erase(p->GetLowGUID()); |
|---|
| 2517 | _playerslock.ReleaseWriteLock(); |
|---|
| 2518 | |
|---|
| 2519 | } |
|---|
| 2520 | |
|---|
| 2521 | Corpse * 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 | |
|---|
| 2530 | void ObjectMgr::AddCorpse(Corpse * p)//add it to global storage |
|---|
| 2531 | { |
|---|
| 2532 | _corpseslock.Acquire(); |
|---|
| 2533 | m_corpses[p->GetLowGUID()]=p; |
|---|
| 2534 | _corpseslock.Release(); |
|---|
| 2535 | } |
|---|
| 2536 | |
|---|
| 2537 | void ObjectMgr::RemoveCorpse(Corpse * p) |
|---|
| 2538 | { |
|---|
| 2539 | _corpseslock.Acquire(); |
|---|
| 2540 | m_corpses.erase(p->GetLowGUID()); |
|---|
| 2541 | _corpseslock.Release(); |
|---|
| 2542 | } |
|---|
| 2543 | |
|---|
| 2544 | Corpse * 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 | |
|---|
| 2554 | Transporter * 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 | |
|---|
| 2564 | void ObjectMgr::AddTransport(Transporter *pTransporter) |
|---|
| 2565 | { |
|---|
| 2566 | _TransportLock.Acquire(); |
|---|
| 2567 | mTransports[pTransporter->GetUIdFromGUID()]=pTransporter; |
|---|
| 2568 | _TransportLock.Release(); |
|---|
| 2569 | } |
|---|
| 2570 | |
|---|
| 2571 | Transporter * 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 | |
|---|
| 2588 | void 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 | |
|---|
| 2604 | Charter * 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 | |
|---|
| 2615 | Charter * 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 | |
|---|
| 2624 | Charter::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 | |
|---|
| 2644 | void 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 | |
|---|
| 2663 | void 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 | |
|---|
| 2678 | void 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 | |
|---|
| 2710 | void 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 | |
|---|
| 2731 | Charter * 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 | |
|---|
| 2750 | Charter * 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 | |
|---|
| 2778 | Charter * 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 | |
|---|
| 2796 | void 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 | |
|---|
| 2810 | void 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 | |
|---|
| 2844 | void ObjectMgr::LoadReputationModifiers() |
|---|
| 2845 | { |
|---|
| 2846 | LoadReputationModifierTable("reputation_creature_onkill", &m_reputation_creature); |
|---|
| 2847 | LoadReputationModifierTable("reputation_faction_onkill", &m_reputation_faction); |
|---|
| 2848 | LoadInstanceReputationModifiers(); |
|---|
| 2849 | } |
|---|
| 2850 | |
|---|
| 2851 | ReputationModifier * 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 | |
|---|
| 2867 | void 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 | |
|---|
| 2932 | void 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 | |
|---|
| 3021 | bool 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 | |
|---|
| 3030 | void 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 | |
|---|
| 3063 | bool 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 | |
|---|
| 3109 | void 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 | |
|---|
| 3124 | void ObjectMgr::ReloadDisabledSpells() |
|---|
| 3125 | { |
|---|
| 3126 | m_disabled_spells.clear(); |
|---|
| 3127 | LoadDisabledSpells(); |
|---|
| 3128 | } |
|---|
| 3129 | |
|---|
| 3130 | void 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 | |
|---|
| 3151 | void 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 | |
|---|
| 3176 | ArenaTeam * 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 | |
|---|
| 3191 | ArenaTeam * 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 | |
|---|
| 3200 | ArenaTeam * 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 | |
|---|
| 3215 | void 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 | |
|---|
| 3223 | void 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 | |
|---|
| 3231 | class ArenaSorter |
|---|
| 3232 | { |
|---|
| 3233 | public: |
|---|
| 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 | |
|---|
| 3244 | void 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 | |
|---|
| 3269 | void 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 | |
|---|
| 3301 | void 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 | |
|---|
| 3325 | void 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 |
|---|
| 3340 | void 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 |
|---|