diff --git a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe index 03c769076..a1e982f0c 100644 Binary files a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe and b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe differ diff --git a/contrib/vmap_extractor_v2/vmapextract/wmo.cpp b/contrib/vmap_extractor_v2/vmapextract/wmo.cpp index 9dfda6f77..a0deab1eb 100644 --- a/contrib/vmap_extractor_v2/vmapextract/wmo.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/wmo.cpp @@ -315,7 +315,11 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, bool pPreciseVectorData) IndexExTr = new int[mopy_size]; for (int i=0; i #include "mpq.h" +// MOPY flags +#define WMO_MATERIAL_NOCAMCOLLIDE 0x01 +#define WMO_MATERIAL_DETAIL 0x02 +#define WMO_MATERIAL_NO_COLLISION 0x04 +#define WMO_MATERIAL_HINT 0x08 +#define WMO_MATERIAL_RENDER 0x10 +#define WMO_MATERIAL_COLLIDE_HIT 0x20 +#define WMO_MATERIAL_WALL_SURFACE 0x40 class WMOInstance; class WMOManager; diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 2e708ae06..1191fdb36 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -407,21 +407,21 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui { AchievementCriteriaEntry const *achievementCriteria = (*i); - // don't update already completed criteria - if(IsCompletedCriteria(achievementCriteria)) - continue; - - if(achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup()) + if (achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup()) continue; AchievementEntry const *achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); - if(!achievement) + if (!achievement) continue; if ((achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_HORDE && GetPlayer()->GetTeam() != HORDE) || (achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE)) continue; + // don't update already completed criteria + if (IsCompletedCriteria(achievementCriteria,achievement)) + continue; + switch (type) { // std. case: increment at 1 @@ -834,6 +834,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(miscvalue1 != achievementCriteria->equip_item.itemID) continue; + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: + // miscvalue1 = go entry + if(!miscvalue1) + continue; + if(miscvalue1 != achievementCriteria->use_gameobject.goEntry) + continue; + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: @@ -926,7 +935,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS: case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS: - case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: @@ -955,20 +963,24 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_TOTAL: break; // Not implemented yet :( } - if(IsCompletedCriteria(achievementCriteria)) - CompletedCriteria(achievementCriteria); + if(IsCompletedCriteria(achievementCriteria,achievement)) + CompletedCriteria(achievementCriteria,achievement); + + + if(AchievementEntryList const* achRefList = achievementmgr.GetAchievementByReferencedId(achievement->ID)) + { + for(AchievementEntryList::const_iterator itr = achRefList->begin(); itr != achRefList->end(); ++itr) + if(IsCompletedAchievement(*itr)) + CompletedAchievement(*itr); + } } } static const uint32 achievIdByClass[MAX_CLASSES] = { 0, 459, 465 , 462, 458, 464, 461, 467, 460, 463, 0, 466 }; static const uint32 achievIdByRace[MAX_RACES] = { 0, 1408, 1410, 1407, 1409, 1413, 1411, 1404, 1412, 0, 1405, 1406 }; -bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria) +bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement) { - AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); - if(!achievement) - return false; - // counter can never complete if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return false; @@ -1056,6 +1068,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: return progress->counter >= achievementCriteria->loot_money.goldInCopper; + case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: + return progress->counter >= achievementCriteria->use_gameobject.useCount; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; @@ -1083,45 +1097,64 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return false; } -void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria) +void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement) { - AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); - if(!achievement) - return; // counter can never complete if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return; - if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || GetAchievementCompletionState(achievement)==ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED) - { + // already completed and stored + if (m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) + return; + + if ((criteria->referredAchievement==achievement->ID && (criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL)) || + IsCompletedAchievement(achievement)) CompletedAchievement(achievement); - } } // TODO: achievement 705 requires 4 criteria to be fulfilled -AchievementCompletionState AchievementMgr::GetAchievementCompletionState(AchievementEntry const* entry) +bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry) { - if(m_completedAchievements.find(entry->ID)!=m_completedAchievements.end()) - return ACHIEVEMENT_COMPLETED_COMPLETED_STORED; + // for achievement with referenced achievement criterias get from referenced and counter from self + uint32 achievmentForTestId = entry->refAchievement ? entry->refAchievement : entry->ID; + uint32 achievmentForTestCount = entry->count; - bool foundOutstanding = false; - for (uint32 entryId = 0; entryIdbegin(); itr != cList->end(); ++itr) { - AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); - if(!criteria || criteria->referredAchievement!= entry->ID) - continue; + AchievementCriteriaEntry const* criteria = *itr; - if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) - return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; + bool completed = IsCompletedCriteria(criteria,entry); - // found an umcompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL - if(!IsCompletedCriteria(criteria)) - foundOutstanding = true; + // found an uncompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL + if(completed) + ++count; + else + completed_all = false; + + if(achievmentForTestId == entry->ID) // not referenced achievement + { + // completed as single req. criteria + if(completed && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) + return true; + } + + // completed as have req. count of completed criterias + if(achievmentForTestCount > 0 && achievmentForTestCount <= count) + return true; } - if(foundOutstanding) - return ACHIEVEMENT_COMPLETED_NONE; - else - return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; + + // all criterias completed requirement + if(completed_all && achievmentForTestCount==0) + return true; + + return false; } void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype) @@ -1317,7 +1350,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList() } barGoLink bar( sAchievementCriteriaStore.GetNumRows() ); - for (uint32 entryId = 0; entryIdrequiredType].push_back(criteria); + m_AchievementCriteriaListByAchievement[criteria->referredAchievement].push_back(criteria); } sLog.outString(); sLog.outString(">> Loaded %lu achievement criteria.",(unsigned long)m_AchievementCriteriasByType->size()); } +void AchievementGlobalMgr::LoadAchievementReferenceList() +{ + if(sAchievementStore.GetNumRows()==0) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 achievement references."); + return; + } + + uint32 count = 0; + barGoLink bar( sAchievementStore.GetNumRows() ); + for (uint32 entryId = 0; entryId < sAchievementStore.GetNumRows(); ++entryId) + { + bar.step(); + + AchievementEntry const* achievement = sAchievementStore.LookupEntry(entryId); + if(!achievement || !achievement->refAchievement) + continue; + + m_AchievementListByReferencedId[achievement->refAchievement].push_back(achievement); + ++count; + } + + sLog.outString(); + sLog.outString(">> Loaded %u achievement references.",count); +} void AchievementGlobalMgr::LoadCompletedAchievements() { diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index d355023d6..89ec6ad19 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -30,7 +30,11 @@ #define CRITERIA_CAST_SPELL_REQ_COUNT 46 #define ACHIEVEMENT_REWARD_COUNT 57 -typedef std::list AchievementCriteriaEntryList; +typedef std::list AchievementCriteriaEntryList; +typedef std::list AchievementEntryList; + +typedef std::map AchievementCriteriaListByAchievement; +typedef std::map AchievementListByReferencedId; struct CriteriaProgress { @@ -80,13 +84,6 @@ class Unit; class Player; class WorldPacket; -enum AchievementCompletionState -{ - ACHIEVEMENT_COMPLETED_NONE, - ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED, - ACHIEVEMENT_COMPLETED_COMPLETED_STORED, -}; - class AchievementMgr { public: @@ -108,10 +105,11 @@ class AchievementMgr void SendAchievementEarned(AchievementEntry const* achievement); void SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress); void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype = PROGRESS_SET); - void CompletedCriteria(AchievementCriteriaEntry const* entry); + void CompletedCriteria(AchievementCriteriaEntry const* entry, AchievementEntry const* achievement); void CompletedAchievement(AchievementEntry const* entry); - bool IsCompletedCriteria(AchievementCriteriaEntry const* entry); - AchievementCompletionState GetAchievementCompletionState(AchievementEntry const* entry); + bool IsCompletedCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement); + bool IsCompletedAchievement(AchievementEntry const* entry); + void CompleteAchievementsWithRefs(AchievementEntry const* entry); void BuildAllDataPacket(WorldPacket *data); Player* m_player; @@ -123,6 +121,17 @@ class AchievementGlobalMgr { public: AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); + AchievementCriteriaEntryList const* GetAchievementCriteriaByAchievement(uint32 id) + { + AchievementCriteriaListByAchievement::const_iterator itr = m_AchievementCriteriaListByAchievement.find(id); + return itr != m_AchievementCriteriaListByAchievement.end() ? &itr->second : NULL; + } + + AchievementEntryList const* GetAchievementByReferencedId(uint32 id) const + { + AchievementListByReferencedId::const_iterator itr = m_AchievementListByReferencedId.find(id); + return itr != m_AchievementListByReferencedId.end() ? &itr->second : NULL; + } AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const { @@ -156,6 +165,7 @@ class AchievementGlobalMgr } void LoadAchievementCriteriaList(); + void LoadAchievementReferenceList(); void LoadCompletedAchievements(); void LoadRewards(); void LoadRewardLocales(); @@ -164,6 +174,10 @@ class AchievementGlobalMgr // store achievement criterias by type to speed up lookup AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL]; + // store achievement criterias by achievement to speed up lookup + AchievementCriteriaListByAchievement m_AchievementCriteriaListByAchievement; + // store achievements by referenced achievement id to speed up lookup + AchievementListByReferencedId m_AchievementListByReferencedId; typedef std::set AllCompletedAchievements; AllCompletedAchievements m_allCompletedAchievements; diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 14acd6706..2f823f4a2 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -52,8 +52,8 @@ struct AchievementEntry //uint32 icon; // 42 icon (from SpellIcon.dbc) //char *titleReward[16]; // 43-58 //uint32 titleReward_flags; // 59 - //uint32 count; // 60 - need this count Criteria for complete - uint32 refAchievement; // 61 - related achievement? + uint32 count; // 60 - need this count of completed criterias (own or referenced achievement criterias) + uint32 refAchievement; // 61 - referenced achievement (counting of all completed criterias) }; struct AchievementCategoryEntry diff --git a/src/game/DBCfmt.h b/src/game/DBCfmt.h index 748c59f2c..bba12409e 100644 --- a/src/game/DBCfmt.h +++ b/src/game/DBCfmt.h @@ -19,7 +19,7 @@ #ifndef MANGOS_DBCSFRM_H #define MANGOS_DBCSFRM_H -const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxxi"; +const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxii"; const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiixix"; const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxxx"; const char AreaGroupEntryfmt[]="niiiiiii"; diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 8c96febbc..f05ca8f58 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -48,11 +48,11 @@ Map::~Map() UnloadAll(true); } -bool Map::ExistMap(uint32 mapid,int x,int y) +bool Map::ExistMap(uint32 mapid,int gx,int gy) { int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; char* tmp = new char[len]; - snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,x,y); + snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,gx,gy); FILE *pf=fopen(tmp,"rb"); @@ -79,17 +79,17 @@ bool Map::ExistMap(uint32 mapid,int x,int y) return true; } -bool Map::ExistVMap(uint32 mapid,int x,int y) +bool Map::ExistVMap(uint32 mapid,int gx,int gy) { if(VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) { if(vmgr->isMapLoadingEnabled()) { // x and y are swapped !! => fixed now - bool exists = vmgr->existsMap((sWorld.GetDataPath()+ "vmaps").c_str(), mapid, x,y); + bool exists = vmgr->existsMap((sWorld.GetDataPath()+ "vmaps").c_str(), mapid, gx,gy); if(!exists) { - std::string name = vmgr->getDirFileName(mapid,x,y); + std::string name = vmgr->getDirFileName(mapid,gx,gy); sLog.outError("VMap file '%s' is missing or point to wrong version vmap file, redo vmaps with latest vmap_assembler.exe program", (sWorld.GetDataPath()+"vmaps/"+name).c_str()); return false; } @@ -99,75 +99,70 @@ bool Map::ExistVMap(uint32 mapid,int x,int y) return true; } -void Map::LoadVMap(int x,int y) +void Map::LoadVMap(int gx,int gy) { // x and y are swapped !! - int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath()+ "vmaps").c_str(), GetId(), x,y); + int vmapLoadResult = VMAP::VMapFactory::createOrGetVMapManager()->loadMap((sWorld.GetDataPath()+ "vmaps").c_str(), GetId(), gx,gy); switch(vmapLoadResult) { case VMAP::VMAP_LOAD_RESULT_OK: - sLog.outDetail("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), x,y, x,y); + sLog.outDetail("VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); break; case VMAP::VMAP_LOAD_RESULT_ERROR: - sLog.outDetail("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), x,y, x,y); + sLog.outDetail("Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); break; case VMAP::VMAP_LOAD_RESULT_IGNORED: - DEBUG_LOG("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), x,y, x,y); + DEBUG_LOG("Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx,gy,gx,gy); break; } } -void Map::LoadMap(uint32 mapid, uint32 instanceid, int x,int y) +void Map::LoadMap(int gx,int gy) { - if( instanceid != 0 ) + if( i_InstanceId != 0 ) { - if(GridMaps[x][y]) + if(GridMaps[gx][gy]) return; - Map* baseMap = const_cast(MapManager::Instance().GetBaseMap(mapid)); + Map* baseMap = const_cast(MapManager::Instance().GetBaseMap(i_id)); - // load gridmap for base map - if (!baseMap->GridMaps[x][y]) - baseMap->EnsureGridCreated(GridPair(63-x,63-y)); + // load grid map for base map + if (!baseMap->GridMaps[gx][gy]) + baseMap->EnsureGridCreated(GridPair(63-gx,63-gy)); -//+++ if (!baseMap->GridMaps[x][y]) don't check for GridMaps[gx][gy], we need the management for vmaps -// return; - - ((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(x,y)); - GridMaps[x][y] = baseMap->GridMaps[x][y]; + ((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(gx,gy)); + GridMaps[gx][gy] = baseMap->GridMaps[gx][gy]; return; } //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?) - if(GridMaps[x][y]) + if(GridMaps[gx][gy]) { - sLog.outDetail("Unloading already loaded map %u before reloading.",mapid); - delete (GridMaps[x][y]); - GridMaps[x][y]=NULL; + sLog.outDetail("Unloading already loaded map %u before reloading.",i_id); + delete (GridMaps[gx][gy]); + GridMaps[gx][gy]=NULL; } // map file name char *tmp=NULL; - // Pihhan: dataPath length + "maps/" + 3+2+2+ ".map" length may be > 32 ! int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; tmp = new char[len]; - snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),mapid,x,y); + snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),i_id,gx,gy); sLog.outDetail("Loading map %s",tmp); // loading data - GridMaps[x][y] = new GridMap(); - if (!GridMaps[x][y]->loadData(tmp)) + GridMaps[gx][gy] = new GridMap(); + if (!GridMaps[gx][gy]->loadData(tmp)) { sLog.outError("Error load map file: \n %s\n", tmp); } delete [] tmp; - return; } -void Map::LoadMapAndVMap(uint32 mapid, uint32 instanceid, int x,int y) +void Map::LoadMapAndVMap(int gx,int gy) { - LoadMap(mapid,instanceid,x,y); - if(instanceid == 0) - LoadVMap(x, y); // Only load the data for the base map + LoadMap(gx,gy); + if(i_InstanceId == 0) + LoadVMap(gx, gy); // Only load the data for the base map } void Map::InitStateMachine() @@ -334,20 +329,20 @@ Map::EnsureGridCreated(const GridPair &p) int gy=63-p.y_coord; if(!GridMaps[gx][gy]) - Map::LoadMapAndVMap(i_id,i_InstanceId,gx,gy); + LoadMapAndVMap(gx,gy); } } } void -Map::EnsureGridLoaded(const Cell &cell, Player *player) +Map::EnsureGridLoadedAtEnter(const Cell &cell, Player *player) { - EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); - NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); + NGridType *grid; - assert(grid != NULL); - if (!isGridObjectDataLoaded(cell.GridX(), cell.GridY())) + if(EnsureGridLoaded(cell)) { + grid = getNGrid(cell.GridX(), cell.GridY()); + if (player) { player->SendDelayResponse(MAX_GRID_LOAD_TIME); @@ -358,23 +353,17 @@ Map::EnsureGridLoaded(const Cell &cell, Player *player) DEBUG_LOG("Active object nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), i_id); } - ObjectGridLoader loader(*grid, this, cell); - loader.LoadN(); - setGridObjectDataLoaded(true, cell.GridX(), cell.GridY()); - - // Add resurrectable corpses to world object list in grid - ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this); - ResetGridExpiry(*getNGrid(cell.GridX(), cell.GridY()), 0.1f); grid->SetGridState(GRID_STATE_ACTIVE); } + else + grid = getNGrid(cell.GridX(), cell.GridY()); if (player) AddToGrid(player,grid,cell); } -void -Map::LoadGrid(const Cell& cell, bool no_unload) +bool Map::EnsureGridLoaded(const Cell &cell) { EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); @@ -389,10 +378,18 @@ Map::LoadGrid(const Cell& cell, bool no_unload) ObjectAccessor::Instance().AddCorpsesToGrid(GridPair(cell.GridX(),cell.GridY()),(*grid)(cell.CellX(), cell.CellY()), this); setGridObjectDataLoaded(true,cell.GridX(), cell.GridY()); - if(no_unload) - getNGrid(cell.GridX(), cell.GridY())->setUnloadExplicitLock(true); + return true; } - LoadVMap(63-cell.GridX(),63-cell.GridY()); + + return false; +} + +void Map::LoadGrid(const Cell& cell, bool no_unload) +{ + EnsureGridLoaded(cell); + + if(no_unload) + getNGrid(cell.GridX(), cell.GridY())->setUnloadExplicitLock(true); } bool Map::Add(Player *player) @@ -404,7 +401,7 @@ bool Map::Add(Player *player) // update player state for other player and visa-versa CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); Cell cell(p); - EnsureGridLoaded(cell, player); + EnsureGridLoadedAtEnter(cell, player); player->AddToWorld(); SendInitSelf(player); @@ -433,7 +430,7 @@ Map::Add(T *obj) Cell cell(p); if(obj->isActiveObject()) - EnsureGridLoaded(cell); + EnsureGridLoadedAtEnter(cell); else EnsureGridCreated(GridPair(cell.GridX(), cell.GridY())); @@ -788,7 +785,7 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati if( !old_cell.DiffGrid(new_cell) ) AddToGrid(player, oldGrid,new_cell); else - EnsureGridLoaded(new_cell, player); + EnsureGridLoadedAtEnter(new_cell, player); } // if move then update what player see and who seen @@ -912,7 +909,7 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell) // in diff. grids but active creature if(c->isActiveObject()) { - EnsureGridLoaded(new_cell); + EnsureGridLoadedAtEnter(new_cell); #ifdef MANGOS_DEBUG if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0) @@ -1878,7 +1875,8 @@ void Map::SendInitTransports( Player * player ) for (MapManager::TransportSet::iterator i = tset.begin(); i != tset.end(); ++i) { - if((*i) != player->GetTransport()) // send data for current transport in other place + // send data for current transport in other place + if((*i) != player->GetTransport() && (*i)->GetMapId()==i_id) { hasTransport = true; (*i)->BuildCreateUpdateBlockForPlayer(&transData, player); @@ -1905,7 +1903,7 @@ void Map::SendRemoveTransports( Player * player ) // except used transport for (MapManager::TransportSet::iterator i = tset.begin(); i != tset.end(); ++i) - if(player->GetTransport() != (*i)) + if((*i) != player->GetTransport() && (*i)->GetMapId()!=i_id) (*i)->BuildOutOfRangeUpdateBlock(&transData); WorldPacket packet; diff --git a/src/game/Map.h b/src/game/Map.h index e0739c423..9252f9928 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -299,9 +299,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj time_t GetGridExpiry(void) const { return i_gridExpiry; } uint32 GetId(void) const { return i_id; } - static bool ExistMap(uint32 mapid, int x, int y); - static bool ExistVMap(uint32 mapid, int x, int y); - void LoadMapAndVMap(uint32 mapid, uint32 instanceid, int x, int y); + static bool ExistMap(uint32 mapid, int gx, int gy); + static bool ExistVMap(uint32 mapid, int gx, int gy); static void InitStateMachine(); static void DeleteStateMachine(); @@ -404,8 +403,9 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj void RemoveFromActive(Creature* obj); private: - void LoadVMap(int pX, int pY); - void LoadMap(uint32 mapid, uint32 instanceid, int x,int y); + void LoadMapAndVMap(int gx, int gy); + void LoadVMap(int gx, int gy); + void LoadMap(int gx,int gy); GridMap *GetGrid(float x, float y); void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } @@ -425,8 +425,9 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj CreatureMoveList i_creaturesToMove; bool loaded(const GridPair &) const; - void EnsureGridLoaded(const Cell&, Player* player = NULL); - void EnsureGridCreated(const GridPair &); + void EnsureGridCreated(const GridPair &); + bool EnsureGridLoaded(Cell const&); + void EnsureGridLoadedAtEnter(Cell const&, Player* player = NULL); void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h index e195cdcb7..783de74ad 100644 --- a/src/game/MapInstanced.h +++ b/src/game/MapInstanced.h @@ -49,7 +49,7 @@ class MANGOS_DLL_DECL MapInstanced : public Map SetUnloadReferenceLock(GridPair(63-p.x_coord, 63-p.y_coord), true); } - void RemoveGridMapReference(const GridPair &p) + void RemoveGridMapReference(GridPair const& p) { --GridMapReference[p.x_coord][p.y_coord]; if (!GridMapReference[p.x_coord][p.y_coord]) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ec485481f..afa5219ec 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1773,7 +1773,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // if the player is saved before worldportack (at logout for example) // this will be used instead of the current location in SaveToDB - RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING); // move packet sent by client always after far teleport // SetPosition(final_x, final_y, final_z, final_o, true); @@ -14384,15 +14384,17 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) else remaincharges = 0; - //do not load single target auras (unless they were cast by the player) - if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto)) - continue; for(uint32 i=0; iGetModifier()->m_amount; + + // reset stolen single target auras + if (caster_guid != GetGUID() && aura->IsSingleTarget()) + aura->SetIsSingleTarget(false); + aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); AddAura(aura); sLog.outDetail("Added aura spellid %u, effect %u", spellproto->Id, effindex); @@ -15422,7 +15424,7 @@ void Player::_SaveAuras() if (!(itr2->second->IsPassive() || itr2->second->IsRemovedOnShapeLost())) { //do not save single target auras (unless they were cast by the player) - if (!(itr2->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo))) + if (!(itr2->second->GetCasterGUID() != GetGUID() && itr2->second->IsSingleTarget())) { uint8 i; // or apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index e3b0f494e..e5024a717 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2487,7 +2487,7 @@ void Spell::cast(bool skipCheck) if (m_caster->GetTypeId() == TYPEID_PLAYER) { - if (m_CastItem) + if (!m_IsTriggeredSpell && m_CastItem) ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry()); ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id); @@ -4991,8 +4991,8 @@ SpellCastResult Spell::CheckItems() focusObject = ok; // game object found in range } - // check reagents - if (!p_caster->CanNoReagentCast(m_spellInfo)) + // check reagents (ignore triggered spells with reagents processed by original spell) and special reagent ignore case. + if (!m_IsTriggeredSpell && !p_caster->CanNoReagentCast(m_spellInfo)) { for(uint32 i=0;i<8;i++) { diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index dcafd1030..e7bf02395 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -365,6 +365,8 @@ m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false) m_isPassive = IsPassiveSpell(GetId()); m_positive = IsPositiveEffect(GetId(), m_effIndex); + m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto); + m_applyTime = time(NULL); int32 damage; @@ -3489,52 +3491,56 @@ void Aura::HandleAuraModStun(bool apply, bool Real) void Aura::HandleModStealth(bool apply, bool Real) { - if(apply) + Unit* pTarget = m_target; + + if (apply) { // drop flag at stealth in bg - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + pTarget->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); // only at real aura add - if(Real) + if (Real) { - m_target->SetStandFlags(UNIT_STAND_FLAGS_CREEP); - if(m_target->GetTypeId()==TYPEID_PLAYER) - m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); + pTarget->SetStandFlags(UNIT_STAND_FLAGS_CREEP); + + if (pTarget->GetTypeId()==TYPEID_PLAYER) + pTarget->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); // apply only if not in GM invisibility (and overwrite invisibility state) - if(m_target->GetVisibility()!=VISIBILITY_OFF) + if (pTarget->GetVisibility()!=VISIBILITY_OFF) { - m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); + pTarget->SetVisibility(VISIBILITY_GROUP_NO_DETECT); + pTarget->SetVisibility(VISIBILITY_GROUP_STEALTH); } } } else { // only at real aura remove - if(Real) + if (Real) { // if last SPELL_AURA_MOD_STEALTH and no GM invisibility - if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF) + if (!pTarget->HasAuraType(SPELL_AURA_MOD_STEALTH) && pTarget->GetVisibility()!=VISIBILITY_OFF) { - m_target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); - if(m_target->GetTypeId()==TYPEID_PLAYER) - m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); + pTarget->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); + + if (pTarget->GetTypeId()==TYPEID_PLAYER) + pTarget->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); // restore invisibility if any - if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) + if (pTarget->HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) { - m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); + pTarget->SetVisibility(VISIBILITY_GROUP_NO_DETECT); + pTarget->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); } else - m_target->SetVisibility(VISIBILITY_ON); + pTarget->SetVisibility(VISIBILITY_ON); } } } // Master of Subtlety - Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY); + Unit::AuraList const& mDummyAuras = pTarget->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) { if ((*i)->GetSpellProto()->SpellIconID == 2114) @@ -3542,10 +3548,10 @@ void Aura::HandleModStealth(bool apply, bool Real) if (apply) { int32 bp = (*i)->GetModifier()->m_amount; - m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true); + pTarget->CastCustomSpell(pTarget,31665,&bp,NULL,NULL,true); } else - m_target->CastSpell(m_target,31666,true); + pTarget->CastSpell(pTarget,31666,true); break; } } @@ -6747,3 +6753,21 @@ void Aura::HandlePhase(bool apply, bool Real) m_target->SetVisibility(m_target->GetVisibility()); } +void Aura::UnregisterSingleCastAura() +{ + if (IsSingleTarget()) + { + Unit* caster = NULL; + caster = GetCaster(); + if(caster) + { + caster->GetSingleCastAuras().remove(this); + } + else + { + sLog.outError("Couldn't find the caster of the single target aura, may crash later!"); + assert(false); + } + m_isSingleTargetAura = false; + } +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index a9877d5d2..da920425c 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -267,6 +267,8 @@ class MANGOS_DLL_SPEC Aura return m_procCharges == 0; } + void UnregisterSingleCastAura(); + void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); } void SendAuraUpdate(bool remove); @@ -296,6 +298,10 @@ class MANGOS_DLL_SPEC Aura bool IsUpdated() { return m_updated; } void SetUpdated(bool val) { m_updated = val; } + + bool IsSingleTarget() {return m_isSingleTargetAura;} + void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;} + void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } virtual Unit* GetTriggerTarget() const { return m_target; } @@ -352,6 +358,7 @@ class MANGOS_DLL_SPEC Aura bool m_isRemovedOnShapeLost:1; bool m_updated:1; // Prevent remove aura by stack if set bool m_in_use:1; // true while in Aura::ApplyModifier call + bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example private: void CleanupTriggeredSpells(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 0f18b3d91..8eed38f7f 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1748,6 +1748,26 @@ void Spell::EffectDummy(uint32 i) return; } break; + case SPELLFAMILY_DEATHKNIGHT: + // Death Coil + if(m_spellInfo->SpellFamilyFlags & 0x002000LL) + { + if(m_caster->IsFriendlyTo(unitTarget)) + { + if(unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD) + return; + + int32 bp = damage * 1.5f; + m_caster->CastCustomSpell(unitTarget,47633,&bp,NULL,NULL,true); + } + else + { + int32 bp = damage; + m_caster->CastCustomSpell(unitTarget,47632,&bp,NULL,NULL,true); + } + return; + } + break; } // pet auras @@ -2375,6 +2395,14 @@ void Spell::EffectPowerBurn(uint32 i) if(damage < 0) return; + // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn) + if(m_spellInfo->ManaCostPercentage) + { + uint32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100; + damage = unitTarget->GetMaxPower(powertype) * damage / 100; + if(damage > maxdamage) damage = maxdamage; + } + int32 curPower = int32(unitTarget->GetPower(powertype)); // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 19b7d2b99..b6122c7c8 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -234,6 +234,15 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) recvPacket >> guid; sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [in game guid: %u]", GUID_LOPART(guid)); + + GameObject* go = ObjectAccessor::GetGameObject(*_player,guid); + if(!go) + return; + + if(!go->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) + return; + + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry()); } void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index 97bb68ae3..845c98ba9 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -85,8 +85,6 @@ void MapManager::LoadTransports() continue; } - t->m_name = goinfo->name; - float x, y, z, o; uint32 mapid; x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1; @@ -181,6 +179,8 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, if(dynflags) SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags)); + SetName(goinfo->name); + return true; } @@ -432,11 +432,9 @@ Transport::WayPointMap::iterator Transport::GetNextWayPoint() void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) { - //GetMap()->Remove((GameObject *)this, false); + Map const* oldMap = GetMap(); SetMapId(newMapid); - //MapManager::Instance().LoadGrid(newMapid,x,y,true); Relocate(x, y, z); - //GetMap()->Add((GameObject *)this); for(PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();) { @@ -460,13 +458,21 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) //data << uint32(0); //plr->GetSession()->SendPacket(&data); } + + Map const* newMap = GetMap(); + + if(oldMap != newMap) + { + UpdateForMap(oldMap); + UpdateForMap(newMap); + } } bool Transport::AddPassenger(Player* passenger) { if (m_passengers.find(passenger) == m_passengers.end()) { - sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), m_name.c_str()); + sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), GetName()); m_passengers.insert(passenger); } return true; @@ -475,7 +481,7 @@ bool Transport::AddPassenger(Player* passenger) bool Transport::RemovePassenger(Player* passenger) { if (m_passengers.erase(passenger)) - sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), m_name.c_str()); + sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), GetName()); return true; } @@ -497,7 +503,6 @@ void Transport::Update(uint32 /*p_time*/) } else { - //MapManager::Instance().GetMap(m_curr->second.mapid)->GameobjectRelocation((GameObject *)this, m_curr->second.x, m_curr->second.y, m_curr->second.z, m_orientation); Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z); } @@ -513,13 +518,42 @@ void Transport::Update(uint32 /*p_time*/) m_nextNodeTime = m_curr->first; if (m_curr == m_WayPoints.begin() && (sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES)==0) - sLog.outDetail(" ************ BEGIN ************** %s", m_name.c_str()); - - // MapManager::Instance().GetMap(m_curr->second.mapid)->Add(&this); // -> // ->Add(t); - //MapManager::Instance().GetMap(m_curr->second.mapid)->Remove((GameObject *)this, false); // -> // ->Add(t); - //MapManager::Instance().GetMap(m_curr->second.mapid)->Add((GameObject *)this); // -> // ->Add(t); + sLog.outDetail(" ************ BEGIN ************** %s", GetName()); if ((sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES)==0) - sLog.outDetail("%s moved to %f %f %f %d", m_name.c_str(), m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); + sLog.outDetail("%s moved to %f %f %f %d", GetName(), m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); + } +} + +void Transport::UpdateForMap(Map const* targetMap) +{ + Map::PlayerList const& pl = targetMap->GetPlayers(); + if(pl.isEmpty()) + return; + + if(GetMapId()==targetMap->GetId()) + { + for(Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) + { + if(this != itr->getSource()->GetTransport()) + { + UpdateData transData; + BuildCreateUpdateBlockForPlayer(&transData, itr->getSource()); + WorldPacket packet; + transData.BuildPacket(&packet, true); + itr->getSource()->SendDirectMessage(&packet); + } + } + } + else + { + UpdateData transData; + BuildOutOfRangeUpdateBlock(&transData); + WorldPacket out_packet; + transData.BuildPacket(&out_packet, true); + + for(Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) + if(this != itr->getSource()->GetTransport()) + itr->getSource()->SendDirectMessage(&out_packet); } } diff --git a/src/game/Transports.h b/src/game/Transports.h index bfd2ccccb..1a7cbb7bd 100644 --- a/src/game/Transports.h +++ b/src/game/Transports.h @@ -54,7 +54,7 @@ class TransportPath std::vector i_nodes; }; -class Transport : private GameObject +class Transport : protected GameObject { public: explicit Transport(); @@ -81,7 +81,6 @@ class Transport : private GameObject typedef std::set PlayerSet; PlayerSet const& GetPassengers() const { return m_passengers; } - std::string m_name; private: struct WayPoint { @@ -111,6 +110,7 @@ class Transport : private GameObject private: void TeleportTransport(uint32 newMapid, float x, float y, float z); + void UpdateForMap(Map const* map); WayPointMap::iterator GetNextWayPoint(); }; #endif diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 46cfbfb6c..33a63d2fe 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3411,7 +3411,7 @@ bool Unit::AddAura(Aura *Aur) } // update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura) - if (IsSingleTargetSpell(aurSpellInfo) && Aur->GetTarget()) + if (Aur->IsSingleTarget() && Aur->GetTarget()) { // caster pointer can be deleted in time aura remove, find it by guid at each iteration for(;;) @@ -3692,10 +3692,9 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID) { int32 basePoints = aur->GetBasePoints(); - // construct the new aura for the attacker - Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), &basePoints, stealer); - if(!new_aur) - continue; + // construct the new aura for the attacker - will never return NULL, it's just a wrapper for + // some different constructors + Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), &basePoints, stealer, this); // set its duration and maximum duration // max duration 2 minutes (in msecs) @@ -3704,6 +3703,12 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur ); new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur ); + // Unregister _before_ adding to stealer + aur->UnregisterSingleCastAura(); + + // strange but intended behaviour: Stolen single target auras won't be treated as single targeted + new_aur->SetIsSingleTarget(false); + // add the new aura to stealer stealer->AddAura(new_aur); @@ -3830,21 +3835,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) Aura* Aur = i->second; SpellEntry const* AurSpellInfo = Aur->GetSpellProto(); - Unit* caster = NULL; - if (IsSingleTargetSpell(AurSpellInfo)) - { - caster = Aur->GetCaster(); - if(caster) - { - AuraList& scAuras = caster->GetSingleCastAuras(); - scAuras.remove(Aur); - } - else - { - sLog.outError("Couldn't find the caster of the single target aura, may crash later!"); - assert(false); - } - } + Aur->UnregisterSingleCastAura(); // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) if (Aur->GetModifier()->m_auraname < TOTAL_AURAS) @@ -3864,8 +3855,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) bool caster_channeled = false; if(IsChanneledSpell(AurSpellInfo)) { - if(!caster) // can be already located for IsSingleTargetSpell case - caster = Aur->GetCaster(); + Unit* caster = Aur->GetCaster(); if(caster) { diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index 469a837cb..5cea9ed93 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -101,7 +101,7 @@ void WaypointManager::Load() node.y = fields[1].GetFloat(); node.z = fields[2].GetFloat(); node.orientation = fields[3].GetFloat(); - node.delay = fields[6].GetUInt16(); + node.delay = fields[6].GetUInt32(); // prevent using invalid coordinates if(!MaNGOS::IsValidMapCoord(node.x, node.y, node.z, node.orientation)) diff --git a/src/game/World.cpp b/src/game/World.cpp index a64a68698..e1364d66c 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1267,6 +1267,7 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Achievements..." ); sLog.outString(); + achievementmgr.LoadAchievementReferenceList(); achievementmgr.LoadAchievementCriteriaList(); achievementmgr.LoadRewards(); achievementmgr.LoadRewardLocales(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 41b7460fe..cdfa2499e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7590" + #define REVISION_NR "7608" #endif // __REVISION_NR_H__