mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +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;
|
||||
}
|
||||
|
||||
// store data only for real progress
|
||||
if(iter->second.counter != 0)
|
||||
// store data only for real progress, exceptions are timedCriterias, they are also stored for 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
|
||||
if(!need_execute_ins)
|
||||
|
|
@ -597,13 +604,27 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri
|
|||
continue;
|
||||
}
|
||||
|
||||
if (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL))
|
||||
continue;
|
||||
|
||||
CriteriaProgress& progress = m_criteriaProgress[id];
|
||||
progress.counter = counter;
|
||||
progress.date = date;
|
||||
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
|
||||
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);
|
||||
data << uint32(id);
|
||||
|
||||
time_t now = time(NULL);
|
||||
// the counter is packed like a packed Guid
|
||||
data.appendPackGUID(progress->counter);
|
||||
|
||||
data << GetPlayer()->GetPackGUID();
|
||||
data << uint32(0);
|
||||
data << uint32(secsToTimeBitFields(progress->date));
|
||||
data << uint32(0); // timer 1
|
||||
data << uint32(0); // timer 2
|
||||
data << uint32(progress->timedCriteriaFailed ? 1 : 0);
|
||||
data << uint32(secsToTimeBitFields(now));
|
||||
data << uint32(now - progress->date); // timer 1
|
||||
data << uint32(now - progress->date); // timer 2
|
||||
GetPlayer()->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
|
|
@ -758,11 +780,58 @@ void AchievementMgr::StartTimedAchievementCriteria(AchievementCriteriaTypes type
|
|||
|
||||
// Start with given startTime or now
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
@ -1902,13 +1971,24 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri
|
|||
if(changeValue == 0)
|
||||
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())
|
||||
return;
|
||||
|
||||
progress = &m_criteriaProgress[criteria->ID];
|
||||
newValue = changeValue;
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -1936,27 +2016,6 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri
|
|||
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->changed = true;
|
||||
|
||||
|
|
@ -2144,15 +2203,16 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data)
|
|||
}
|
||||
*data << int32(-1);
|
||||
|
||||
time_t now = time(NULL);
|
||||
for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter)
|
||||
{
|
||||
*data << uint32(iter->first);
|
||||
data->appendPackGUID(iter->second.counter);
|
||||
*data << GetPlayer()->GetPackGUID();
|
||||
*data << uint32(0);
|
||||
*data << uint32(secsToTimeBitFields(iter->second.date));
|
||||
*data << uint32(0);
|
||||
*data << uint32(0);
|
||||
*data << uint32(iter->second.timedCriteriaFailed ? 1 : 0);
|
||||
*data << uint32(secsToTimeBitFields(now));
|
||||
*data << uint32(now - iter->second.date);
|
||||
*data << uint32(now - iter->second.date);
|
||||
}
|
||||
|
||||
*data << int32(-1);
|
||||
|
|
|
|||
|
|
@ -33,12 +33,14 @@ typedef std::list<AchievementEntry const*> AchievementEntryList;
|
|||
|
||||
typedef std::map<uint32,AchievementCriteriaEntryList> AchievementCriteriaListByAchievement;
|
||||
typedef std::map<uint32,AchievementEntryList> AchievementListByReferencedId;
|
||||
typedef std::map<uint32,time_t> AchievementCriteriaFailTimeMap;
|
||||
|
||||
struct CriteriaProgress
|
||||
{
|
||||
uint32 counter;
|
||||
time_t date;
|
||||
bool changed;
|
||||
bool timedCriteriaFailed;
|
||||
};
|
||||
|
||||
enum AchievementCriteriaRequirementType
|
||||
|
|
@ -250,6 +252,7 @@ class AchievementMgr
|
|||
void SaveToDB();
|
||||
void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=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 CheckAllAchievementCriteria();
|
||||
void SendAllAchievementData();
|
||||
|
|
@ -292,6 +295,7 @@ class AchievementMgr
|
|||
Player* m_player;
|
||||
CriteriaProgressMap m_criteriaProgress;
|
||||
CompletedAchievementMap m_completedAchievements;
|
||||
AchievementCriteriaFailTimeMap m_criteriaFailTimes;
|
||||
};
|
||||
|
||||
class AchievementGlobalMgr
|
||||
|
|
|
|||
|
|
@ -1180,6 +1180,9 @@ void Player::Update( uint32 p_time )
|
|||
if(!IsInWorld())
|
||||
return;
|
||||
|
||||
// remove failed timed Achievements
|
||||
GetAchievementMgr().DoFailedTimedAchievementCriterias();
|
||||
|
||||
// undelivered mail
|
||||
if(m_nextMailDelivereTime && m_nextMailDelivereTime <= time(NULL))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "10666"
|
||||
#define REVISION_NR "10667"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue