mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[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 "heroic" related checks in spells/etc.
This commit is contained in:
parent
70fb82b262
commit
37ba6623bb
19 changed files with 149 additions and 124 deletions
|
|
@ -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;
|
||||
|
||||
--
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
6
sql/updates/8828_01_characters_instance_reset.sql
Normal file
6
sql/updates/8828_01_characters_instance_reset.sql
Normal file
|
|
@ -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`);
|
||||
6
sql/updates/8828_02_mangos_instance_template.sql
Normal file
6
sql/updates/8828_02_mangos_instance_template.sql
Normal file
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ DBCStorage <MapEntry> sMapStore(MapEntryfmt);
|
|||
|
||||
// DBC used only for initialization sMapDifficultyMap at startup.
|
||||
DBCStorage <MapDifficultyEntry> sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading
|
||||
typedef std::map<uint32/*pair32(map,diff)*/,MapDifficulty> MapDifficultyMap;
|
||||
MapDifficultyMap sMapDifficultyMap;
|
||||
|
||||
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
|
||||
|
|
|
|||
|
|
@ -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<uint32/*pair32(map,diff)*/,MapDifficulty> MapDifficultyMap;
|
||||
MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
|
||||
|
||||
uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls);
|
||||
|
|
@ -113,6 +114,7 @@ extern DBCStorage <LockEntry> sLockStore;
|
|||
extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
|
||||
extern DBCStorage <MapEntry> sMapStore;
|
||||
//extern DBCStorage <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed
|
||||
extern MapDifficultyMap sMapDifficultyMap;
|
||||
extern DBCStorage <MovieEntry> sMovieStore;
|
||||
extern DBCStorage <QuestSortEntry> sQuestSortStore;
|
||||
extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore;
|
||||
|
|
|
|||
|
|
@ -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<uint32, std::pair<uint32, time_t> > ResetTimeMapType;
|
||||
ResetTimeMapType InstResetTime;
|
||||
QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0");
|
||||
typedef std::pair<uint32 /*PAIR32(map,difficulty)*/, time_t> ResetTimeMapDiffType;
|
||||
typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType;
|
||||
InstResetTimeMapDiffType instResetTime;
|
||||
|
||||
// index instance ids by map/difficulty pairs for fast reset warning send
|
||||
typedef std::multimap<uint32 /*PAIR32(map,difficulty)*/, uint32 /*instanceid*/ > 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<uint32, uint64>(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)
|
||||
{
|
||||
// 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)
|
||||
|
|
|
|||
|
|
@ -118,28 +118,39 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||
InstanceSaveManager();
|
||||
~InstanceSaveManager();
|
||||
|
||||
typedef std::map<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveMap;
|
||||
typedef UNORDERED_MAP<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap;
|
||||
typedef std::map<uint32 /*mapId*/, InstanceSaveMap> InstanceSaveMapMap;
|
||||
typedef UNORDERED_MAP<uint32 /*mapId*/, InstanceSaveHashMap> 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<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue;
|
||||
typedef std::vector<time_t /*resetTime*/> ResetTimeVector;
|
||||
typedef UNORDERED_MAP<uint32 /*PAIR32(map,difficulty)*/,time_t /*resetTime*/> 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::Singleton<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 &itr);
|
||||
void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...);
|
||||
|
|
@ -164,8 +175,8 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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() && !HavePlayers() && !IsRaid() && !IsHeroic())
|
||||
if(IsDungeon() && !HavePlayers() && !IsRaidOrHeroicDungeon())
|
||||
{
|
||||
InstanceSave *save = sInstanceSaveMgr.GetInstanceSave(GetInstanceId());
|
||||
if(!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId());
|
||||
else sInstanceSaveMgr.ScheduleReset(on, save->GetResetTime(), 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<NGridType>, 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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
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
|
||||
}
|
||||
else if (mapDiffNorm && mapDiffNorm->resetTime && entry->map_type == MAP_RAID)
|
||||
// for normal raid only
|
||||
{
|
||||
temp->reset_delay = mapDiffNorm->resetTime / DAY;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 );
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8827"
|
||||
#define REVISION_NR "8828"
|
||||
#endif // __REVISION_NR_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__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue