mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[10667] Timed Achievements, Fail-Support and Opcodes
Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
parent
e78887e964
commit
ef5ea6f24f
4 changed files with 104 additions and 37 deletions
|
|
@ -523,8 +523,15 @@ void AchievementMgr::SaveToDB()
|
||||||
ssdel << iter->first;
|
ssdel << iter->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store data only for real progress
|
// store data only for real progress, exceptions are timedCriterias, they are also stored for counter == 0
|
||||||
if(iter->second.counter != 0)
|
bool needSave = iter->second.counter != 0;
|
||||||
|
if (!needSave)
|
||||||
|
{
|
||||||
|
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(iter->first);
|
||||||
|
needSave = criteria && criteria->timeLimit > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needSave)
|
||||||
{
|
{
|
||||||
/// first new/changed record prefix
|
/// first new/changed record prefix
|
||||||
if(!need_execute_ins)
|
if(!need_execute_ins)
|
||||||
|
|
@ -597,13 +604,27 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
CriteriaProgress& progress = m_criteriaProgress[id];
|
CriteriaProgress& progress = m_criteriaProgress[id];
|
||||||
progress.counter = counter;
|
progress.counter = counter;
|
||||||
progress.date = date;
|
progress.date = date;
|
||||||
progress.changed = false;
|
progress.changed = false;
|
||||||
|
progress.timedCriteriaFailed = false;
|
||||||
|
|
||||||
|
// A failed achievement will be removed on next tick - TODO: Possible that timer 2 is reseted
|
||||||
|
if (criteria->timeLimit)
|
||||||
|
{
|
||||||
|
AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement);
|
||||||
|
|
||||||
|
// Add not-completed achievements to time map
|
||||||
|
if (!IsCompletedCriteria(criteria, achievement))
|
||||||
|
{
|
||||||
|
time_t failTime = time_t(progress.date + criteria->timeLimit);
|
||||||
|
m_criteriaFailTimes[criteria->ID] = failTime;
|
||||||
|
// A failed Achievement - will be removed by DoFailedTimedAchievementCriterias on next tick for player
|
||||||
|
if (failTime <= time(NULL))
|
||||||
|
progress.timedCriteriaFailed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check intergiry with max allowed counter value
|
// check intergiry with max allowed counter value
|
||||||
if (uint32 maxcounter = GetCriteriaProgressMaxCounter(criteria))
|
if (uint32 maxcounter = GetCriteriaProgressMaxCounter(criteria))
|
||||||
|
|
@ -667,14 +688,15 @@ void AchievementMgr::SendCriteriaUpdate(uint32 id, CriteriaProgress const* progr
|
||||||
WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
|
WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8);
|
||||||
data << uint32(id);
|
data << uint32(id);
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
// the counter is packed like a packed Guid
|
// the counter is packed like a packed Guid
|
||||||
data.appendPackGUID(progress->counter);
|
data.appendPackGUID(progress->counter);
|
||||||
|
|
||||||
data << GetPlayer()->GetPackGUID();
|
data << GetPlayer()->GetPackGUID();
|
||||||
data << uint32(0);
|
data << uint32(progress->timedCriteriaFailed ? 1 : 0);
|
||||||
data << uint32(secsToTimeBitFields(progress->date));
|
data << uint32(secsToTimeBitFields(now));
|
||||||
data << uint32(0); // timer 1
|
data << uint32(now - progress->date); // timer 1
|
||||||
data << uint32(0); // timer 2
|
data << uint32(now - progress->date); // timer 2
|
||||||
GetPlayer()->SendDirectMessage(&data);
|
GetPlayer()->SendDirectMessage(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -758,11 +780,58 @@ void AchievementMgr::StartTimedAchievementCriteria(AchievementCriteriaTypes type
|
||||||
|
|
||||||
// Start with given startTime or now
|
// Start with given startTime or now
|
||||||
progress->date = startTime ? startTime : time(NULL);
|
progress->date = startTime ? startTime : time(NULL);
|
||||||
|
progress->timedCriteriaFailed = false;
|
||||||
|
|
||||||
|
// Add to timer map
|
||||||
|
m_criteriaFailTimes[achievementCriteria->ID] = time_t(progress->date + achievementCriteria->timeLimit);
|
||||||
|
|
||||||
SendCriteriaUpdate(achievementCriteria->ID, progress);
|
SendCriteriaUpdate(achievementCriteria->ID, progress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this function will be called whenever there could be a timed achievement criteria failed because of ellapsed time
|
||||||
|
*/
|
||||||
|
void AchievementMgr::DoFailedTimedAchievementCriterias()
|
||||||
|
{
|
||||||
|
if (m_criteriaFailTimes.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
|
for (AchievementCriteriaFailTimeMap::iterator iter = m_criteriaFailTimes.begin(); iter != m_criteriaFailTimes.end();)
|
||||||
|
{
|
||||||
|
if (iter->second > now)
|
||||||
|
{
|
||||||
|
++iter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Possible failed achievement criteria found
|
||||||
|
AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(iter->first);
|
||||||
|
AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement);
|
||||||
|
|
||||||
|
// Send Fail for failed criterias
|
||||||
|
if (!IsCompletedCriteria(criteria, achievement))
|
||||||
|
{
|
||||||
|
DETAIL_FILTER_LOG(LOG_FILTER_ACHIEVEMENT_UPDATES, "AchievementMgr::DoFailedTimedAchievementCriterias for criteria %u", criteria->ID);
|
||||||
|
|
||||||
|
CriteriaProgressMap::iterator pro_iter = m_criteriaProgress.find(criteria->ID);
|
||||||
|
MANGOS_ASSERT(pro_iter != m_criteriaProgress.end());
|
||||||
|
|
||||||
|
CriteriaProgress* progress = &pro_iter->second;
|
||||||
|
|
||||||
|
// Set to failed, and send to client
|
||||||
|
progress->timedCriteriaFailed = true;
|
||||||
|
SendCriteriaUpdate(criteria->ID, progress);
|
||||||
|
|
||||||
|
// Remove failed progress
|
||||||
|
m_criteriaProgress.erase(pro_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = m_criteriaFailTimes.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this function will be called whenever the user might have done a criteria relevant action
|
* this function will be called whenever the user might have done a criteria relevant action
|
||||||
*/
|
*/
|
||||||
|
|
@ -1902,13 +1971,24 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri
|
||||||
if(changeValue == 0)
|
if(changeValue == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// not start manually started timed achievements - must be same check as below (ie possible on player logout between start and finish)
|
// not start manually started timed achievements
|
||||||
if (criteria->IsExplicitlyStartedTimedCriteria())
|
if (criteria->IsExplicitlyStartedTimedCriteria())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
progress = &m_criteriaProgress[criteria->ID];
|
progress = &m_criteriaProgress[criteria->ID];
|
||||||
newValue = changeValue;
|
|
||||||
progress->date = time(NULL);
|
progress->date = time(NULL);
|
||||||
|
progress->timedCriteriaFailed = false;
|
||||||
|
|
||||||
|
// timed criterias are added to fail-timer map, and send the starting with counter=0
|
||||||
|
if (criteria->timeLimit)
|
||||||
|
{
|
||||||
|
m_criteriaFailTimes[criteria->ID] = time_t(progress->date + criteria->timeLimit);
|
||||||
|
progress->counter = 0;
|
||||||
|
SendCriteriaUpdate(criteria->ID, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
newValue = changeValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1936,27 +2016,6 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress->changed = true;
|
|
||||||
|
|
||||||
if(criteria->timeLimit)
|
|
||||||
{
|
|
||||||
time_t now = time(NULL);
|
|
||||||
|
|
||||||
// too later, need restart from 1 auto-started or just fail explcit started
|
|
||||||
if (time_t(progress->date + criteria->timeLimit) < now)
|
|
||||||
{
|
|
||||||
// Do not reset timer for requirements that are started manually, also reset their counter, same check as above
|
|
||||||
if (criteria->IsExplicitlyStartedTimedCriteria())
|
|
||||||
newValue = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newValue = 1;
|
|
||||||
// This is used as start time of the achievement, and hence only updated on fail
|
|
||||||
progress->date = now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progress->counter = newValue;
|
progress->counter = newValue;
|
||||||
progress->changed = true;
|
progress->changed = true;
|
||||||
|
|
||||||
|
|
@ -2144,15 +2203,16 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data)
|
||||||
}
|
}
|
||||||
*data << int32(-1);
|
*data << int32(-1);
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||||
{
|
{
|
||||||
*data << uint32(iter->first);
|
*data << uint32(iter->first);
|
||||||
data->appendPackGUID(iter->second.counter);
|
data->appendPackGUID(iter->second.counter);
|
||||||
*data << GetPlayer()->GetPackGUID();
|
*data << GetPlayer()->GetPackGUID();
|
||||||
*data << uint32(0);
|
*data << uint32(iter->second.timedCriteriaFailed ? 1 : 0);
|
||||||
*data << uint32(secsToTimeBitFields(iter->second.date));
|
*data << uint32(secsToTimeBitFields(now));
|
||||||
*data << uint32(0);
|
*data << uint32(now - iter->second.date);
|
||||||
*data << uint32(0);
|
*data << uint32(now - iter->second.date);
|
||||||
}
|
}
|
||||||
|
|
||||||
*data << int32(-1);
|
*data << int32(-1);
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,14 @@ typedef std::list<AchievementEntry const*> AchievementEntryList;
|
||||||
|
|
||||||
typedef std::map<uint32,AchievementCriteriaEntryList> AchievementCriteriaListByAchievement;
|
typedef std::map<uint32,AchievementCriteriaEntryList> AchievementCriteriaListByAchievement;
|
||||||
typedef std::map<uint32,AchievementEntryList> AchievementListByReferencedId;
|
typedef std::map<uint32,AchievementEntryList> AchievementListByReferencedId;
|
||||||
|
typedef std::map<uint32,time_t> AchievementCriteriaFailTimeMap;
|
||||||
|
|
||||||
struct CriteriaProgress
|
struct CriteriaProgress
|
||||||
{
|
{
|
||||||
uint32 counter;
|
uint32 counter;
|
||||||
time_t date;
|
time_t date;
|
||||||
bool changed;
|
bool changed;
|
||||||
|
bool timedCriteriaFailed;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AchievementCriteriaRequirementType
|
enum AchievementCriteriaRequirementType
|
||||||
|
|
@ -250,6 +252,7 @@ class AchievementMgr
|
||||||
void SaveToDB();
|
void SaveToDB();
|
||||||
void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0);
|
void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0);
|
||||||
void StartTimedAchievementCriteria(AchievementCriteriaTypes type, uint32 timedRequirementId, time_t startTime = 0);
|
void StartTimedAchievementCriteria(AchievementCriteriaTypes type, uint32 timedRequirementId, time_t startTime = 0);
|
||||||
|
void DoFailedTimedAchievementCriterias();
|
||||||
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0);
|
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0);
|
||||||
void CheckAllAchievementCriteria();
|
void CheckAllAchievementCriteria();
|
||||||
void SendAllAchievementData();
|
void SendAllAchievementData();
|
||||||
|
|
@ -292,6 +295,7 @@ class AchievementMgr
|
||||||
Player* m_player;
|
Player* m_player;
|
||||||
CriteriaProgressMap m_criteriaProgress;
|
CriteriaProgressMap m_criteriaProgress;
|
||||||
CompletedAchievementMap m_completedAchievements;
|
CompletedAchievementMap m_completedAchievements;
|
||||||
|
AchievementCriteriaFailTimeMap m_criteriaFailTimes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AchievementGlobalMgr
|
class AchievementGlobalMgr
|
||||||
|
|
|
||||||
|
|
@ -1180,6 +1180,9 @@ void Player::Update( uint32 p_time )
|
||||||
if(!IsInWorld())
|
if(!IsInWorld())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// remove failed timed Achievements
|
||||||
|
GetAchievementMgr().DoFailedTimedAchievementCriterias();
|
||||||
|
|
||||||
// undelivered mail
|
// undelivered mail
|
||||||
if(m_nextMailDelivereTime && m_nextMailDelivereTime <= time(NULL))
|
if(m_nextMailDelivereTime && m_nextMailDelivereTime <= time(NULL))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "10666"
|
#define REVISION_NR "10667"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue