<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>sql/updates/8828_01_characters_instance_reset.sql</filename>
    </added>
    <added>
      <filename>sql/updates/8828_02_mangos_instance_template.sql</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -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>
      <filename>sql/characters.sql</filename>
    </modified>
    <modified>
      <diff>@@ -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>
      <filename>sql/mangos.sql</filename>
    </modified>
    <modified>
      <diff>@@ -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>
      <filename>sql/updates/Makefile.am</filename>
    </modified>
    <modified>
      <diff>@@ -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 &lt;&lt; DIFFICULTY_DEFAULT),// any any maps without spawn modes
 
     SPAWNMASK_DUNGEON_NORMAL    = (1 &lt;&lt; DUNGEON_DIFFICULTY_NORMAL),
     SPAWNMASK_DUNGEON_HEROIC    = (1 &lt;&lt; DUNGEON_DIFFICULTY_HEROIC),</diff>
      <filename>src/game/DBCEnums.h</filename>
    </modified>
    <modified>
      <diff>@@ -100,7 +100,6 @@ DBCStorage &lt;MapEntry&gt; sMapStore(MapEntryfmt);
 
 // DBC used only for initialization sMapDifficultyMap at startup.
 DBCStorage &lt;MapDifficultyEntry&gt; sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading
-typedef std::map&lt;uint32/*pair32(map,diff)*/,MapDifficulty&gt; MapDifficultyMap;
 MapDifficultyMap sMapDifficultyMap;
 
 DBCStorage &lt;MovieEntry&gt; sMovieStore(MovieEntryfmt);</diff>
      <filename>src/game/DBCStores.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -55,6 +55,7 @@ bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredT
 void Zone2MapCoordinates(float&amp; x,float&amp; y,uint32 zone);
 void Map2ZoneCoordinates(float&amp; x,float&amp; y,uint32 zone);
 
+typedef std::map&lt;uint32/*pair32(map,diff)*/,MapDifficulty&gt; MapDifficultyMap;
 MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
 
 uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls);
@@ -113,6 +114,7 @@ extern DBCStorage &lt;LockEntry&gt;                    sLockStore;
 extern DBCStorage &lt;MailTemplateEntry&gt;            sMailTemplateStore;
 extern DBCStorage &lt;MapEntry&gt;                     sMapStore;
 //extern DBCStorage &lt;MapDifficultyEntry&gt;           sMapDifficultyStore; -- use GetMapDifficultyData insteed
+extern MapDifficultyMap                          sMapDifficultyMap;
 extern DBCStorage &lt;MovieEntry&gt;                   sMovieStore;
 extern DBCStorage &lt;QuestSortEntry&gt;               sQuestSortStore;
 extern DBCStorage &lt;RandomPropertiesPointsEntry&gt;  sRandomPropertiesPointsStore;</diff>
      <filename>src/game/DBCStores.h</filename>
    </modified>
    <modified>
      <diff>@@ -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-&gt;map_type == MAP_RAID || difficulty == DUNGEON_DIFFICULTY_HEROIC)
-            resetTime = GetResetTimeFor(mapId);
+        if(entry-&gt;map_type == MAP_RAID || difficulty &gt; 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&lt;uint32, std::pair&lt;uint32, time_t&gt; &gt; ResetTimeMapType;
-    ResetTimeMapType InstResetTime;
-    QueryResult *result = CharacterDatabase.Query(&quot;SELECT id, map, resettime FROM instance WHERE resettime &gt; 0&quot;);
+    typedef std::pair&lt;uint32 /*PAIR32(map,difficulty)*/, time_t&gt; ResetTimeMapDiffType;
+    typedef std::map&lt;uint32, ResetTimeMapDiffType&gt; InstResetTimeMapDiffType;
+    InstResetTimeMapDiffType instResetTime;
+
+    // index instance ids by map/difficulty pairs for fast reset warning send
+    typedef std::multimap&lt;uint32 /*PAIR32(map,difficulty)*/, uint32 /*instanceid*/ &gt; ResetTimeMapDiffInstances;
+    ResetTimeMapDiffInstances mapDiffResetInstances;
+
+    QueryResult *result = CharacterDatabase.Query(&quot;SELECT id, map, difficulty, resettime FROM instance WHERE resettime &gt; 0&quot;);
     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&lt;uint32, uint64&gt;(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-&gt;NextRow());
@@ -404,8 +412,8 @@ void InstanceSaveManager::LoadResetTimes()
                 Field *fields = result-&gt;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() &amp;&amp; itr-&gt;second.second != resettime)
+                InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance);
+                if(itr != instResetTime.end() &amp;&amp; itr-&gt;second.second != resettime)
                 {
                     CharacterDatabase.DirectPExecute(&quot;UPDATE instance SET resettime = '&quot;UI64FMTD&quot;' WHERE id = '%u'&quot;, uint64(resettime), instance);
                     itr-&gt;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-&gt;second.second &gt; now)
-                ScheduleReset(true, itr-&gt;second.second, InstResetEvent(0, itr-&gt;second.first, itr-&gt;first));
+                ScheduleReset(true, itr-&gt;second.second, InstResetEvent(0, PAIR32_LOPART(itr-&gt;second.first),Difficulty(PAIR32_HIPART(itr-&gt;second.first)),itr-&gt;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(&quot;SELECT mapid, resettime FROM instance_reset&quot;);
+    result = CharacterDatabase.Query(&quot;SELECT mapid, difficulty, resettime FROM instance_reset&quot;);
     if(result)
     {
         do
         {
             Field *fields = result-&gt;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(&quot;InstanceSaveManager::LoadResetTimes: invalid mapid %u in instance_reset!&quot;, mapid);
-                CharacterDatabase.DirectPExecute(&quot;DELETE FROM instance_reset WHERE mapid = '%u'&quot;, mapid);
+                sLog.outError(&quot;InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!&quot;, mapid, difficulty);
+                CharacterDatabase.DirectPExecute(&quot;DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'&quot;, 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(&quot;UPDATE instance_reset SET resettime = '&quot;UI64FMTD&quot;' WHERE mapid = '%u'&quot;, newresettime, mapid);
+                CharacterDatabase.DirectPExecute(&quot;UPDATE instance_reset SET resettime = '&quot;UI64FMTD&quot;' WHERE mapid = '%u' AND difficulty = '%u'&quot;, newresettime, mapid, difficulty);
 
-            m_resetTimeByMapId[mapid] = newresettime;
+            SetResetTimeFor(mapid,difficulty,newresettime);
         } while(result-&gt;NextRow());
         delete result;
     }
 
     // clean expired instances, references to them will be deleted in CleanupInstances
     // must be done before calculating new reset times
-    _DelHelper(CharacterDatabase, &quot;id, map, difficulty&quot;, &quot;instance&quot;, &quot;LEFT JOIN instance_reset ON mapid = map WHERE (instance.resettime &lt; '&quot;UI64FMTD&quot;' AND instance.resettime &gt; '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime &lt; '&quot;UI64FMTD&quot;')&quot;,  (uint64)now, (uint64)now);
+    _DelHelper(CharacterDatabase, &quot;id, map, instance.difficulty&quot;, &quot;instance&quot;, &quot;LEFT JOIN instance_reset ON mapid = map AND instance.difficulty =  instance_reset.difficulty WHERE (instance.resettime &lt; '&quot;UI64FMTD&quot;' AND instance.resettime &gt; '0') OR (NOT instance_reset.resettime IS NULL AND instance_reset.resettime &lt; '&quot;UI64FMTD&quot;')&quot;,  (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 &lt; sInstanceTemplate.MaxEntry; i++)
+    for(MapDifficultyMap::const_iterator itr = sMapDifficultyMap.begin(); itr != sMapDifficultyMap.end(); ++itr)
     {
-        InstanceTemplate const* temp = ObjectMgr::GetInstanceTemplate(i);
-        if(!temp || temp-&gt;reset_delay == 0)
+        uint32 map_diff_pair = itr-&gt;first;
+        uint32 mapid = PAIR32_LOPART(map_diff_pair);
+        Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair));
+        MapDifficulty const* mapDiff = &amp;itr-&gt;second;
+        if (!mapDiff-&gt;resetTime)
             continue;
 
-        uint32 period = temp-&gt;reset_delay * DAY;
-        assert(period != 0);
-        time_t t = m_resetTimeByMapId[temp-&gt;map];
+        // the reset_delay must be at least one day
+        uint32 period =  (mapDiff-&gt;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(&quot;INSERT INTO instance_reset VALUES ('%u','&quot;UI64FMTD&quot;')&quot;, i, (uint64)t);
+            CharacterDatabase.DirectPExecute(&quot;INSERT INTO instance_reset VALUES ('%u','%u','&quot;UI64FMTD&quot;')&quot;, mapid, difficulty, (uint64)t);
         }
 
         if(t &lt; 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(&quot;UPDATE instance_reset SET resettime = '&quot;UI64FMTD&quot;' WHERE mapid = '%u'&quot;, (uint64)t, i);
+            CharacterDatabase.DirectPExecute(&quot;UPDATE instance_reset SET resettime = '&quot;UI64FMTD&quot;' WHERE mapid = '%u' AND difficulty= '%u'&quot;, (uint64)t, mapid, difficulty);
         }
 
-        m_resetTimeByMapId[temp-&gt;map] = t;
+        SetResetTimeFor(mapid,difficulty,t);
 
         // schedule the global reset/warning
         uint8 type = 1;
         static int tim[4] = {3600, 900, 300, 60};
         for(; type &lt; 4; type++)
-            if(t - tim[type-1] &gt; now) break;
-        ScheduleReset(true, t - tim[type-1], InstResetEvent(type, i));
+            if(t - tim[type-1] &gt; 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-&gt;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-&gt;Instanceable())
+    MapEntry const *mapEntry = sMapStore.LookupEntry(mapid);
+    if (!mapEntry-&gt;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-&gt;reset_delay)
+        MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
+        if (!mapDiff || !mapDiff-&gt;resetTime)
         {
-            sLog.outError(&quot;InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d&quot;, mapid);
+            sLog.outError(&quot;InstanceSaveManager::ResetOrWarnAll: not valid difficulty or no reset delay for map %d&quot;, mapid);
             return;
         }
 
         // remove all binds to instances of the given map
         for(InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();)
         {
-            if(itr-&gt;second-&gt;GetMapId() == mapid)
+            if (itr-&gt;second-&gt;GetMapId() == mapid &amp;&amp; itr-&gt;second-&gt;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-&gt;reset_delay * DAY;
+        uint32 period = mapDiff-&gt;resetTime * DAY;
         uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff;
         // update it in the DB
-        CharacterDatabase.PExecute(&quot;UPDATE instance_reset SET resettime = '&quot;UI64FMTD&quot;' WHERE mapid = '%d'&quot;, next_reset, mapid);
+        CharacterDatabase.PExecute(&quot;UPDATE instance_reset SET resettime = '&quot;UI64FMTD&quot;' WHERE mapid = '%d' AND difficulty = '%d'&quot;, 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 &amp;instMaps = ((MapInstanced*)map)-&gt;GetInstancedMaps();
     MapInstanced::InstancedMaps::iterator mitr;
     for(mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)</diff>
      <filename>src/game/InstanceSaveMgr.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -118,28 +118,39 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton&lt;InstanceSav
         InstanceSaveManager();
         ~InstanceSaveManager();
 
-        typedef std::map&lt;uint32 /*InstanceId*/, InstanceSave*&gt; InstanceSaveMap;
         typedef UNORDERED_MAP&lt;uint32 /*InstanceId*/, InstanceSave*&gt; InstanceSaveHashMap;
-        typedef std::map&lt;uint32 /*mapId*/, InstanceSaveMap&gt; InstanceSaveMapMap;
+        typedef UNORDERED_MAP&lt;uint32 /*mapId*/, InstanceSaveHashMap&gt; 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&amp; e) { return e.instanceId == instanceId; }
         };
         typedef std::multimap&lt;time_t /*resetTime*/, InstResetEvent&gt; ResetTimeQueue;
-        typedef std::vector&lt;time_t /*resetTime*/&gt; ResetTimeVector;
+        typedef UNORDERED_MAP&lt;uint32 /*PAIR32(map,difficulty)*/,time_t /*resetTime*/&gt; 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-&gt;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::Singleton&lt;InstanceSav
         uint32 GetNumBoundGroupsTotal();
 
     private:
-        void _ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeleft);
+        void _ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeleft);
         void _ResetInstance(uint32 mapid, uint32 instanceId);
         void _ResetSave(InstanceSaveHashMap::iterator &amp;itr);
         void _DelHelper(DatabaseType &amp;db, const char *fields, const char *table, const char *queryTail,...);
@@ -164,8 +175,8 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton&lt;InstanceSav
         bool lock_instLists;
         // fast lookup by instance id
         InstanceSaveHashMap m_instanceSaveById;
-        // fast lookup for reset times
-        ResetTimeVector m_resetTimeByMapId;
+        // fast lookup for reset times (always use existed functions for access/set)
+        ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty;
         ResetTimeQueue m_resetTimeQueue;
 };
 </diff>
      <filename>src/game/InstanceSaveMgr.h</filename>
    </modified>
    <modified>
      <diff>@@ -2610,22 +2610,32 @@ void InstanceMap::SetResetSchedule(bool on)
     // only for normal instances
     // the reset time is only scheduled when there are no payers inside
     // it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
-    if(IsDungeon() &amp;&amp; !HavePlayers() &amp;&amp; !IsRaid() &amp;&amp; !IsHeroic())
+    if(IsDungeon() &amp;&amp; !HavePlayers() &amp;&amp; !IsRaidOrHeroicDungeon())
     {
         InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
         if(!save) sLog.outError(&quot;InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d&quot;, on ? &quot;on&quot; : &quot;off&quot;, GetInstanceId(), GetId());
-        else sInstanceSaveMgr.ScheduleReset(on, save-&gt;GetResetTime(), InstanceSaveManager::InstResetEvent(0, GetId(), GetInstanceId()));
+        else sInstanceSaveMgr.ScheduleReset(on, save-&gt;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-&gt;maxPlayersHeroic : iTemplate-&gt;maxPlayers;
+    MapDifficulty const* mapDiff = GetMapDifficulty();
+    return mapDiff ? mapDiff-&gt;maxPlayers : 0;
 }
 
+uint32 InstanceMap::GetMaxResetDelay() const
+{
+    MapDifficulty const* mapDiff = GetMapDifficulty();
+    return mapDiff ? mapDiff-&gt;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>
      <filename>src/game/Map.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -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&lt;NGridType&gt;, 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 &amp;&amp; i_mapEntry-&gt;IsDungeon(); }
         bool IsRaid() const { return i_mapEntry &amp;&amp; i_mapEntry-&gt;IsRaid(); }
-        bool IsHeroic() const { return IsRaid() ? i_spawnMode &gt;= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode &gt;= DUNGEON_DIFFICULTY_HEROIC; }
+        bool IsRaidOrHeroicDungeon() const { return IsRaid() || i_spawnMode &gt; DUNGEON_DIFFICULTY_NORMAL; }
         bool IsBattleGround() const { return i_mapEntry &amp;&amp; i_mapEntry-&gt;IsBattleGround(); }
         bool IsBattleArena() const { return i_mapEntry &amp;&amp; i_mapEntry-&gt;IsBattleArena(); }
         bool IsBattleGroundOrArena() const { return i_mapEntry &amp;&amp; i_mapEntry-&gt;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>
      <filename>src/game/Map.h</filename>
    </modified>
    <modified>
      <diff>@@ -141,20 +141,13 @@ void WorldSession::HandleMoveWorldportAckOpcode()
         }
     }
 
-    if (mInstance)
+    if (mInstance &amp;&amp; mEntry-&gt;IsDungeon())
     {
-        if(mEntry-&gt;IsRaid())
+        Difficulty diff = GetPlayer()-&gt;GetDifficulty(mEntry-&gt;IsRaid());
+        if (uint32 timeReset = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()-&gt;GetMapId(),diff))
         {
-            uint32 timeleft = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()-&gt;GetMapId()) - time(NULL);
-            GetPlayer()-&gt;SendInstanceResetWarning(GetPlayer()-&gt;GetMapId(), GetPlayer()-&gt;GetRaidDifficulty(), timeleft);
-        }
-        else if(mEntry-&gt;IsNonRaidDungeon() &amp;&amp; GetPlayer()-&gt;GetDungeonDifficulty() &gt; DUNGEON_DIFFICULTY_NORMAL)
-        {
-            if(MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry-&gt;MapID,GetPlayer()-&gt;GetDungeonDifficulty()))
-            {
-                uint32 timeleft = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()-&gt;GetMapId()) - time(NULL);
-                GetPlayer()-&gt;SendInstanceResetWarning(GetPlayer()-&gt;GetMapId(), GetPlayer()-&gt;GetDungeonDifficulty(), timeleft);
-            }
+            uint32 timeleft = timeReset - time(NULL);
+            GetPlayer()-&gt;SendInstanceResetWarning(GetPlayer()-&gt;GetMapId(), diff, timeleft);
         }
     }
 </diff>
      <filename>src/game/MovementHandler.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -4593,42 +4593,14 @@ void ObjectMgr::LoadInstanceTemplate()
         if(!temp)
             continue;
 
