Use reset time for normal/heroic from new DBC. Improve basic support for raid difficalties.

This commit is contained in:
VladimirMangos 2009-10-05 02:04:33 +04:00
parent 9850551751
commit a9af7f2b1c
24 changed files with 340 additions and 173 deletions

View file

@ -509,7 +509,7 @@ Player::~Player ()
delete ItemSetEff[x];
// clean up player-instance binds, may unload some instance saves
for(uint8 i = 0; i < TOTAL_DUNGEON_DIFFICULTIES; ++i)
for(uint8 i = 0; i < MAX_DIFFICULTY; ++i)
for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
itr->second.save->RemovePlayer(this);
@ -14182,7 +14182,11 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
uint32 transGUID = fields[31].GetUInt32();
Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat());
SetLocationMapId(fields[16].GetUInt32());
SetDungeonDifficulty(fields[39].GetUInt32()); // may be changed in _LoadGroup
uint32 difficulty = fields[39].GetUInt32();
if(difficulty >= MAX_DUNGEON_DIFFICULTY)
difficulty = DUNGEON_DIFFICULTY_NORMAL;
SetDungeonDifficulty(Difficulty(difficulty)); // may be changed in _LoadGroup
_LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP));
@ -15281,19 +15285,20 @@ void Player::_LoadSpells(QueryResult *result)
void Player::_LoadGroup(QueryResult *result)
{
//QueryResult *result = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", GetGUIDLow());
if(result)
if (result)
{
uint64 leaderGuid = MAKE_NEW_GUID((*result)[0].GetUInt32(), 0, HIGHGUID_PLAYER);
delete result;
Group* group = objmgr.GetGroupByLeader(leaderGuid);
if(group)
if (Group* group = objmgr.GetGroupByLeader(leaderGuid))
{
uint8 subgroup = group->GetMemberGroup(GetGUID());
SetGroup(group, subgroup);
if(getLevel() >= LEVELREQUIREMENT_HEROIC)
if (getLevel() >= LEVELREQUIREMENT_HEROIC)
{
// the group leader may change the instance difficulty while the player is offline
SetDungeonDifficulty(group->GetDungeonDifficulty());
SetRaidDifficulty(group->GetRaidDifficulty());
}
}
}
@ -15301,7 +15306,7 @@ void Player::_LoadGroup(QueryResult *result)
void Player::_LoadBoundInstances(QueryResult *result)
{
for(uint8 i = 0; i < TOTAL_DUNGEON_DIFFICULTIES; ++i)
for(uint8 i = 0; i < MAX_DIFFICULTY; ++i)
m_boundInstances[i].clear();
Group *group = GetGroup();
@ -15316,6 +15321,7 @@ void Player::_LoadBoundInstances(QueryResult *result)
uint32 mapId = fields[2].GetUInt32();
uint32 instanceId = fields[0].GetUInt32();
uint8 difficulty = fields[3].GetUInt8();
time_t resetTime = (time_t)fields[4].GetUInt64();
// the resettime for normal instances is only saved when the InstanceSave is unloaded
// so the value read from the DB may be wrong here but only if the InstanceSave is loaded
@ -15329,6 +15335,21 @@ void Player::_LoadBoundInstances(QueryResult *result)
continue;
}
if(difficulty >= MAX_DIFFICULTY)
{
sLog.outError("_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u", GetName(), GetGUIDLow(), difficulty, mapId);
CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND instance = '%d'", GetGUIDLow(), instanceId);
continue;
}
MapDifficulty const* mapDiff = GetMapDifficultyData(mapId,Difficulty(difficulty));
if(!mapDiff)
{
sLog.outError("_LoadBoundInstances: player %s(%d) has bind to not existed difficulty %d instance for map %u", GetName(), GetGUIDLow(), difficulty, mapId);
CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%d' AND instance = '%d'", GetGUIDLow(), instanceId);
continue;
}
if(!perm && group)
{
sLog.outError("_LoadBoundInstances: player %s(%d) is in group %d but has a non-permanent character bind to map %d,%d,%d", GetName(), GetGUIDLow(), GUID_LOPART(group->GetLeaderGUID()), mapId, instanceId, difficulty);
@ -15337,18 +15358,19 @@ void Player::_LoadBoundInstances(QueryResult *result)
}
// since non permanent binds are always solo bind, they can always be reset
InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapId, instanceId, difficulty, resetTime, !perm, true);
InstanceSave *save = sInstanceSaveManager.AddInstanceSave(mapId, instanceId, Difficulty(difficulty), resetTime, !perm, true);
if(save) BindToInstance(save, perm, true);
} while(result->NextRow());
delete result;
}
}
InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, uint8 difficulty)
InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, Difficulty difficulty)
{
// some instances only have one difficulty
const MapEntry* entry = sMapStore.LookupEntry(mapid);
if(!entry || !entry->SupportsHeroicMode()) difficulty = DUNGEON_DIFFICULTY_NORMAL;
MapDifficulty const* mapDiff = GetMapDifficultyData(mapid,difficulty);
if(!mapDiff)
return NULL;
BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid);
if(itr != m_boundInstances[difficulty].end())
@ -15357,13 +15379,13 @@ InstancePlayerBind* Player::GetBoundInstance(uint32 mapid, uint8 difficulty)
return NULL;
}
void Player::UnbindInstance(uint32 mapid, uint8 difficulty, bool unload)
void Player::UnbindInstance(uint32 mapid, Difficulty difficulty, bool unload)
{
BoundInstancesMap::iterator itr = m_boundInstances[difficulty].find(mapid);
UnbindInstance(itr, difficulty, unload);
}
void Player::UnbindInstance(BoundInstancesMap::iterator &itr, uint8 difficulty, bool unload)
void Player::UnbindInstance(BoundInstancesMap::iterator &itr, Difficulty difficulty, bool unload)
{
if(itr != m_boundInstances[difficulty].end())
{
@ -15415,7 +15437,7 @@ void Player::SendRaidInfo()
time_t now = time(NULL);
for(int i = 0; i < TOTAL_DUNGEON_DIFFICULTIES; ++i)
for(int i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::const_iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
@ -15444,7 +15466,7 @@ void Player::SendSavedInstances()
bool hasBeenSaved = false;
WorldPacket data;
for(uint8 i = 0; i < TOTAL_DUNGEON_DIFFICULTIES; ++i)
for(uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::const_iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
@ -15464,7 +15486,7 @@ void Player::SendSavedInstances()
if(!hasBeenSaved)
return;
for(uint8 i = 0; i < TOTAL_DUNGEON_DIFFICULTIES; ++i)
for(uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::const_iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr)
{
@ -15492,7 +15514,7 @@ void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player
if(player)
{
for(uint8 i = 0; i < TOTAL_DUNGEON_DIFFICULTIES; ++i)
for(uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();)
{
@ -15501,7 +15523,8 @@ void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player
// permanent binds are not removed
if(!itr->second.perm)
{
player->UnbindInstance(itr, i, true); // increments itr
// increments itr in call
player->UnbindInstance(itr, Difficulty(i), true);
has_solo = true;
}
else
@ -16209,18 +16232,18 @@ void Player::SendResetFailedNotify(uint32 mapid)
}
/// Reset all solo instances and optionally send a message on success for each
void Player::ResetInstances(uint8 method)
void Player::ResetInstances(uint8 method, bool isRaid)
{
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_JOIN
// we assume that when the difficulty changes, all instances that can be reset will be
uint8 dif = GetDungeonDifficulty();
Difficulty diff = GetDifficulty(isRaid);
for (BoundInstancesMap::iterator itr = m_boundInstances[dif].begin(); itr != m_boundInstances[dif].end();)
for (BoundInstancesMap::iterator itr = m_boundInstances[diff].begin(); itr != m_boundInstances[diff].end();)
{
InstanceSave *p = itr->second.save;
const MapEntry *entry = sMapStore.LookupEntry(itr->first);
if(!entry || !p->CanReset())
if(!entry || entry->IsRaid() != isRaid || !p->CanReset())
{
++itr;
continue;
@ -16229,7 +16252,7 @@ void Player::ResetInstances(uint8 method)
if(method == INSTANCE_RESET_ALL)
{
// the "reset all instances" method can only reset normal maps
if(dif == DUNGEON_DIFFICULTY_HEROIC || entry->map_type == MAP_RAID)
if(entry->map_type == MAP_RAID || diff == DUNGEON_DIFFICULTY_HEROIC)
{
++itr;
continue;
@ -16246,7 +16269,7 @@ void Player::ResetInstances(uint8 method)
SendResetInstanceSuccess(p->GetMapId());
p->DeleteFromDB();
m_boundInstances[dif].erase(itr++);
m_boundInstances[diff].erase(itr++);
// the following should remove the instance save from the manager and delete it as well
p->RemovePlayer(this);
@ -18325,7 +18348,7 @@ void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg)
GetSession()->SendPacket(&data);
}
void Player::SendInstanceResetWarning( uint32 mapid, uint32 difficulty, uint32 time )
void Player::SendInstanceResetWarning( uint32 mapid, Difficulty difficulty, uint32 time )
{
// type of warning, based on the time remaining until reset
uint32 type;