diff --git a/sql/characters.sql b/sql/characters.sql index aed3b1d0f..6d4debeef 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_8721_01_characters_guild` bit(1) default NULL + `required_8828_01_characters_instance_reset` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -1170,8 +1170,9 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `instance_reset`; CREATE TABLE `instance_reset` ( `mapid` int(11) unsigned NOT NULL default '0', + `difficulty` tinyint(1) unsigned NOT NULL default '0', `resettime` bigint(40) NOT NULL default '0', - PRIMARY KEY (`mapid`) + PRIMARY KEY (`mapid`,`difficulty`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- diff --git a/sql/mangos.sql b/sql/mangos.sql index d8c98dae7..377f82e32 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_8818_01_mangos_mangos_string` bit(1) default NULL + `required_8828_02_mangos_instance_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -1904,9 +1904,6 @@ CREATE TABLE `instance_template` ( `parent` int(10) unsigned NOT NULL, `levelMin` tinyint(3) unsigned NOT NULL default '0', `levelMax` tinyint(3) unsigned NOT NULL default '0', - `maxPlayers` tinyint(3) unsigned NOT NULL default '0', - `maxPlayersHeroic` tinyint(3) unsigned NOT NULL default '0', - `reset_delay` int(10) unsigned NOT NULL default '0', `startLocX` float default NULL, `startLocY` float default NULL, `startLocZ` float default NULL, diff --git a/sql/updates/8828_01_characters_instance_reset.sql b/sql/updates/8828_01_characters_instance_reset.sql new file mode 100644 index 000000000..0fb87f4c7 --- /dev/null +++ b/sql/updates/8828_01_characters_instance_reset.sql @@ -0,0 +1,6 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_8721_01_characters_guild required_8828_01_characters_instance_reset bit; + +ALTER TABLE instance_reset + ADD COLUMN difficulty tinyint(1) unsigned NOT NULL default '0' AFTER mapid, + DROP PRIMARY KEY, + ADD PRIMARY KEY (`mapid`,`difficulty`); diff --git a/sql/updates/8828_02_mangos_instance_template.sql b/sql/updates/8828_02_mangos_instance_template.sql new file mode 100644 index 000000000..c5f1815b9 --- /dev/null +++ b/sql/updates/8828_02_mangos_instance_template.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_8818_01_mangos_mangos_string required_8828_02_mangos_instance_template bit; + +ALTER TABLE instance_template + DROP COLUMN maxPlayers, + DROP COLUMN maxPlayersHeroic, + DROP COLUMN reset_delay; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index ecb0c3202..f27eb879d 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -158,6 +158,8 @@ pkgdata_DATA = \ 8803_02_mangos_playercreateinfo_action.sql \ 8815_01_mangos_mangos_string.sql \ 8818_01_mangos_mangos_string.sql \ + 8828_01_characters_instance_reset.sql \ + 8828_02_mangos_instance_template.sql \ README ## Additional files to include when running 'make dist' @@ -296,4 +298,6 @@ EXTRA_DIST = \ 8803_02_mangos_playercreateinfo_action.sql \ 8815_01_mangos_mangos_string.sql \ 8818_01_mangos_mangos_string.sql \ + 8828_01_characters_instance_reset.sql \ + 8828_02_mangos_instance_template.sql \ README diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h index 9eae1082d..8b0833859 100644 --- a/src/game/DBCEnums.h +++ b/src/game/DBCEnums.h @@ -234,6 +234,8 @@ enum AreaFlags enum Difficulty { + DIFFICULTY_DEFAULT = 0, + DUNGEON_DIFFICULTY_NORMAL = 0, DUNGEON_DIFFICULTY_HEROIC = 1, @@ -249,7 +251,7 @@ enum Difficulty enum SpawnMask { - SPAWNMASK_CONTINENT = 1, // any any maps without spawn modes + SPAWNMASK_CONTINENT = (1 << DIFFICULTY_DEFAULT),// any any maps without spawn modes SPAWNMASK_DUNGEON_NORMAL = (1 << DUNGEON_DIFFICULTY_NORMAL), SPAWNMASK_DUNGEON_HEROIC = (1 << DUNGEON_DIFFICULTY_HEROIC), diff --git a/src/game/DBCStores.cpp b/src/game/DBCStores.cpp index 6d09018e1..743c79552 100644 --- a/src/game/DBCStores.cpp +++ b/src/game/DBCStores.cpp @@ -100,7 +100,6 @@ DBCStorage sMapStore(MapEntryfmt); // DBC used only for initialization sMapDifficultyMap at startup. DBCStorage sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading -typedef std::map MapDifficultyMap; MapDifficultyMap sMapDifficultyMap; DBCStorage sMovieStore(MovieEntryfmt); diff --git a/src/game/DBCStores.h b/src/game/DBCStores.h index 046cfc6b5..691c4354c 100644 --- a/src/game/DBCStores.h +++ b/src/game/DBCStores.h @@ -55,6 +55,7 @@ bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredT void Zone2MapCoordinates(float& x,float& y,uint32 zone); void Map2ZoneCoordinates(float& x,float& y,uint32 zone); +typedef std::map MapDifficultyMap; MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty); uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls); @@ -113,6 +114,7 @@ extern DBCStorage sLockStore; extern DBCStorage sMailTemplateStore; extern DBCStorage sMapStore; //extern DBCStorage sMapDifficultyStore; -- use GetMapDifficultyData insteed +extern MapDifficultyMap sMapDifficultyMap; extern DBCStorage sMovieStore; extern DBCStorage sQuestSortStore; extern DBCStorage sRandomPropertiesPointsStore; diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index 8963de3f5..ea713d95a 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -100,13 +100,13 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance { // initialize reset time // for normal instances if no creatures are killed the instance will reset in two hours - if(entry->map_type == MAP_RAID || difficulty == DUNGEON_DIFFICULTY_HEROIC) - resetTime = GetResetTimeFor(mapId); + if(entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL) + resetTime = GetResetTimeFor(mapId,difficulty); else { resetTime = time(NULL) + 2 * HOUR; // normally this will be removed soon after in InstanceMap::Add, prevent error - ScheduleReset(true, resetTime, InstResetEvent(0, mapId, instanceId)); + ScheduleReset(true, resetTime, InstResetEvent(0, mapId, difficulty, instanceId)); } } @@ -378,18 +378,26 @@ void InstanceSaveManager::LoadResetTimes() // get the current reset times for normal instances (these may need to be updated) // these are only kept in memory for InstanceSaves that are loaded later // resettime = 0 in the DB for raid/heroic instances so those are skipped - typedef std::map > ResetTimeMapType; - ResetTimeMapType InstResetTime; - QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0"); + typedef std::pair ResetTimeMapDiffType; + typedef std::map InstResetTimeMapDiffType; + InstResetTimeMapDiffType instResetTime; + + // index instance ids by map/difficulty pairs for fast reset warning send + typedef std::multimap ResetTimeMapDiffInstances; + ResetTimeMapDiffInstances mapDiffResetInstances; + + QueryResult *result = CharacterDatabase.Query("SELECT id, map, difficulty, resettime FROM instance WHERE resettime > 0"); if( result ) { do { - if(time_t resettime = time_t((*result)[2].GetUInt64())) + if(time_t resettime = time_t((*result)[3].GetUInt64())) { uint32 id = (*result)[0].GetUInt32(); uint32 mapid = (*result)[1].GetUInt32(); - InstResetTime[id] = std::pair(mapid, resettime); + uint32 difficulty = (*result)[2].GetUInt32(); + instResetTime[id] = ResetTimeMapDiffType(MAKE_PAIR32(mapid,difficulty), resettime); + mapDiffResetInstances.insert(ResetTimeMapDiffInstances::value_type(MAKE_PAIR32(mapid,difficulty),id)); } } while (result->NextRow()); @@ -404,8 +412,8 @@ void InstanceSaveManager::LoadResetTimes() Field *fields = result->Fetch(); uint32 instance = fields[1].GetUInt32(); time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR); - ResetTimeMapType::iterator itr = InstResetTime.find(instance); - if(itr != InstResetTime.end() && itr->second.second != resettime) + InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance); + if(itr != instResetTime.end() && itr->second.second != resettime) { CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance); itr->second.second = resettime; @@ -416,59 +424,65 @@ void InstanceSaveManager::LoadResetTimes() } // schedule the reset times - for(ResetTimeMapType::iterator itr = InstResetTime.begin(); itr != InstResetTime.end(); ++itr) + for(InstResetTimeMapDiffType::iterator itr = instResetTime.begin(); itr != instResetTime.end(); ++itr) if(itr->second.second > now) - ScheduleReset(true, itr->second.second, InstResetEvent(0, itr->second.first, itr->first)); + ScheduleReset(true, itr->second.second, InstResetEvent(0, PAIR32_LOPART(itr->second.first),Difficulty(PAIR32_HIPART(itr->second.first)),itr->first)); } // load the global respawn times for raid/heroic instances uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; - m_resetTimeByMapId.resize(sMapStore.GetNumRows()+1); - result = CharacterDatabase.Query("SELECT mapid, resettime FROM instance_reset"); + result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset"); if(result) { do { Field *fields = result->Fetch(); uint32 mapid = fields[0].GetUInt32(); - if(!ObjectMgr::GetInstanceTemplate(mapid)) + Difficulty difficulty = Difficulty(fields[1].GetUInt32()); + uint64 oldresettime = fields[2].GetUInt64(); + + MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty); + if(!mapDiff) { - sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid %u in instance_reset!", mapid); - CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid); + sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty); + CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid,difficulty); continue; } // update the reset time if the hour in the configs changes - uint64 oldresettime = fields[1].GetUInt64(); uint64 newresettime = (oldresettime / DAY) * DAY + diff; if(oldresettime != newresettime) - CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", newresettime, mapid); + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty = '%u'", newresettime, mapid, difficulty); - m_resetTimeByMapId[mapid] = newresettime; + SetResetTimeFor(mapid,difficulty,newresettime); } while(result->NextRow()); delete result; } // clean expired instances, references to them will be deleted in CleanupInstances // must be done before calculating new reset times - _DelHelper(CharacterDatabase, "id, map, difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now); + _DelHelper(CharacterDatabase, "id, map, instance.difficulty", "instance", "LEFT JOIN instance_reset ON mapid = map AND instance.difficulty = instance_reset.difficulty WHERE (instance.resettime < '"UI64FMTD"' AND instance.resettime > '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime < '"UI64FMTD"')", (uint64)now, (uint64)now); // calculate new global reset times for expired instances and those that have never been reset yet // add the global reset times to the priority queue - for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) + for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr) { - InstanceTemplate const* temp = ObjectMgr::GetInstanceTemplate(i); - if(!temp || temp->reset_delay == 0) + uint32 map_diff_pair = itr->first; + uint32 mapid = PAIR32_LOPART(map_diff_pair); + Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair)); + MapDifficulty const* mapDiff = &itr->second; + if (!mapDiff->resetTime) continue; - uint32 period = temp->reset_delay * DAY; - assert(period != 0); - time_t t = m_resetTimeByMapId[temp->map]; + // the reset_delay must be at least one day + uint32 period = (mapDiff->resetTime / DAY * sWorld.getRate(RATE_INSTANCE_RESET_TIME)) * DAY; + + time_t t = GetResetTimeFor(mapid,difficulty); if(!t) { // initialize the reset time t = today + period + diff; - CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','"UI64FMTD"')", i, (uint64)t); + CharacterDatabase.DirectPExecute("INSERT INTO instance_reset VALUES ('%u','%u','"UI64FMTD"')", mapid, difficulty, (uint64)t); } if(t < now) @@ -477,17 +491,23 @@ void InstanceSaveManager::LoadResetTimes() // calculate the next reset time t = (t / DAY) * DAY; t += ((today - t) / period + 1) * period + diff; - CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u'", (uint64)t, i); + CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty); } - m_resetTimeByMapId[temp->map] = t; + SetResetTimeFor(mapid,difficulty,t); // schedule the global reset/warning uint8 type = 1; static int tim[4] = {3600, 900, 300, 60}; for(; type < 4; type++) - if(t - tim[type-1] > now) break; - ScheduleReset(true, t - tim[type-1], InstResetEvent(type, i)); + if(t - tim[type-1] > now) + break; + + for(ResetTimeMapDiffInstances::const_iterator in_itr = mapDiffResetInstances.lower_bound(map_diff_pair); + in_itr != mapDiffResetInstances.upper_bound(map_diff_pair); ++in_itr) + { + ScheduleReset(true, t - tim[type-1], InstResetEvent(type, mapid, difficulty, in_itr->second)); + } } } @@ -528,8 +548,8 @@ void InstanceSaveManager::Update() else { // global reset/warning for a certain map - time_t resetTime = GetResetTimeFor(event.mapid); - _ResetOrWarnAll(event.mapid, event.type != 4, resetTime - now); + time_t resetTime = GetResetTimeFor(event.mapid,event.difficulty); + _ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, resetTime - now); if(event.type != 4) { // schedule the next warning/reset @@ -580,29 +600,28 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId) else sObjectMgr.DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded } -void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLeft) +void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeLeft) { // global reset for all instances of the given map - // note: this isn't fast but it's meant to be executed very rarely - Map const *map = sMapMgr.CreateBaseMap(mapid); - if(!map->Instanceable()) + MapEntry const *mapEntry = sMapStore.LookupEntry(mapid); + if (!mapEntry->Instanceable()) return; + uint64 now = (uint64)time(NULL); - if(!warn) + if (!warn) { - // this is called one minute before the reset time - InstanceTemplate const* temp = ObjectMgr::GetInstanceTemplate(mapid); - if(!temp || !temp->reset_delay) + MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty); + if (!mapDiff || !mapDiff->resetTime) { - sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid); + sLog.outError("InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d", mapid); return; } // remove all binds to instances of the given map for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();) { - if(itr->second->GetMapId() == mapid) + if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) _ResetSave(itr); else ++itr; @@ -617,12 +636,14 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe // calculate the next reset time uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; - uint32 period = temp->reset_delay * DAY; + uint32 period = mapDiff->resetTime * DAY; uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff; // update it in the DB - CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d'", next_reset, mapid); + CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%d' AND difficulty = '%d'", next_reset, mapid, difficulty); } + // note: this isn't fast but it's meant to be executed very rarely + Map const *map = sMapMgr.CreateBaseMap(mapid); // _not_ include difficulty MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps(); MapInstanced::InstancedMaps::iterator mitr; for(mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr) diff --git a/src/game/InstanceSaveMgr.h b/src/game/InstanceSaveMgr.h index c080fd5da..f457fe3de 100644 --- a/src/game/InstanceSaveMgr.h +++ b/src/game/InstanceSaveMgr.h @@ -118,28 +118,39 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton InstanceSaveMap; typedef UNORDERED_MAP InstanceSaveHashMap; - typedef std::map InstanceSaveMapMap; + typedef UNORDERED_MAP InstanceSaveMapMap; /* resetTime is a global propery of each (raid/heroic) map all instances of that map reset at the same time */ struct InstResetEvent { uint8 type; + Difficulty difficulty:8; uint16 mapid; uint16 instanceId; - InstResetEvent(uint8 t = 0, uint16 m = 0, uint16 i = 0) : type(t), mapid(m), instanceId(i) {} + + InstResetEvent() : type(0), difficulty(DUNGEON_DIFFICULTY_NORMAL), mapid(0), instanceId(0) {} + InstResetEvent(uint8 t, uint32 _mapid, Difficulty d, uint16 _instanceid) + : type(t), difficulty(d), mapid(_mapid), instanceId(_instanceid) {} bool operator == (const InstResetEvent& e) { return e.instanceId == instanceId; } }; typedef std::multimap ResetTimeQueue; - typedef std::vector ResetTimeVector; + typedef UNORDERED_MAP ResetTimeByMapDifficultyMap; void CleanupInstances(); void PackInstances(); void LoadResetTimes(); - time_t GetResetTimeFor(uint32 mapid) { return m_resetTimeByMapId[mapid]; } + time_t GetResetTimeFor(uint32 mapid, Difficulty d) const + { + ResetTimeByMapDifficultyMap::const_iterator itr = m_resetTimeByMapDifficulty.find(MAKE_PAIR32(mapid,d)); + return itr != m_resetTimeByMapDifficulty.end() ? itr->second : 0; + } + void SetResetTimeFor(uint32 mapid, Difficulty d, time_t t) + { + m_resetTimeByMapDifficulty[MAKE_PAIR32(mapid,d)] = t; + } void ScheduleReset(bool add, time_t time, InstResetEvent event); void Update(); @@ -156,7 +167,7 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::SingletonGetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), GetInstanceId())); + else sInstanceSaveMgr.ScheduleReset(on, save->GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), Difficulty(GetSpawnMode()), GetInstanceId())); } } +MapDifficulty const* InstanceMap::GetMapDifficulty() const +{ + return GetMapDifficultyData(GetId(),GetDifficulty()); +} + uint32 InstanceMap::GetMaxPlayers() const { - InstanceTemplate const* iTemplate = ObjectMgr::GetInstanceTemplate(GetId()); - if(!iTemplate) - return 0; - return IsHeroic() ? iTemplate->maxPlayersHeroic : iTemplate->maxPlayers; + MapDifficulty const* mapDiff = GetMapDifficulty(); + return mapDiff ? mapDiff->maxPlayers : 0; } +uint32 InstanceMap::GetMaxResetDelay() const +{ + MapDifficulty const* mapDiff = GetMapDifficulty(); + return mapDiff ? mapDiff->resetTime : 0; +} + + /* ******* Battleground Instance Maps ******* */ BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent, uint8 spawnMode) @@ -3560,4 +3570,3 @@ uint32 Map::GenerateLocalLowGuid(HighGuid guidhigh) ASSERT(0); return 0; } - diff --git a/src/game/Map.h b/src/game/Map.h index 849efcb8b..428d182c9 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -227,9 +227,6 @@ struct InstanceTemplate uint32 parent; uint32 levelMin; uint32 levelMax; - uint32 maxPlayers; - uint32 maxPlayersHeroic; - uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset. float startLocX; float startLocY; float startLocZ; @@ -373,7 +370,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); } bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); } - bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; } + bool IsRaidOrHeroicDungeon() const { return IsRaid() || i_spawnMode > DUNGEON_DIFFICULTY_NORMAL; } bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); } bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); } @@ -599,7 +596,12 @@ class MANGOS_DLL_SPEC InstanceMap : public Map bool CanEnter(Player* player); void SendResetWarnings(uint32 timeLeft) const; void SetResetSchedule(bool on); + + // have meaning only for instanced map (that have set real difficulty) + Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); } uint32 GetMaxPlayers() const; + uint32 GetMaxResetDelay() const; + MapDifficulty const* GetMapDifficulty() const; virtual void InitVisibilityDistance(); private: diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 99f8abc12..5853824ef 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -141,20 +141,13 @@ void WorldSession::HandleMoveWorldportAckOpcode() } } - if (mInstance) + if (mInstance && mEntry->IsDungeon()) { - if(mEntry->IsRaid()) + Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); + if (uint32 timeReset = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()->GetMapId(),diff)) { - uint32 timeleft = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); - GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), GetPlayer()->GetRaidDifficulty(), timeleft); - } - else if(mEntry->IsNonRaidDungeon() && GetPlayer()->GetDungeonDifficulty() > DUNGEON_DIFFICULTY_NORMAL) - { - if(MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID,GetPlayer()->GetDungeonDifficulty())) - { - uint32 timeleft = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); - GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), GetPlayer()->GetDungeonDifficulty(), timeleft); - } + uint32 timeleft = timeReset - time(NULL); + GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), diff, timeleft); } } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 11b577fdd..b466f121e 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -4593,42 +4593,14 @@ void ObjectMgr::LoadInstanceTemplate() if(!temp) continue; - const MapEntry* entry = sMapStore.LookupEntry(temp->map); - if(!entry) - { + if(!MapManager::IsValidMAP(temp->map)) sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!", temp->map); - continue; - } - //FIXME: now exist heroic instance, normal/heroic raid instances - // entry->resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid) - // entry->resetTimeRaid store reset time for normal raid only - // for current state entry->resetTimeRaid == entry->resetTimeHeroic in case raid instances with heroic mode. - // but at some point wee need implement reset time dependent from raid instance mode - if(temp->reset_delay == 0) + if(!MapManager::IsValidMapCoord(temp->parent,temp->startLocX,temp->startLocY,temp->startLocZ,temp->startLocO)) { - MapDifficulty const* mapDiffNorm = GetMapDifficultyData(temp->map,DUNGEON_DIFFICULTY_NORMAL); - MapDifficulty const* mapDiffHeroic = GetMapDifficultyData(temp->map,DUNGEON_DIFFICULTY_HEROIC); - - // no reset time - if ((!mapDiffNorm || mapDiffNorm->resetTime == 0) && - (!mapDiffHeroic || mapDiffHeroic->resetTime == 0)) - continue; - - // use defaults from the DBC - if(mapDiffHeroic && mapDiffHeroic->resetTime) // for both raid and non raids, read above - { - temp->reset_delay = mapDiffHeroic->resetTime / DAY; - } - else if (mapDiffNorm && mapDiffNorm->resetTime && entry->map_type == MAP_RAID) - // for normal raid only - { - temp->reset_delay = mapDiffNorm->resetTime / DAY; - } + sLog.outErrorDb("ObjectMgr::LoadInstanceTemplate: bad parent entrance coordinates for map id %d template!", temp->map); + temp->parent = 0; // will have wrong continent 0 parent, at least existed } - - // the reset_delay must be at least one day - temp->reset_delay = std::max((uint32)1, (uint32)(temp->reset_delay * sWorld.getRate(RATE_INSTANCE_RESET_TIME))); } sLog.outString( ">> Loaded %u Instance Template definitions", sInstanceTemplate.RecordCount ); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index a1cb8d774..4294cb87e 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2319,7 +2319,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { if (m_target->GetMap()->IsDungeon()) { - uint32 spellId = m_target->GetMap()->IsHeroic() ? 46163 : 44190; + uint32 spellId = ((InstanceMap*)m_target->GetMap())->GetDifficulty() == DIFFICULTY_DEFAULT ? 44190 : 46163; m_target->CastSpell(m_target, spellId, true, NULL, this); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 03e4dbefe..f08534bcf 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -683,7 +683,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if(m->IsDungeon() && creditedPlayer) { - if(m->IsRaid() || m->IsHeroic()) + if (m->IsRaidOrHeroicDungeon()) { if(cVictim->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) ((InstanceMap *)m)->PermBindAllPlayers(creditedPlayer); diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index e48f45cf9..0a16e71e0 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -36,8 +36,8 @@ const char GameObjectInfodstfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiisiiii"; const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiii"; const char PageTextfmt[]="isi"; -const char InstanceTemplatesrcfmt[]="iiiiiiiffffs"; -const char InstanceTemplatedstfmt[]="iiiiiiiffffi"; +const char InstanceTemplatesrcfmt[]="iiiiffffs"; +const char InstanceTemplatedstfmt[]="iiiiffffi"; SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template"); SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon"); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b62b615b2..14a833449 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 "8827" + #define REVISION_NR "8828" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 968f55826..bec923d2d 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ - #define REVISION_DB_CHARACTERS "required_8721_01_characters_guild" - #define REVISION_DB_MANGOS "required_8818_01_mangos_mangos_string" + #define REVISION_DB_CHARACTERS "required_8828_01_characters_instance_reset" + #define REVISION_DB_MANGOS "required_8828_02_mangos_instance_template" #define REVISION_DB_REALMD "required_8728_01_realmd_account" #endif // __REVISION_SQL_H__