Update InstanceSaveMgr for new instance system
--HG-- branch : trunk
This commit is contained in:
@@ -77,15 +77,27 @@ InstanceSaveManager::~InstanceSaveManager()
|
|||||||
- adding instance into manager
|
- adding instance into manager
|
||||||
- called from InstanceMap::Add, _LoadBoundInstances, LoadGroups
|
- called from InstanceMap::Add, _LoadBoundInstances, LoadGroups
|
||||||
*/
|
*/
|
||||||
InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load)
|
InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load)
|
||||||
{
|
{
|
||||||
InstanceSave *save = GetInstanceSave(instanceId);
|
if(InstanceSave *old_save = GetInstanceSave(instanceId))
|
||||||
if(save) return save;
|
return old_save;
|
||||||
|
|
||||||
const MapEntry* entry = sMapStore.LookupEntry(mapId);
|
const MapEntry* entry = sMapStore.LookupEntry(mapId);
|
||||||
if(!entry || instanceId == 0)
|
if (!entry)
|
||||||
{
|
{
|
||||||
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d!", mapId, instanceId);
|
sLog.outError("InstanceSaveManager::AddInstanceSave: wrong mapid = %d!", mapId, instanceId);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceId == 0)
|
||||||
|
{
|
||||||
|
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, wrong instanceid = %d!", mapId, instanceId);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (difficulty >= (entry->IsRaid() ? MAX_RAID_DIFFICULTY : MAX_DUNGEON_DIFFICULTY))
|
||||||
|
{
|
||||||
|
sLog.outError("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d, wrong dificalty %u!", mapId, instanceId, difficulty);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,19 +105,19 @@ InstanceSave* InstanceSaveManager::AddInstanceSave(uint32 mapId, uint32 instance
|
|||||||
{
|
{
|
||||||
// initialize reset time
|
// initialize reset time
|
||||||
// for normal instances if no creatures are killed the instance will reset in two hours
|
// for normal instances if no creatures are killed the instance will reset in two hours
|
||||||
if(entry->map_type == MAP_RAID || difficulty == DIFFICULTY_HEROIC)
|
if(entry->map_type == MAP_RAID || difficulty > DUNGEON_DIFFICULTY_NORMAL)
|
||||||
resetTime = GetResetTimeFor(mapId);
|
resetTime = GetResetTimeFor(mapId,difficulty);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resetTime = time(NULL) + 2 * HOUR;
|
resetTime = time(NULL) + 2 * HOUR;
|
||||||
// normally this will be removed soon after in InstanceMap::Add, prevent error
|
// 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sLog.outDebug("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId);
|
sLog.outDebug("InstanceSaveManager::AddInstanceSave: mapid = %d, instanceid = %d", mapId, instanceId);
|
||||||
|
|
||||||
save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
|
InstanceSave *save = new InstanceSave(mapId, instanceId, difficulty, resetTime, canReset);
|
||||||
if(!load) save->SaveToDB();
|
if(!load) save->SaveToDB();
|
||||||
|
|
||||||
m_instanceSaveById[instanceId] = save;
|
m_instanceSaveById[instanceId] = save;
|
||||||
@@ -141,7 +153,7 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset)
|
InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset)
|
||||||
: m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId),
|
: m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId),
|
||||||
m_difficulty(difficulty), m_canReset(canReset)
|
m_difficulty(difficulty), m_canReset(canReset)
|
||||||
{
|
{
|
||||||
@@ -180,7 +192,7 @@ time_t InstanceSave::GetResetTimeForDB()
|
|||||||
{
|
{
|
||||||
// only save the reset time for normal instances
|
// only save the reset time for normal instances
|
||||||
const MapEntry *entry = sMapStore.LookupEntry(GetMapId());
|
const MapEntry *entry = sMapStore.LookupEntry(GetMapId());
|
||||||
if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DIFFICULTY_HEROIC)
|
if(!entry || entry->map_type == MAP_RAID || GetDifficulty() == DUNGEON_DIFFICULTY_HEROIC)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return GetResetTime();
|
return GetResetTime();
|
||||||
@@ -402,18 +414,26 @@ void InstanceSaveManager::LoadResetTimes()
|
|||||||
// get the current reset times for normal instances (these may need to be updated)
|
// 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
|
// 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
|
// resettime = 0 in the DB for raid/heroic instances so those are skipped
|
||||||
typedef std::map<uint32, std::pair<uint32, time_t> > ResetTimeMapType;
|
typedef std::pair<uint32 /*PAIR32(map,difficulty)*/, time_t> ResetTimeMapDiffType;
|
||||||
ResetTimeMapType InstResetTime;
|
typedef std::map<uint32, ResetTimeMapDiffType> InstResetTimeMapDiffType;
|
||||||
QueryResult *result = CharacterDatabase.Query("SELECT id, map, resettime FROM instance WHERE resettime > 0");
|
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 )
|
if( result )
|
||||||
{
|
{
|
||||||
do
|
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 id = (*result)[0].GetUInt32();
|
||||||
uint32 mapid = (*result)[1].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());
|
while (result->NextRow());
|
||||||
@@ -428,8 +448,8 @@ void InstanceSaveManager::LoadResetTimes()
|
|||||||
Field *fields = result->Fetch();
|
Field *fields = result->Fetch();
|
||||||
uint32 instance = fields[1].GetUInt32();
|
uint32 instance = fields[1].GetUInt32();
|
||||||
time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR);
|
time_t resettime = time_t(fields[0].GetUInt64() + 2 * HOUR);
|
||||||
ResetTimeMapType::iterator itr = InstResetTime.find(instance);
|
InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance);
|
||||||
if(itr != InstResetTime.end() && itr->second.second != resettime)
|
if(itr != instResetTime.end() && itr->second.second != resettime)
|
||||||
{
|
{
|
||||||
CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance);
|
CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance);
|
||||||
itr->second.second = resettime;
|
itr->second.second = resettime;
|
||||||
@@ -440,62 +460,65 @@ void InstanceSaveManager::LoadResetTimes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// schedule the reset times
|
// 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)
|
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
|
// load the global respawn times for raid/heroic instances
|
||||||
uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
|
uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
|
||||||
m_resetTimeByMapId.resize(sMapStore.GetNumRows()+1);
|
result = CharacterDatabase.Query("SELECT mapid, difficulty, resettime FROM instance_reset");
|
||||||
result = CharacterDatabase.Query("SELECT mapid, resettime FROM instance_reset");
|
|
||||||
if(result)
|
if(result)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Field *fields = result->Fetch();
|
Field *fields = result->Fetch();
|
||||||
uint32 mapid = fields[0].GetUInt32();
|
uint32 mapid = fields[0].GetUInt32();
|
||||||
if(!objmgr.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);
|
sLog.outError("InstanceSaveManager::LoadResetTimes: invalid mapid(%u)/difficulty(%u) pair in instance_reset!", mapid, difficulty);
|
||||||
CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u'", mapid);
|
CharacterDatabase.DirectPExecute("DELETE FROM instance_reset WHERE mapid = '%u' AND difficulty = '%u'", mapid,difficulty);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the reset time if the hour in the configs changes
|
// update the reset time if the hour in the configs changes
|
||||||
uint64 oldresettime = fields[1].GetUInt64();
|
|
||||||
uint64 newresettime = (oldresettime / DAY) * DAY + diff;
|
uint64 newresettime = (oldresettime / DAY) * DAY + diff;
|
||||||
if(oldresettime != newresettime)
|
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());
|
} while(result->NextRow());
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean expired instances, references to them will be deleted in CleanupInstances
|
// clean expired instances, references to them will be deleted in CleanupInstances
|
||||||
// must be done before calculating new reset times
|
// 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
|
// 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
|
// 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 = objmgr.GetInstanceTemplate(i);
|
uint32 map_diff_pair = itr->first;
|
||||||
if(!temp) continue;
|
uint32 mapid = PAIR32_LOPART(map_diff_pair);
|
||||||
// only raid/heroic maps have a global reset time
|
Difficulty difficulty = Difficulty(PAIR32_HIPART(map_diff_pair));
|
||||||
const MapEntry* entry = sMapStore.LookupEntry(temp->map);
|
MapDifficulty const* mapDiff = &itr->second;
|
||||||
if(!entry || !entry->HasResetTime())
|
if (!mapDiff->resetTime)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint32 period = temp->reset_delay * DAY;
|
// the reset_delay must be at least one day
|
||||||
assert(period != 0);
|
uint32 period = (mapDiff->resetTime / DAY * sWorld.getRate(RATE_INSTANCE_RESET_TIME)) * DAY;
|
||||||
time_t t = m_resetTimeByMapId[temp->map];
|
|
||||||
|
time_t t = GetResetTimeFor(mapid,difficulty);
|
||||||
if(!t)
|
if(!t)
|
||||||
{
|
{
|
||||||
// initialize the reset time
|
// initialize the reset time
|
||||||
t = today + period + diff;
|
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)
|
if(t < now)
|
||||||
@@ -504,17 +527,23 @@ void InstanceSaveManager::LoadResetTimes()
|
|||||||
// calculate the next reset time
|
// calculate the next reset time
|
||||||
t = (t / DAY) * DAY;
|
t = (t / DAY) * DAY;
|
||||||
t += ((today - t) / period + 1) * period + diff;
|
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
|
// schedule the global reset/warning
|
||||||
uint8 type = 1;
|
uint8 type = 1;
|
||||||
static int tim[4] = {3600, 900, 300, 60};
|
static int tim[4] = {3600, 900, 300, 60};
|
||||||
for (; type < 4; type++)
|
for (; type < 4; type++)
|
||||||
if(t - tim[type-1] > now) break;
|
if(t - tim[type-1] > now)
|
||||||
ScheduleReset(true, t - tim[type-1], InstResetEvent(type, i));
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,8 +584,8 @@ void InstanceSaveManager::Update()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// global reset/warning for a certain map
|
// global reset/warning for a certain map
|
||||||
time_t resetTime = GetResetTimeFor(event.mapid);
|
time_t resetTime = GetResetTimeFor(event.mapid,event.difficulty);
|
||||||
_ResetOrWarnAll(event.mapid, event.type != 4, resetTime - now);
|
_ResetOrWarnAll(event.mapid, event.difficulty, event.type != 4, resetTime - now);
|
||||||
if(event.type != 4)
|
if(event.type != 4)
|
||||||
{
|
{
|
||||||
// schedule the next warning/reset
|
// schedule the next warning/reset
|
||||||
@@ -607,29 +636,28 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId)
|
|||||||
else objmgr.DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded
|
else objmgr.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
|
// global reset for all instances of the given map
|
||||||
// note: this isn't fast but it's meant to be executed very rarely
|
MapEntry const *mapEntry = sMapStore.LookupEntry(mapid);
|
||||||
Map const *map = MapManager::Instance().CreateBaseMap(mapid);
|
if (!mapEntry->Instanceable())
|
||||||
if(!map->Instanceable())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint64 now = (uint64)time(NULL);
|
uint64 now = (uint64)time(NULL);
|
||||||
|
|
||||||
if(!warn)
|
if(!warn)
|
||||||
{
|
{
|
||||||
// this is called one minute before the reset time
|
MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
|
||||||
InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid);
|
if (!mapDiff || !mapDiff->resetTime)
|
||||||
if(!temp || !temp->reset_delay)
|
|
||||||
{
|
{
|
||||||
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all binds to instances of the given map
|
// remove all binds to instances of the given map
|
||||||
for (InstanceSaveHashMap::iterator itr = m_instanceSaveById.begin(); itr != m_instanceSaveById.end();)
|
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);
|
_ResetSave(itr);
|
||||||
else
|
else
|
||||||
++itr;
|
++itr;
|
||||||
@@ -644,16 +672,14 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe
|
|||||||
|
|
||||||
// calculate the next reset time
|
// calculate the next reset time
|
||||||
uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR;
|
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;
|
uint64 next_reset = ((now + timeLeft + MINUTE) / DAY * DAY) + period + diff;
|
||||||
// update it in the DB
|
// 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);
|
||||||
|
|
||||||
// schedule next reset.
|
|
||||||
m_resetTimeByMapId[mapid] = (time_t) next_reset;
|
|
||||||
ScheduleReset(true, (time_t) (next_reset-3600), InstResetEvent(1, mapid));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note: this isn't fast but it's meant to be executed very rarely
|
||||||
|
Map const *map = MapManager::Instance().CreateBaseMap(mapid); // _not_ include difficulty
|
||||||
MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
|
MapInstanced::InstancedMaps &instMaps = ((MapInstanced*)map)->GetInstancedMaps();
|
||||||
MapInstanced::InstancedMaps::iterator mitr;
|
MapInstanced::InstancedMaps::iterator mitr;
|
||||||
for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
|
for (mitr = instMaps.begin(); mitr != instMaps.end(); ++mitr)
|
||||||
@@ -682,4 +708,3 @@ uint32 InstanceSaveManager::GetNumBoundGroupsTotal()
|
|||||||
ret += itr->second->GetGroupCount();
|
ret += itr->second->GetGroupCount();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+26
-14
@@ -29,6 +29,8 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include "Utilities/UnorderedMap.h"
|
#include "Utilities/UnorderedMap.h"
|
||||||
#include "Database/DatabaseEnv.h"
|
#include "Database/DatabaseEnv.h"
|
||||||
|
#include "DBCEnums.h"
|
||||||
|
#include "ObjectDefines.h"
|
||||||
|
|
||||||
struct InstanceTemplate;
|
struct InstanceTemplate;
|
||||||
struct MapEntry;
|
struct MapEntry;
|
||||||
@@ -50,7 +52,7 @@ class InstanceSave
|
|||||||
- any new instance is being generated
|
- any new instance is being generated
|
||||||
- the first time a player bound to InstanceId logs in
|
- the first time a player bound to InstanceId logs in
|
||||||
- when a group bound to the instance is loaded */
|
- when a group bound to the instance is loaded */
|
||||||
InstanceSave(uint16 MapId, uint32 InstanceId, uint8 difficulty, time_t resetTime, bool canReset);
|
InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset);
|
||||||
|
|
||||||
/* Unloaded when m_playerList and m_groupList become empty
|
/* Unloaded when m_playerList and m_groupList become empty
|
||||||
or when the instance is reset */
|
or when the instance is reset */
|
||||||
@@ -95,7 +97,7 @@ class InstanceSave
|
|||||||
|
|
||||||
/* currently it is possible to omit this information from this structure
|
/* currently it is possible to omit this information from this structure
|
||||||
but that would depend on a lot of things that can easily change in future */
|
but that would depend on a lot of things that can easily change in future */
|
||||||
uint8 GetDifficulty() { return m_difficulty; }
|
Difficulty GetDifficulty() { return m_difficulty; }
|
||||||
|
|
||||||
typedef std::list<Player*> PlayerListType;
|
typedef std::list<Player*> PlayerListType;
|
||||||
typedef std::list<Group*> GroupListType;
|
typedef std::list<Group*> GroupListType;
|
||||||
@@ -108,8 +110,8 @@ class InstanceSave
|
|||||||
GroupListType m_groupList;
|
GroupListType m_groupList;
|
||||||
time_t m_resetTime;
|
time_t m_resetTime;
|
||||||
uint32 m_instanceid;
|
uint32 m_instanceid;
|
||||||
uint16 m_mapid;
|
uint32 m_mapid;
|
||||||
uint8 m_difficulty;
|
Difficulty m_difficulty;
|
||||||
bool m_canReset;
|
bool m_canReset;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -120,33 +122,44 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||||||
InstanceSaveManager();
|
InstanceSaveManager();
|
||||||
~InstanceSaveManager();
|
~InstanceSaveManager();
|
||||||
|
|
||||||
typedef std::map<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveMap;
|
|
||||||
typedef UNORDERED_MAP<uint32 /*InstanceId*/, InstanceSave*> InstanceSaveHashMap;
|
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
|
/* resetTime is a global propery of each (raid/heroic) map
|
||||||
all instances of that map reset at the same time */
|
all instances of that map reset at the same time */
|
||||||
struct InstResetEvent
|
struct InstResetEvent
|
||||||
{
|
{
|
||||||
uint8 type;
|
uint8 type;
|
||||||
|
Difficulty difficulty:8;
|
||||||
uint16 mapid;
|
uint16 mapid;
|
||||||
uint16 instanceId;
|
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; }
|
bool operator == (const InstResetEvent& e) { return e.instanceId == instanceId; }
|
||||||
};
|
};
|
||||||
typedef std::multimap<time_t /*resetTime*/, InstResetEvent> ResetTimeQueue;
|
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 CleanupInstances();
|
||||||
void PackInstances();
|
void PackInstances();
|
||||||
|
|
||||||
void LoadResetTimes();
|
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 ScheduleReset(bool add, time_t time, InstResetEvent event);
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, uint8 difficulty, time_t resetTime, bool canReset, bool load = false);
|
InstanceSave* AddInstanceSave(uint32 mapId, uint32 instanceId, Difficulty difficulty, time_t resetTime, bool canReset, bool load = false);
|
||||||
void RemoveInstanceSave(uint32 InstanceId);
|
void RemoveInstanceSave(uint32 InstanceId);
|
||||||
static void DeleteInstanceFromDB(uint32 instanceid);
|
static void DeleteInstanceFromDB(uint32 instanceid);
|
||||||
|
|
||||||
@@ -158,7 +171,7 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||||||
uint32 GetNumBoundGroupsTotal();
|
uint32 GetNumBoundGroupsTotal();
|
||||||
|
|
||||||
private:
|
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 _ResetInstance(uint32 mapid, uint32 instanceId);
|
||||||
void _ResetSave(InstanceSaveHashMap::iterator &itr);
|
void _ResetSave(InstanceSaveHashMap::iterator &itr);
|
||||||
void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...);
|
void _DelHelper(DatabaseType &db, const char *fields, const char *table, const char *queryTail,...);
|
||||||
@@ -166,11 +179,10 @@ class MANGOS_DLL_DECL InstanceSaveManager : public MaNGOS::Singleton<InstanceSav
|
|||||||
bool lock_instLists;
|
bool lock_instLists;
|
||||||
// fast lookup by instance id
|
// fast lookup by instance id
|
||||||
InstanceSaveHashMap m_instanceSaveById;
|
InstanceSaveHashMap m_instanceSaveById;
|
||||||
// fast lookup for reset times
|
// fast lookup for reset times (always use existed functions for access/set)
|
||||||
ResetTimeVector m_resetTimeByMapId;
|
ResetTimeByMapDifficultyMap m_resetTimeByMapDifficulty;
|
||||||
ResetTimeQueue m_resetTimeQueue;
|
ResetTimeQueue m_resetTimeQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sInstanceSaveManager Trinity::Singleton<InstanceSaveManager>::Instance()
|
#define sInstanceSaveManager Trinity::Singleton<InstanceSaveManager>::Instance()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -751,15 +751,15 @@ uint32 Item::GetEnchantRequiredLevel() const
|
|||||||
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
|
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
|
||||||
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
|
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
|
||||||
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
|
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
|
||||||
if (enchantEntry->RequiredLevel > level)
|
if (enchantEntry->requiredLevel > level)
|
||||||
level = enchantEntry->RequiredLevel;
|
level = enchantEntry->requiredLevel;
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Item::IsBoundByEnchant() const
|
bool Item::IsBoundByEnchant() const
|
||||||
{
|
{
|
||||||
// Check all enchants for soulbound
|
// Check all enchants for soulbound
|
||||||
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
|
for (uint32 enchant_slot = PERM_ENCHANTMENT_SLOT; enchant_slot < MAX_ENCHANTMENT_SLOT; ++enchant_slot)
|
||||||
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
|
if (uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot)))
|
||||||
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
|
if (SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id))
|
||||||
if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND)
|
if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND)
|
||||||
|
|||||||
@@ -328,4 +328,3 @@ class TRINITY_DLL_SPEC Item : public Object
|
|||||||
bool mb_in_trade; // true if item is currently in trade-window
|
bool mb_in_trade; // true if item is currently in trade-window
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data )
|
|||||||
//sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM");
|
//sLog.outDebug("WORLD: CMSG_SWAP_INV_ITEM");
|
||||||
uint8 srcslot, dstslot;
|
uint8 srcslot, dstslot;
|
||||||
|
|
||||||
recv_data >> srcslot >> dstslot;
|
recv_data >> dstslot >> srcslot;
|
||||||
//sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
|
//sLog.outDebug("STORAGE: receive srcslot = %u, dstslot = %u", srcslot, dstslot);
|
||||||
|
|
||||||
// prevent attempt swap same item to current position generated by client at special checting sequence
|
// prevent attempt swap same item to current position generated by client at special checting sequence
|
||||||
@@ -319,6 +319,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data )
|
|||||||
data << pProto->DisplayInfoID;
|
data << pProto->DisplayInfoID;
|
||||||
data << pProto->Quality;
|
data << pProto->Quality;
|
||||||
data << pProto->Flags;
|
data << pProto->Flags;
|
||||||
|
data << pProto->Faction; // 3.2 faction?
|
||||||
data << pProto->BuyPrice;
|
data << pProto->BuyPrice;
|
||||||
data << pProto->SellPrice;
|
data << pProto->SellPrice;
|
||||||
data << pProto->InventoryType;
|
data << pProto->InventoryType;
|
||||||
@@ -947,10 +948,10 @@ void WorldSession::HandleSetAmmoOpcode(WorldPacket & recv_data)
|
|||||||
void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID)
|
void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10
|
WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 2.0.10
|
||||||
data << Target;
|
data << uint64(Target);
|
||||||
data << Caster;
|
data << uint64(Caster);
|
||||||
data << ItemID;
|
data << uint32(ItemID);
|
||||||
data << SpellID;
|
data << uint32(SpellID);
|
||||||
data << uint8(0);
|
data << uint8(0);
|
||||||
SendPacket(&data);
|
SendPacket(&data);
|
||||||
}
|
}
|
||||||
@@ -1336,3 +1337,27 @@ void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recv_data)
|
|||||||
item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);
|
item->ClearEnchantment(TEMP_ENCHANTMENT_SLOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldSession::HandleItemRefundInfoRequest(WorldPacket& recv_data)
|
||||||
|
{
|
||||||
|
sLog.outDebug("WORLD: CMSG_ITEM_REFUND_INFO_REQUEST");
|
||||||
|
|
||||||
|
uint64 guid;
|
||||||
|
|
||||||
|
recv_data >> guid; // item guid
|
||||||
|
|
||||||
|
Item *item = _player->GetItemByGuid(guid);
|
||||||
|
|
||||||
|
if(!item)
|
||||||
|
{
|
||||||
|
sLog.outDebug("Item refund: item not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_REFUNDABLE))
|
||||||
|
{
|
||||||
|
sLog.outDebug("Item refund: item not refundable!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// item refund system not implemented yet
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,10 +65,13 @@ enum ItemModType
|
|||||||
ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
|
ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
|
||||||
ITEM_MOD_MANA_REGENERATION = 43,
|
ITEM_MOD_MANA_REGENERATION = 43,
|
||||||
ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
|
ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
|
||||||
ITEM_MOD_SPELL_POWER = 45
|
ITEM_MOD_SPELL_POWER = 45,
|
||||||
|
ITEM_MOD_HEALTH_REGEN = 46,
|
||||||
|
ITEM_MOD_SPELL_PENETRATION = 47,
|
||||||
|
ITEM_MOD_BLOCK_VALUE = 48
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_ITEM_MOD 46
|
#define MAX_ITEM_MOD 49
|
||||||
|
|
||||||
enum ItemSpelltriggerType
|
enum ItemSpelltriggerType
|
||||||
{
|
{
|
||||||
@@ -108,9 +111,13 @@ enum ITEM_FLAGS
|
|||||||
ITEM_FLAGS_OPENABLE = 0x00000004,
|
ITEM_FLAGS_OPENABLE = 0x00000004,
|
||||||
ITEM_FLAGS_WRAPPED = 0x00000008,
|
ITEM_FLAGS_WRAPPED = 0x00000008,
|
||||||
ITEM_FLAGS_BROKEN = 0x00000010, // appears red icon (like when item durability==0)
|
ITEM_FLAGS_BROKEN = 0x00000010, // appears red icon (like when item durability==0)
|
||||||
|
ITEM_FLAGS_TOTEM = 0x00000020, // ?
|
||||||
|
ITEM_FLAGS_USABLE = 0x00000040, // ?
|
||||||
ITEM_FLAGS_WRAPPER = 0x00000200, // used or not used wrapper
|
ITEM_FLAGS_WRAPPER = 0x00000200, // used or not used wrapper
|
||||||
ITEM_FLAGS_PARTY_LOOT = 0x00000800, // determines if item is party loot or not
|
ITEM_FLAGS_PARTY_LOOT = 0x00000800, // determines if item is party loot or not
|
||||||
|
ITEM_FLAGS_REFUNDABLE = 0x00001000, // item cost can be refunded within 2 hours after purchase
|
||||||
ITEM_FLAGS_CHARTER = 0x00002000, // arena/guild charter
|
ITEM_FLAGS_CHARTER = 0x00002000, // arena/guild charter
|
||||||
|
ITEM_FLAGS_REFUNDABLE_2 = 0x00008000,
|
||||||
ITEM_FLAGS_PROSPECTABLE = 0x00040000,
|
ITEM_FLAGS_PROSPECTABLE = 0x00040000,
|
||||||
ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000,
|
ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000,
|
||||||
ITEM_FLAGS_USEABLE_IN_ARENA = 0x00200000,
|
ITEM_FLAGS_USEABLE_IN_ARENA = 0x00200000,
|
||||||
@@ -118,7 +125,9 @@ enum ITEM_FLAGS
|
|||||||
ITEM_FLAGS_SPECIALUSE = 0x00800000, // last used flag in 2.3.0
|
ITEM_FLAGS_SPECIALUSE = 0x00800000, // last used flag in 2.3.0
|
||||||
ITEM_FLAGS_BOA = 0x08000000, // bind on account (set in template for items that can binded in like way)
|
ITEM_FLAGS_BOA = 0x08000000, // bind on account (set in template for items that can binded in like way)
|
||||||
ITEM_FLAGS_TRIGGERED_CAST = 0x10000000, // used by enchanting scrolls made with vellum
|
ITEM_FLAGS_TRIGGERED_CAST = 0x10000000, // used by enchanting scrolls made with vellum
|
||||||
ITEM_FLAGS_MILLABLE = 0x20000000
|
ITEM_FLAGS_ENCHANT_SCROLL = 0x10000000, // for enchant scrolls
|
||||||
|
ITEM_FLAGS_MILLABLE = 0x20000000,
|
||||||
|
ITEM_FLAGS_BOP_TRADEABLE = 0x80000000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BAG_FAMILY_MASK
|
enum BAG_FAMILY_MASK
|
||||||
@@ -515,6 +524,7 @@ struct ItemPrototype
|
|||||||
uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc
|
uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc
|
||||||
uint32 Quality;
|
uint32 Quality;
|
||||||
uint32 Flags;
|
uint32 Flags;
|
||||||
|
uint32 Faction;
|
||||||
uint32 BuyCount;
|
uint32 BuyCount;
|
||||||
uint32 BuyPrice;
|
uint32 BuyPrice;
|
||||||
uint32 SellPrice;
|
uint32 SellPrice;
|
||||||
@@ -649,4 +659,3 @@ struct ItemLocale
|
|||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user