-        const MapEntry* entry = sMapStore.LookupEntry(temp-&gt;map);
-        if(!entry)
-        {
+        if(!MapManager::IsValidMAP(temp-&gt;map))
             sLog.outErrorDb(&quot;ObjectMgr::LoadInstanceTemplate: bad mapid %d for template!&quot;, temp-&gt;map);
-            continue;
-        }
 
-        //FIXME: now exist heroic instance, normal/heroic raid instances
-        // entry-&gt;resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid)
-        // entry-&gt;resetTimeRaid   store reset time for normal raid only
-        // for current state  entry-&gt;resetTimeRaid == entry-&gt;resetTimeHeroic in case raid instances with heroic mode.
-        // but at some point wee need implement reset time dependent from raid instance mode
-        if(temp-&gt;reset_delay == 0)
+        if(!MapManager::IsValidMapCoord(temp-&gt;parent,temp-&gt;startLocX,temp-&gt;startLocY,temp-&gt;startLocZ,temp-&gt;startLocO))
         {
-            MapDifficulty const* mapDiffNorm   = GetMapDifficultyData(temp-&gt;map,DUNGEON_DIFFICULTY_NORMAL);
-            MapDifficulty const* mapDiffHeroic = GetMapDifficultyData(temp-&gt;map,DUNGEON_DIFFICULTY_HEROIC);
-
-            // no reset time
-            if ((!mapDiffNorm || mapDiffNorm-&gt;resetTime == 0) &amp;&amp;
-                (!mapDiffHeroic || mapDiffHeroic-&gt;resetTime == 0))
-                continue;
-
-            // use defaults from the DBC
-            if(mapDiffHeroic &amp;&amp; mapDiffHeroic-&gt;resetTime)   // for both raid and non raids, read above
-            {
-                temp-&gt;reset_delay = mapDiffHeroic-&gt;resetTime / DAY;
-            }
-            else if (mapDiffNorm &amp;&amp; mapDiffNorm-&gt;resetTime &amp;&amp; entry-&gt;map_type == MAP_RAID)
-                                                            // for normal raid only
-            {
-                temp-&gt;reset_delay = mapDiffNorm-&gt;resetTime / DAY;
-            }
+            sLog.outErrorDb(&quot;ObjectMgr::LoadInstanceTemplate: bad parent entrance coordinates for map id %d template!&quot;, temp-&gt;map);
+            temp-&gt;parent = 0;                               // will have wrong continent 0 parent, at least existed
         }
-
-        // the reset_delay must be at least one day
-        temp-&gt;reset_delay = std::max((uint32)1, (uint32)(temp-&gt;reset_delay * sWorld.getRate(RATE_INSTANCE_RESET_TIME)));
     }
 
     sLog.outString( &quot;&gt;&gt; Loaded %u Instance Template definitions&quot;, sInstanceTemplate.RecordCount );</diff>
      <filename>src/game/ObjectMgr.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -2319,7 +2319,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
             {
                 if (m_target-&gt;GetMap()-&gt;IsDungeon())
                 {
-                    uint32 spellId = m_target-&gt;GetMap()-&gt;IsHeroic() ? 46163 : 44190;
+                    uint32 spellId = ((InstanceMap*)m_target-&gt;GetMap())-&gt;GetDifficulty() == DIFFICULTY_DEFAULT ? 44190 : 46163;
 
                     m_target-&gt;CastSpell(m_target, spellId, true, NULL, this);
                 }</diff>
      <filename>src/game/SpellAuras.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -683,7 +683,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
 
                 if(m-&gt;IsDungeon() &amp;&amp; creditedPlayer)
                 {
-                    if(m-&gt;IsRaid() || m-&gt;IsHeroic())
+                    if (m-&gt;IsRaidOrHeroicDungeon())
                     {
                         if(cVictim-&gt;GetCreatureInfo()-&gt;flags_extra &amp; CREATURE_FLAG_EXTRA_INSTANCE_BIND)
                             ((InstanceMap *)m)-&gt;PermBindAllPlayers(creditedPlayer);</diff>
      <filename>src/game/Unit.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -36,8 +36,8 @@ const char GameObjectInfodstfmt[]=&quot;iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii&quot;;
 const char ItemPrototypesrcfmt[]=&quot;iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiisiiii&quot;;
 const char ItemPrototypedstfmt[]=&quot;iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiii&quot;;
 const char PageTextfmt[]=&quot;isi&quot;;
-const char InstanceTemplatesrcfmt[]=&quot;iiiiiiiffffs&quot;;
-const char InstanceTemplatedstfmt[]=&quot;iiiiiiiffffi&quot;;
+const char InstanceTemplatesrcfmt[]=&quot;iiiiffffs&quot;;
+const char InstanceTemplatedstfmt[]=&quot;iiiiffffi&quot;;
 
 SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, &quot;entry&quot;,&quot;creature_template&quot;);
 SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,&quot;guid&quot;,&quot;creature_addon&quot;);</diff>
      <filename>src/shared/Database/SQLStorage.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
 #ifndef __REVISION_NR_H__
 #define __REVISION_NR_H__
- #define REVISION_NR &quot;8827&quot;
+ #define REVISION_NR &quot;8828&quot;
 #endif // __REVISION_NR_H__</diff>
      <filename>src/shared/revision_nr.h</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 #ifndef __REVISION_SQL_H__
 #define __REVISION_SQL_H__
- #define REVISION_DB_CHARACTERS &quot;required_8721_01_characters_guild&quot;
- #define REVISION_DB_MANGOS &quot;required_8818_01_mangos_mangos_string&quot;
+ #define REVISION_DB_CHARACTERS &quot;required_8828_01_characters_instance_reset&quot;
+ #define REVISION_DB_MANGOS &quot;required_8828_02_mangos_instance_template&quot;
  #define REVISION_DB_REALMD &quot;required_8728_01_realmd_account&quot;
 #endif // __REVISION_SQL_H__</diff>
      <filename>src/shared/revision_sql.h</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>40513638ad932545f3cde7cf100e7e4b41676def</id>
    </parent>
  </parents>
  <author>
    <name>VladimirMangos</name>
    <login></login>
    <email>vladimir@getmangos.com</email>
  </author>
  <url>http://github.com/mangos/mangos/commit/b5f81e5011c5c930c827b068284d305f4983e2a0</url>
  <id>b5f81e5011c5c930c827b068284d305f4983e2a0</id>
  <committed-date>2009-11-17T23:08:41-08:00</committed-date>
  <authored-date>2009-11-17T22:58:10-08:00</authored-date>
  <message>[8828] Independent instance reset time for different difficulties.

* Store reset time for map/difficulty pairs.
* Use DBC data for reset time and max players instead `instance_template` fields (dropped)
  for each existed map/difficulty pair.
* Fix some &quot;heroic&quot; related checks in spells/etc.</message>
  <tree>2ec6c97a2b40bc87e73282a0b23c8dd136383ac2</tree>
  <committer>
    <name>VladimirMangos</name>
    <login></login>
    <email>vladimir@getmangos.com</email>
  </committer>
</commit>
