mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
Added database support for achievement progress
Implemented ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT
This commit is contained in:
parent
c5dbf49ece
commit
6b32fa7175
6 changed files with 134 additions and 26 deletions
14
sql/wotlk_updates/6_character_achievement.sql
Normal file
14
sql/wotlk_updates/6_character_achievement.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS `character_achievement` (
|
||||||
|
`guid` int(11) NOT NULL,
|
||||||
|
`achievement` int(11) NOT NULL,
|
||||||
|
`date` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`guid`,`achievement`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `character_achievement_progress` (
|
||||||
|
`guid` int(11) NOT NULL,
|
||||||
|
`criteria` int(11) NOT NULL,
|
||||||
|
`counter` int(11) NOT NULL,
|
||||||
|
`date` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`guid`,`criteria`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||||
|
|
@ -23,20 +23,76 @@
|
||||||
#include "Database/DBCEnums.h"
|
#include "Database/DBCEnums.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
#include "Guild.h"
|
#include "Guild.h"
|
||||||
|
#include "Database/DatabaseEnv.h"
|
||||||
|
|
||||||
AchievementMgr::AchievementMgr(Player *player)
|
AchievementMgr::AchievementMgr(Player *player)
|
||||||
{
|
{
|
||||||
m_player = player;
|
m_player = player;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::SaveToDB()
|
AchievementMgr::~AchievementMgr()
|
||||||
{
|
{
|
||||||
// TODO store achievements
|
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
m_criteriaProgress.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::LoadFromDB()
|
void AchievementMgr::SaveToDB()
|
||||||
{
|
{
|
||||||
// TODO load achievements
|
if(!m_completedAchievements.empty())
|
||||||
|
{
|
||||||
|
CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = %u", GetPlayer()->GetGUIDLow());
|
||||||
|
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "INSERT INTO character_achievement (guid, achievement, date) VALUES ";
|
||||||
|
for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++)
|
||||||
|
{
|
||||||
|
if(iter != m_completedAchievements.begin())
|
||||||
|
ss << ", ";
|
||||||
|
ss << "("<<GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second << ")";
|
||||||
|
}
|
||||||
|
CharacterDatabase.Execute( ss.str().c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_criteriaProgress.empty())
|
||||||
|
{
|
||||||
|
CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = %u", GetPlayer()->GetGUIDLow());
|
||||||
|
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES ";
|
||||||
|
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||||
|
{
|
||||||
|
if(iter != m_criteriaProgress.begin())
|
||||||
|
ss << ", ";
|
||||||
|
ss << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second->counter << ", " << iter->second->date << ")";
|
||||||
|
}
|
||||||
|
CharacterDatabase.Execute( ss.str().c_str() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult)
|
||||||
|
{
|
||||||
|
if(achievementResult)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Field *fields = achievementResult->Fetch();
|
||||||
|
m_completedAchievements[fields[0].GetUInt32()] = fields[1].GetUInt32();
|
||||||
|
} while(achievementResult->NextRow());
|
||||||
|
delete achievementResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(criteriaResult)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Field *fields = criteriaResult->Fetch();
|
||||||
|
CriteriaProgress *progress = new CriteriaProgress(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt64());
|
||||||
|
m_criteriaProgress[progress->id] = progress;
|
||||||
|
} while(criteriaResult->NextRow());
|
||||||
|
delete criteriaResult;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::SendAchievementEarned(uint32 achievementId)
|
void AchievementMgr::SendAchievementEarned(uint32 achievementId)
|
||||||
|
|
@ -79,18 +135,17 @@ void AchievementMgr::SendAchievementEarned(uint32 achievementId)
|
||||||
GetPlayer()->SendMessageToSet(&data, true);
|
GetPlayer()->SendMessageToSet(&data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::SendCriteriaUpdate(uint32 criteriaId, uint32 counter)
|
void AchievementMgr::SendCriteriaUpdate(CriteriaProgress *progress)
|
||||||
{
|
{
|
||||||
sLog.outString("AchievementMgr::SendCriteriaUpdate(%u, %u)", criteriaId, counter);
|
|
||||||
WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
|
WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
|
||||||
data << uint32(criteriaId);
|
data << uint32(progress->id);
|
||||||
|
|
||||||
// the counter is packed like a packed Guid
|
// the counter is packed like a packed Guid
|
||||||
data.appendPackGUID(counter);
|
data.appendPackGUID(progress->counter);
|
||||||
|
|
||||||
data.append(GetPlayer()->GetPackGUID());
|
data.append(GetPlayer()->GetPackGUID());
|
||||||
data << uint32(0);
|
data << uint32(0);
|
||||||
data << uint32(secsToTimeBitFields(time(NULL)));
|
data << uint32(secsToTimeBitFields(progress->date));
|
||||||
data << uint32(0); // timer 1
|
data << uint32(0); // timer 1
|
||||||
data << uint32(0); // timer 2
|
data << uint32(0); // timer 2
|
||||||
GetPlayer()->SendMessageToSet(&data, true);
|
GetPlayer()->SendMessageToSet(&data, true);
|
||||||
|
|
@ -121,6 +176,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||||
if(IsCompletedCriteria(achievementCriteria))
|
if(IsCompletedCriteria(achievementCriteria))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if(achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup())
|
||||||
|
continue;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
||||||
|
|
@ -129,8 +187,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
||||||
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
|
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
|
||||||
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1);
|
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1);
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if(IsCompletedCriteria(achievementCriteria))
|
if(IsCompletedCriteria(achievementCriteria))
|
||||||
CompletedCriteria(achievementCriteria);
|
CompletedCriteria(achievementCriteria);
|
||||||
|
|
@ -146,15 +202,20 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
|
||||||
if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
|
if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(m_criteriaProgress.find(achievementCriteria->ID) == m_criteriaProgress.end())
|
CriteriaProgressMap::iterator itr = m_criteriaProgress.find(achievementCriteria->ID);
|
||||||
|
if(itr == m_criteriaProgress.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
CriteriaProgress *progress = itr->second;
|
||||||
|
|
||||||
switch(achievementCriteria->requiredType)
|
switch(achievementCriteria->requiredType)
|
||||||
{
|
{
|
||||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
||||||
return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->reach_level.level;
|
return progress->counter >= achievementCriteria->reach_level.level;
|
||||||
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
|
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
|
||||||
return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->buy_bank_slot.numberOfSlots;
|
return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots;
|
||||||
|
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT:
|
||||||
|
return m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +250,7 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve
|
||||||
if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL)
|
if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL)
|
||||||
return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED;
|
return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED;
|
||||||
|
|
||||||
// found an umcompleted criteria, but DONT return false - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL
|
// found an umcompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL
|
||||||
if(!IsCompletedCriteria(criteria))
|
if(!IsCompletedCriteria(criteria))
|
||||||
foundOutstanding = true;
|
foundOutstanding = true;
|
||||||
}
|
}
|
||||||
|
|
@ -202,8 +263,21 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve
|
||||||
void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue)
|
void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue)
|
||||||
{
|
{
|
||||||
sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue);
|
sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue);
|
||||||
m_criteriaProgress[entry->ID] = newValue;
|
CriteriaProgress *progress = NULL;
|
||||||
SendCriteriaUpdate(entry->ID, newValue);
|
|
||||||
|
if(m_criteriaProgress.find(entry->ID) == m_criteriaProgress.end())
|
||||||
|
{
|
||||||
|
progress = new CriteriaProgress(entry->ID, newValue);
|
||||||
|
m_criteriaProgress[entry->ID]=progress;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
progress = m_criteriaProgress[entry->ID];
|
||||||
|
if(progress->counter == newValue)
|
||||||
|
return;
|
||||||
|
progress->counter = newValue;
|
||||||
|
}
|
||||||
|
SendCriteriaUpdate(progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||||
|
|
@ -214,6 +288,8 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||||
|
|
||||||
SendAchievementEarned(achievement->ID);
|
SendAchievementEarned(achievement->ID);
|
||||||
m_completedAchievements[achievement->ID] = time(NULL);
|
m_completedAchievements[achievement->ID] = time(NULL);
|
||||||
|
|
||||||
|
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT);
|
||||||
// TODO: reward titles and items
|
// TODO: reward titles and items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,16 +324,15 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data)
|
||||||
|
|
||||||
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||||
{
|
{
|
||||||
*data << uint32(iter->first);
|
*data << uint32(iter->second->id);
|
||||||
data->appendPackGUID(iter->second);
|
data->appendPackGUID(iter->second->counter);
|
||||||
data->append(GetPlayer()->GetPackGUID());
|
data->append(GetPlayer()->GetPackGUID());
|
||||||
*data << uint32(0);
|
*data << uint32(0);
|
||||||
*data << uint32(secsToTimeBitFields(time(NULL)));
|
*data << uint32(secsToTimeBitFields(iter->second->date));
|
||||||
*data << uint32(0);
|
*data << uint32(0);
|
||||||
*data << uint32(0);
|
*data << uint32(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
*data << int32(-1);
|
*data << int32(-1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,22 @@
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Database/DBCEnums.h"
|
#include "Database/DBCEnums.h"
|
||||||
#include "Database/DBCStores.h"
|
#include "Database/DBCStores.h"
|
||||||
|
#include "Database/DatabaseEnv.h"
|
||||||
|
|
||||||
typedef HM_NAMESPACE::hash_map<uint32, uint32> CriteriaProgressMap;
|
struct CriteriaProgress
|
||||||
|
{
|
||||||
|
CriteriaProgress(uint32 id, uint32 counter, time_t date = time(NULL))
|
||||||
|
{
|
||||||
|
this->id = id;
|
||||||
|
this->counter = counter;
|
||||||
|
this->date = date;
|
||||||
|
}
|
||||||
|
uint32 id;
|
||||||
|
uint32 counter;
|
||||||
|
time_t date;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef HM_NAMESPACE::hash_map<uint32, CriteriaProgress*> CriteriaProgressMap;
|
||||||
typedef HM_NAMESPACE::hash_map<uint32, time_t> CompletedAchievementMap;
|
typedef HM_NAMESPACE::hash_map<uint32, time_t> CompletedAchievementMap;
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
|
|
@ -39,8 +53,9 @@ class AchievementMgr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AchievementMgr(Player* pl);
|
AchievementMgr(Player* pl);
|
||||||
|
~AchievementMgr();
|
||||||
|
|
||||||
void LoadFromDB();
|
void LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult);
|
||||||
void SaveToDB();
|
void SaveToDB();
|
||||||
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, uint32 time=0);
|
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, uint32 time=0);
|
||||||
void CheckAllAchievementCriteria();
|
void CheckAllAchievementCriteria();
|
||||||
|
|
@ -51,7 +66,7 @@ class AchievementMgr
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SendAchievementEarned(uint32 achievementId);
|
void SendAchievementEarned(uint32 achievementId);
|
||||||
void SendCriteriaUpdate(uint32 criteriaId, uint32 counter);
|
void SendCriteriaUpdate(CriteriaProgress *progress);
|
||||||
void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue);
|
void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue);
|
||||||
void CompletedCriteria(AchievementCriteriaEntry const* entry);
|
void CompletedCriteria(AchievementCriteriaEntry const* entry);
|
||||||
void CompletedAchievement(AchievementEntry const* entry);
|
void CompletedAchievement(AchievementEntry const* entry);
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,8 @@ bool LoginQueryHolder::Initialize()
|
||||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid));
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid));
|
||||||
// in other case still be dummy query
|
// in other case still be dummy query
|
||||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid));
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||||
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||||
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14088,7 +14088,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
||||||
|
|
||||||
_LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES));
|
_LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES));
|
||||||
|
|
||||||
m_achievementMgr.LoadFromDB();
|
m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS));
|
||||||
m_achievementMgr.CheckAllAchievementCriteria();
|
m_achievementMgr.CheckAllAchievementCriteria();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -836,9 +836,11 @@ enum PlayerLoginQueryIndex
|
||||||
PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15,
|
PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15,
|
||||||
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16,
|
PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16,
|
||||||
PLAYER_LOGIN_QUERY_LOADGUILD = 17,
|
PLAYER_LOGIN_QUERY_LOADGUILD = 17,
|
||||||
|
PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 18,
|
||||||
|
PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 19,
|
||||||
|
MAX_PLAYER_LOGIN_QUERY = 20
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_PLAYER_LOGIN_QUERY 18
|
|
||||||
|
|
||||||
// Player summoning auto-decline time (in secs)
|
// Player summoning auto-decline time (in secs)
|
||||||
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
|
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue