Core/Achievements: ported start event and fail event mechanics from master branch

This commit is contained in:
Ovahlord committed 2023-10-11 01:38:01 +02:00
1 parent a599f7461d
commit ff0eb86c54
41 files changed
+325 -362

No files matched your search

@@ -0,0 +1 @@
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_algalon_supermassive_fail';
+128 -167
View File
@@ -21,6 +21,7 @@
#include "Battleground.h"
#include "CellImpl.h"
#include "ChatTextBuilder.h"
#include "Containers.h"
#include "DatabaseEnv.h"
#include "DBCEnums.h"
#include "DisableMgr.h"
@@ -44,6 +45,7 @@
#include "SpellMgr.h"
#include "World.h"
#include "WorldSession.h"
#include "WorldStateMgr.h"
bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
{
@@ -469,7 +471,7 @@ void AchievementMgr<Guild>::RemoveCriteriaProgress(AchievementCriteriaEntry cons
if (!entry)
return;
CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
auto criteriaProgress = m_criteriaProgress.find(entry->ID);
if (criteriaProgress == m_criteriaProgress.end())
return;
@@ -497,43 +499,11 @@ void AchievementMgr<Guild>::RemoveCriteriaProgress(AchievementCriteriaEntry cons
SendPacket(&data);
criteriaProgress->second.counter = 0;
criteriaProgress->second.changed = true;
m_criteriaProgress.erase(criteriaProgress);
}
template<class T>
void AchievementMgr<T>::ResetAchievementCriteria(AchievementCriteriaCondition condition, uint64 value, bool evenIfCriteriaComplete)
{
TC_LOG_DEBUG("achievement", "ResetAchievementCriteria(%u, " UI64FMTD ", %u)", condition, value, evenIfCriteriaComplete);
// disable for gamemasters with GM-mode enabled
if (GetOwner()->IsGameMaster())
return;
AchievementCriteriaEntryList const* achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByCondition(condition, value);
if (!achievementCriteriaList)
return;
for (auto itr = achievementCriteriaList->begin(); itr != achievementCriteriaList->end(); ++itr)
{
AchievementCriteriaEntry const* achievementCriteria = *itr;
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->ReferredAchievement);
if (!achievement)
continue;
// don't update already completed criteria if not forced or achievement already complete
if ((IsCompletedCriteria(achievementCriteria, achievement) && !evenIfCriteriaComplete) || HasAchieved(achievement->ID))
continue;
RemoveCriteriaProgress(achievementCriteria);
}
}
template<>
void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaCondition /*condition*/, uint64 /*value*/, bool /*evenIfCriteriaComplete*/)
{
// Not needed
}
template<class T>
void AchievementMgr<T>::DeleteFromDB(ObjectGuid /*guid*/)
{
@@ -734,7 +704,7 @@ void AchievementMgr<Player>::LoadFromDB(PreparedQueryResult achievementResult, P
continue;
}
if (criteria->StartTimer && time_t(date + criteria->StartTimer) < GameTime::GetGameTime())
if (criteria->TimerTime && time_t(date + criteria->TimerTime) < GameTime::GetGameTime())
continue;
CriteriaProgress& progress = m_criteriaProgress[id];
@@ -796,7 +766,7 @@ void AchievementMgr<Guild>::LoadFromDB(PreparedQueryResult achievementResult, Pr
continue;
}
if (criteria->StartTimer && time_t(date + criteria->StartTimer) < GameTime::GetGameTime())
if (criteria->TimerTime && time_t(date + criteria->TimerTime) < GameTime::GetGameTime())
continue;
CriteriaProgress& progress = m_criteriaProgress[id];
@@ -961,7 +931,7 @@ void AchievementMgr<Player>::SendCriteriaUpdate(AchievementCriteriaEntry const*
criteriaUpdate.Quantity = progress->counter;
criteriaUpdate.PlayerGUID = GetOwner()->GetGUID();
criteriaUpdate.Flags = 0;
if (entry->StartTimer)
if (entry->TimerTime)
criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
criteriaUpdate.CurrentTime = progress->date;
@@ -1179,10 +1149,10 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type,
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
AchievementCriteriaEntry const* achievementCriteria = (*i);
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->ReferredAchievement);
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->AchievementID);
if (!achievement)
{
TC_LOG_ERROR("achievement", "UpdateAchievementCriteria: Achievement %u not found!", achievementCriteria->ReferredAchievement);
TC_LOG_ERROR("achievement", "UpdateAchievementCriteria: Achievement %u not found!", achievementCriteria->AchievementID);
continue;
}
@@ -1619,18 +1589,18 @@ bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteriaEntry const* achi
case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
return progress->counter >= achievementCriteria->Amount;
return progress->counter >= achievementCriteria->Quantity;
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD:
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
return progress->counter >= 1;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
return progress->counter >= achievementCriteria->Amount;
return progress->counter >= achievementCriteria->Quantity;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
return progress->counter >= 9000;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
return achievementCriteria->Amount && progress->counter >= achievementCriteria->Amount;
return achievementCriteria->Quantity && progress->counter >= achievementCriteria->Quantity;
case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
return true;
// handle all statistic-only criteria here
@@ -1716,7 +1686,7 @@ bool AchievementMgr<T>::IsCompletedAchievement(AchievementEntry const* entry)
count += progress->counter;
// for counters, field4 contains the main count requirement
if (count >= criteria->Amount)
if (count >= criteria->Quantity)
return true;
}
return false;
@@ -1762,11 +1732,6 @@ CriteriaProgress* AchievementMgr<T>::GetCriteriaProgress(AchievementCriteriaEntr
template<class T>
void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype)
{
// Don't allow to cheat - doing timed achievements without timer active
TimedAchievementMap::iterator timedIter = m_timedAchievements.find(entry->ID);
if (entry->StartTimer && timedIter == m_timedAchievements.end())
return;
TC_LOG_DEBUG("achievement", "SetCriteriaProgress(%u, " UI64FMTD ") for (%s)",
entry->ID, changeValue, GetOwner()->GetGUID().ToString().c_str());
@@ -1775,7 +1740,7 @@ void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entr
{
// not create record for 0 counter but allow it for timed achievements
// we will need to send 0 progress to client to start the timer
if (changeValue == 0 && !entry->StartTimer)
if (changeValue == 0 && !entry->TimerTime)
return;
progress = &m_criteriaProgress[entry->ID];
@@ -1802,7 +1767,7 @@ void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entr
}
// not update (not mark as changed) if counter will have same value
if (progress->counter == newValue && !entry->StartTimer)
if (progress->counter == newValue && !entry->TimerTime)
return;
progress->counter = newValue;
@@ -1810,98 +1775,102 @@ void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entr
progress->changed = true;
progress->date = GameTime::GetGameTime(); // set the date to the latest update.
progress->CompletedGUID = referencePlayer ? referencePlayer->GetGUID() : ObjectGuid::Empty;
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(entry->ReferredAchievement);
uint32 timeElapsed = 0;
bool criteriaComplete = IsCompletedCriteria(entry, achievement);
Seconds timeElapsed = Seconds::zero();
if (entry->StartTimer)
if (entry->TimerTime)
{
// Client expects this in packet
timeElapsed = entry->StartTimer - (timedIter->second/IN_MILLISECONDS);
auto startedItr = _startedCriteria.find(entry->ID);
if (startedItr != _startedCriteria.end())
{
// Client expects this in packet
timeElapsed = duration_cast<Seconds>(Seconds(entry->TimerTime) - startedItr->second);
// Remove the timer, we wont need it anymore
if (criteriaComplete)
m_timedAchievements.erase(timedIter);
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(entry->AchievementID);
bool criteriaComplete = IsCompletedCriteria(entry, achievement);
// Remove the timer, we wont need it anymore
if (criteriaComplete)
_startedCriteria.erase(startedItr);
}
}
if (criteriaComplete && achievement->Flags & ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS && !progress->CompletedGUID)
progress->CompletedGUID = referencePlayer->GetGUID();
SendCriteriaUpdate(entry, progress, timeElapsed, criteriaComplete);
SendCriteriaUpdate(entry, progress, timeElapsed.count(), true);
}
template<class T>
void AchievementMgr<T>::UpdateTimedAchievements(uint32 timeDiff)
void AchievementMgr<T>::UpdateTimedAchievementCriteria(Milliseconds timeDiff)
{
if (!m_timedAchievements.empty())
for (auto itr = _startedCriteria.begin(); itr != _startedCriteria.end();)
{
for (TimedAchievementMap::iterator itr = m_timedAchievements.begin(); itr != m_timedAchievements.end();)
// Time is up, remove timer and reset progress
if (itr->second <= timeDiff)
{
// Time is up, remove timer and reset progress
if (itr->second <= timeDiff)
{
AchievementCriteriaEntry const* entry = sAchievementMgr->GetAchievementCriteria(itr->first);
RemoveCriteriaProgress(entry);
m_timedAchievements.erase(itr++);
}
else
{
itr->second -= timeDiff;
++itr;
}
AchievementCriteriaEntry const* entry = sAchievementMgr->GetAchievementCriteria(itr->first);
RemoveCriteriaProgress(entry);
itr = _startedCriteria.erase(itr);
}
else
{
itr->second -= timeDiff;
++itr;
}
}
}
template<class T>
void AchievementMgr<T>::StartTimedAchievement(AchievementCriteriaTimedTypes /*type*/, uint32 /*entry*/, uint32 /*timeLost = 0*/)
void AchievementMgr<T>::StartAchievementCriteria(AchievementCriteriaStartEvent /*startEvent*/, uint32 /*entry*/, Milliseconds /*timeLost = Milliseconds::zero() */)
{
}
template<>
void AchievementMgr<Player>::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost /* = 0 */)
void AchievementMgr<Player>::StartAchievementCriteria(AchievementCriteriaStartEvent startEvent, uint32 asset, Milliseconds timeLost /*= Milliseconds::zero()*/)
{
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
AchievementCriteriaEntryList const* criteriaList = sAchievementMgr->GetAchievementCriteriaByStartEvent(startEvent, asset);
if (!criteriaList)
return;
for (AchievementCriteriaEntry const* criteria : *criteriaList)
{
if ((*i)->StartAsset != entry)
Milliseconds timeLimit = Milliseconds::max(); // this value is for criteria that have a start event requirement but no time limit
if (criteria->TimerTime)
timeLimit = Seconds(criteria->TimerTime);
timeLimit -= timeLost;
if (timeLimit <= Milliseconds::zero())
continue;
AchievementEntry const* achievement = sAchievementMgr->GetAchievement((*i)->ReferredAchievement);
if (m_timedAchievements.find((*i)->ID) == m_timedAchievements.end() && !IsCompletedCriteria(*i, achievement))
{
// Start the timer
if ((*i)->StartTimer * IN_MILLISECONDS > timeLost)
{
m_timedAchievements[(*i)->ID] = (*i)->StartTimer * IN_MILLISECONDS - timeLost;
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->AchievementID);
bool canStart = !IsCompletedCriteria(criteria, achievement);
// and at client too
SetCriteriaProgress(*i, 0, GetOwner(), PROGRESS_SET);
}
if (!canStart)
continue;
auto [itr, isNew] = _startedCriteria.try_emplace(criteria->ID, timeLimit);
if (!isNew)
{
if (!(criteria->Flags & ACHIEVEMENT_CRITERIA_FLAG_HIDDEN))
continue;
itr->second = timeLimit;
}
SetCriteriaProgress(criteria, 0, GetOwner(), PROGRESS_SET);
}
}
template<class T>
void AchievementMgr<T>::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
void AchievementMgr<T>::FailAchievementCriteria(AchievementCriteriaFailEvent failEvent, uint32 asset)
{
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
AchievementCriteriaEntryList const* criteriaList = sAchievementMgr->GetAchievementCriteriaByFailEvent(failEvent, asset);
if (!criteriaList)
return;
for (AchievementCriteriaEntry const* criteria : *criteriaList)
{
if ((*i)->StartAsset != entry)
continue;
TimedAchievementMap::iterator timedIter = m_timedAchievements.find((*i)->ID);
// We don't have timer for this achievement
if (timedIter == m_timedAchievements.end())
continue;
// remove progress
RemoveCriteriaProgress(*i);
// Remove the timer
m_timedAchievements.erase(timedIter);
_startedCriteria.erase(criteria->ID);
RemoveCriteriaProgress(criteria);
}
}
@@ -2360,13 +2329,6 @@ bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteriaEntry const* criter
return false;
}
if (achievement->MapID != -1 && referencePlayer->GetMapId() != uint32(achievement->MapID))
{
TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s Achievement %u) Wrong map",
criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Type), achievement->ID);
return false;
}
if ((achievement->Faction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) ||
(achievement->Faction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE))
{
@@ -2403,36 +2365,18 @@ bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteriaEntry const* criter
return false;
}
if (criteria->RequiredWorldStateID != 0)
if (sWorldStateMgr->GetValue(criteria->RequiredWorldStateID, referencePlayer->GetMap()) != criteria->RequiredWorldStateValue)
return false;
return true;
}
template<class T>
bool AchievementMgr<T>::ConditionsSatisfied(AchievementCriteriaEntry const* criteria, Player* referencePlayer) const
bool AchievementMgr<T>::ConditionsSatisfied(AchievementCriteriaEntry const* criteria, Player* /*referencePlayer*/) const
{
for (uint32 i = 0; i < MAX_CRITERIA_REQUIREMENTS; ++i)
{
if (!criteria->AdditionalRequirements[i].Type)
continue;
switch (criteria->AdditionalRequirements[i].Type)
{
case ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP:
if (referencePlayer->GetMapId() != criteria->AdditionalRequirements[i].Asset)
return false;
break;
case ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP:
if (referencePlayer->GetGroup())
return false;
break;
default:
break;
}
}
if (criteria->RequiredWorldStateID != 0)
if (Map* map = referencePlayer->GetMap())
if (map->GetWorldStateValue(criteria->RequiredWorldStateID) != criteria->RequiredWorldStateValue)
return false;
if (criteria->StartEvent && !_startedCriteria.contains(criteria->ID))
return false;
return true;
}
@@ -2548,7 +2492,7 @@ bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const* ac
bool notfit = false;
for (int j = 0; j < MAX_ARENA_SLOT; ++j)
{
if (achievIdByArenaSlot[j] == achievementCriteria->ReferredAchievement)
if (achievIdByArenaSlot[j] == achievementCriteria->AchievementID)
{
Battleground* bg = referencePlayer->GetBattleground();
if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j)
@@ -2573,7 +2517,7 @@ bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const* ac
bool found = false;
for (int j = 0; achievIdForDungeon[j][0]; ++j)
{
if (achievIdForDungeon[j][0] == achievementCriteria->ReferredAchievement)
if (achievIdForDungeon[j][0] == achievementCriteria->AchievementID)
{
if (map->IsRaid())
{
@@ -2736,9 +2680,9 @@ bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const* ac
if (!miscValue1)
return false;
if (achievementCriteria->AdditionalRequirements[0].Type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
if (AchievementCriteriaFailEvent(achievementCriteria->FailEvent) == AchievementCriteriaFailEvent::LeaveBattleground)
{
if (referencePlayer->GetMapId() != achievementCriteria->AdditionalRequirements[0].Asset)
if (!referencePlayer->InBattleground())
return false;
// map specific case (BG in fact) expected player targeted damage/heal
@@ -2979,7 +2923,7 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry
}
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_COMPLETE_QUEST_NOT_IN_GROUP: // 35
{
if (referencePlayer->IsInGroup())
if (referencePlayer->GetGroup())
return false;
break;
}
@@ -3377,6 +3321,16 @@ AchievementCriteriaEntryList const& AchievementGlobalMgr::GetAchievementCriteria
}
}
AchievementCriteriaEntryList const* AchievementGlobalMgr::GetAchievementCriteriaByStartEvent(AchievementCriteriaStartEvent startEvent, int32 asset) const
{
return Trinity::Containers::MapGetValuePtr(_criteriasByStartEvent[size_t(startEvent)], asset);
}
AchievementCriteriaEntryList const* AchievementGlobalMgr::GetAchievementCriteriaByFailEvent(AchievementCriteriaFailEvent startEvent, int32 asset) const
{
return Trinity::Containers::MapGetValuePtr(_criteriasByFailEvent[size_t(startEvent)], asset);
}
bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement) const
{
auto itr = _allCompletedAchievements.find(achievement->ID);
@@ -3406,6 +3360,21 @@ void AchievementGlobalMgr::SetRealmCompleted(AchievementEntry const* achievement
_allCompletedAchievements[achievement->ID] = GameTime::GetGameTimeSystemPoint();
}
inline AchievementCriteriaStartEvent ToStartEvent(uint32 timedStartEvent)
{
switch (static_cast<AchievementCriteriaTimerStartEvent>(timedStartEvent))
{
case AchievementCriteriaTimerStartEvent::SendEvent: return AchievementCriteriaStartEvent::SendEvent;
case AchievementCriteriaTimerStartEvent::AcceptQuest: return AchievementCriteriaStartEvent::AcceptQuest;
case AchievementCriteriaTimerStartEvent::CastSpell: return AchievementCriteriaStartEvent::CastSpell;
case AchievementCriteriaTimerStartEvent::GainAura: return AchievementCriteriaStartEvent::GainAura;
case AchievementCriteriaTimerStartEvent::KillNPC: return AchievementCriteriaStartEvent::KillNPC;
case AchievementCriteriaTimerStartEvent::UseItem: return AchievementCriteriaStartEvent::UseItem;
default:
return AchievementCriteriaStartEvent::None;
}
}
//==========================================================
void AchievementGlobalMgr::LoadAchievementCriteriaList()
{
@@ -3428,9 +3397,9 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
ASSERT(criteria->Type < ACHIEVEMENT_CRITERIA_TYPE_TOTAL, "ACHIEVEMENT_CRITERIA_TYPE_TOTAL must be greater than or equal to %u but is currently equal to %u",
criteria->Type + 1, ACHIEVEMENT_CRITERIA_TYPE_TOTAL);
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->ReferredAchievement);
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->AchievementID);
m_AchievementCriteriaListByAchievement[criteria->ReferredAchievement].push_back(criteria);
m_AchievementCriteriaListByAchievement[criteria->AchievementID].push_back(criteria);
bool guild = false;
if (achievement && achievement->Flags & ACHIEVEMENT_FLAG_GUILD)
@@ -3466,27 +3435,19 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
}
}
for (uint32 i = 0; i < MAX_CRITERIA_REQUIREMENTS; ++i)
{
if (criteria->AdditionalRequirements[i].Type != ACHIEVEMENT_CRITERIA_CONDITION_NONE)
{
ASSERT(criteria->AdditionalRequirements[i].Type < ACHIEVEMENT_CRITERIA_CONDITION_MAX,
"ACHIEVEMENT_CRITERIA_CONDITION_MAX must be greater than or equal to %u but is currently equal to %u",
criteria->AdditionalRequirements[i].Type + 1, ACHIEVEMENT_CRITERIA_CONDITION_MAX);
if (criteria->StartEvent)
_criteriasByStartEvent[criteria->StartEvent][criteria->StartAsset].push_back(criteria);
if (i == 0
|| criteria->AdditionalRequirements[i].Type != criteria->AdditionalRequirements[i - 1].Type
|| criteria->AdditionalRequirements[i].Asset != criteria->AdditionalRequirements[i - 1].Asset)
m_AchievementCriteriasByCondition[criteria->AdditionalRequirements[i].Type][criteria->AdditionalRequirements[i].Asset].push_back(criteria);
}
// Timed criterias use a own event definition which is name-identical with StartEvent so we translate it and add the criterias to the StartEvent container
if (criteria->TimerStartEvent)
{
AchievementCriteriaStartEvent startEvent = ToStartEvent(criteria->TimerStartEvent);
if (startEvent != AchievementCriteriaStartEvent::None)
_criteriasByStartEvent[AsUnderlyingType(startEvent)][criteria->TimerAsset].push_back(criteria);
}
if (criteria->StartTimer)
{
ASSERT(criteria->StartEvent < ACHIEVEMENT_TIMED_TYPE_MAX, "ACHIEVEMENT_TIMED_TYPE_MAX must be greater than or equal to %u but is currently equal to %u",
criteria->StartEvent + 1, ACHIEVEMENT_TIMED_TYPE_MAX);
m_AchievementCriteriasByTimedType[criteria->StartEvent].push_back(criteria);
}
if (criteria->FailEvent)
_criteriasByFailEvent[criteria->FailEvent][criteria->FailAsset].push_back(criteria);
}
TC_LOG_INFO("server.loading", ">> Loaded %u achievement criteria and %u guild achievement crieteria in %u ms.", criterias, guildCriterias, GetMSTimeDiffToNow(oldMSTime));
+9 -19
View File
@@ -36,7 +36,6 @@ typedef std::vector<AchievementEntry const*> AchievementEntryList;
typedef std::unordered_map<uint32, AchievementCriteriaEntryList> AchievementCriteriaListByAchievement;
typedef std::unordered_map<uint32, AchievementCriteriaEntryList> AchievementCriteriaListByMiscValue;
typedef std::unordered_map<uint32, AchievementCriteriaEntryList> AchievementCriteriaListByCondition;
typedef std::unordered_map<uint32, AchievementEntryList> AchievementListByReferencedId;
struct CriteriaProgress
@@ -266,7 +265,6 @@ class TC_GAME_API AchievementMgr
static void DeleteFromDB(ObjectGuid lowguid);
void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
void SaveToDB(CharacterDatabaseTransaction& trans);
void ResetAchievementCriteria(AchievementCriteriaCondition condition, uint64 value, bool evenIfCriteriaComplete);
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, WorldObject const* ref = nullptr, Player* referencePlayer = nullptr, GameObject* go = nullptr);
void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer);
void CheckAllAchievementCriteria(Player* referencePlayer);
@@ -277,9 +275,9 @@ class TC_GAME_API AchievementMgr
CompletedAchievementData* GetCompletedDataForAchievement(uint32 achievementId);
T* GetOwner() const { return _owner; }
void UpdateTimedAchievements(uint32 timeDiff);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry); // used for quest and scripted timed achievements
void UpdateTimedAchievementCriteria(Milliseconds timeDiff);
void StartAchievementCriteria(AchievementCriteriaStartEvent startEvent, uint32 asset, Milliseconds timeLost = Milliseconds::zero());
void FailAchievementCriteria(AchievementCriteriaFailEvent failEvent, uint32 asset);
uint32 GetAchievementPoints() const { return _achievementPoints; }
private:
@@ -301,9 +299,9 @@ class TC_GAME_API AchievementMgr
T* _owner;
CriteriaProgressMap m_criteriaProgress;
CompletedAchievementMap m_completedAchievements;
typedef std::map<uint32, uint32> TimedAchievementMap;
TimedAchievementMap m_timedAchievements; // Criteria id/time left in MS
uint32 _achievementPoints;
std::unordered_map<uint32 /*criteriaID*/, Milliseconds /*time left*/> _startedCriteria;
};
class TC_GAME_API AchievementGlobalMgr
@@ -319,16 +317,9 @@ class TC_GAME_API AchievementGlobalMgr
AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type, uint32 miscValue, bool guild = false) const;
AchievementCriteriaEntryList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
{
return m_AchievementCriteriasByTimedType[type];
}
AchievementCriteriaEntryList const* GetAchievementCriteriaByStartEvent(AchievementCriteriaStartEvent startEvent, int32 asset) const;
AchievementCriteriaEntryList const* GetAchievementCriteriaByCondition(AchievementCriteriaCondition condition, uint32 val)
{
AchievementCriteriaListByCondition::const_iterator itr = m_AchievementCriteriasByCondition[condition].find(val);
return itr != m_AchievementCriteriasByCondition[condition].end() ? &itr->second : nullptr;
}
AchievementCriteriaEntryList const* GetAchievementCriteriaByFailEvent(AchievementCriteriaFailEvent startEvent, int32 asset) const;
AchievementCriteriaEntryList const* GetAchievementCriteriaByAchievement(uint32 id) const
{
@@ -399,9 +390,8 @@ class TC_GAME_API AchievementGlobalMgr
AchievementCriteriaListByMiscValue m_AchievementCriteriasByMiscValue[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
AchievementCriteriaListByMiscValue m_GuildAchievementCriteriasByMiscValue[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
AchievementCriteriaEntryList m_AchievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
AchievementCriteriaListByCondition m_AchievementCriteriasByCondition[ACHIEVEMENT_CRITERIA_CONDITION_MAX];
std::unordered_map<int32, AchievementCriteriaEntryList> _criteriasByStartEvent[size_t(AchievementCriteriaStartEvent::Count)];
std::unordered_map<int32, AchievementCriteriaEntryList> _criteriasByFailEvent[size_t(AchievementCriteriaFailEvent::Count)];
// store achievement criterias by achievement to speed up lookup
AchievementCriteriaListByAchievement m_AchievementCriteriaListByAchievement;
+2 -1
View File
@@ -309,6 +309,7 @@ void Arena::EndBattleground(uint32 winner)
{
// update achievement BEFORE personal rating update
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
player->StartAchievementCriteria(AchievementCriteriaStartEvent::WinRankedArenaMatchWithTeamSize, 0);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId());
player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD));
@@ -335,7 +336,7 @@ void Arena::EndBattleground(uint32 winner)
loserArenaTeam->MemberLost(player, winnerMatchmakerRating, loserMatchmakerChange);
// Arena lost => reset the win_rated_arena having the "no_lose" condition
player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE, 0);
player->FailAchievementCriteria(AchievementCriteriaFailEvent::LoseRankedArenaMatchWithTeamSize, 0);
}
}
@@ -534,6 +534,10 @@ inline void Battleground::_ProcessJoin(uint32 diff)
SetStatus(STATUS_IN_PROGRESS);
SetStartDelayTime(StartDelayTimes[BG_STARTING_EVENT_FOURTH]);
for (auto const& [guid, _] : GetPlayers())
if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), guid))
player->StartAchievementCriteria(AchievementCriteriaStartEvent::StartBattleground, GetBgMap()->GetId());
// Remove preparation
if (isArena())
{
@@ -1021,7 +1025,7 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen
player->SetBGTeam(0);
// remove all criterias on bg leave
player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
player->FailAchievementCriteria(AchievementCriteriaFailEvent::LeaveBattleground, 0);
player->RemoveBattlegroundQueueJoinTime(bgTypeId);
@@ -1141,9 +1145,6 @@ void Battleground::AddPlayer(Player* player)
}
}
// reset all map criterias on map enter
player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
// setup BG group membership
PlayerAddedToBGCheckIfBGIsRunning(player);
AddOrSetPlayerToCorrectBgGroup(player, team);
@@ -567,7 +567,7 @@ void BattlegroundTP::EventPlayerClickedOnFlag(Player* player, GameObject* target
UpdateFlagState(HORDE, BG_TP_FLAG_STATE_ON_PLAYER);
UpdateWorldState(BG_TP_FLAG_UNK_ALLIANCE, 1);
player->CastSpell(player, BG_TP_SPELL_ALLIANCE_FLAG, true);
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_TP_SPELL_ALLIANCE_FLAG_PICKED);
player->StartAchievementCriteria(AchievementCriteriaStartEvent::BeSpellTarget, BG_TP_SPELL_ALLIANCE_FLAG_PICKED);
if (_flagState[1] == BG_TP_FLAG_STATE_ON_PLAYER)
_bothFlagsKept = true;
}
@@ -585,7 +585,7 @@ void BattlegroundTP::EventPlayerClickedOnFlag(Player* player, GameObject* target
UpdateFlagState(ALLIANCE, BG_TP_FLAG_STATE_ON_PLAYER);
UpdateWorldState(BG_TP_FLAG_UNK_HORDE, 1);
player->CastSpell(player, BG_TP_SPELL_HORDE_FLAG, true);
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_TP_SPELL_HORDE_FLAG_PICKED);
player->StartAchievementCriteria(AchievementCriteriaStartEvent::BeSpellTarget, BG_TP_SPELL_HORDE_FLAG_PICKED);
if (_flagState[0] == BG_TP_FLAG_STATE_ON_PLAYER)
_bothFlagsKept = true;
}
@@ -464,7 +464,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* target
//update world state to show correct flag carrier
UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER);
player->CastSpell(player, BG_WS_SPELL_SILVERWING_FLAG, true);
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED);
player->StartAchievementCriteria(AchievementCriteriaStartEvent::BeSpellTarget, BG_WS_SPELL_SILVERWING_FLAG_PICKED);
if (_flagState[1] == BG_WS_FLAG_STATE_ON_PLAYER)
_bothFlagsKept = true;
}
@@ -481,7 +481,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* target
//update world state to show correct flag carrier
UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER);
player->CastSpell(player, BG_WS_SPELL_WARSONG_FLAG, true);
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED);
player->StartAchievementCriteria(AchievementCriteriaStartEvent::BeSpellTarget, BG_WS_SPELL_WARSONG_FLAG_PICKED);
if (_flagState[0] == BG_WS_FLAG_STATE_ON_PLAYER)
_bothFlagsKept = true;
}
+49 -26
View File
@@ -100,26 +100,9 @@ enum AchievementFlags
enum AchievementCriteriaLimits
{
MAX_CRITERIA_REQUIREMENTS = 2,
MAX_ADDITIONAL_CRITERIA_CONDITIONS = 3
};
enum AchievementCriteriaCondition
{
ACHIEVEMENT_CRITERIA_CONDITION_NONE = 0,
ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH = 1, // reset progress on death
ACHIEVEMENT_CRITERIA_CONDITION_UNK2 = 2, // only used in "Complete a daily quest every day for five consecutive days"
ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP = 3, // requires you to be on specific map, reset at change
ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE = 4, // only used in "Win 10 arenas without losing"
ACHIEVEMENT_CRITERIA_CONDITION_UNK5 = 5, // Have spell?
ACHIEVEMENT_CRITERIA_CONDITION_UNK8 = 8,
ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT = 9, // requires the player not to be hit by specific spell
ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP = 10, // requires the player not to be in group
ACHIEVEMENT_CRITERIA_CONDITION_UNK13 = 13, // unk
ACHIEVEMENT_CRITERIA_CONDITION_MAX
};
enum AchievementCriteriaAdditionalCondition
{
ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_DRUNK_VALUE = 1,
@@ -180,17 +163,57 @@ enum AchievementCriteriaFlags
ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER = 0x00000020 // Displays counter as money
};
enum AchievementCriteriaTimedTypes : uint8
enum class AchievementCriteriaFailEvent : uint8
{
ACHIEVEMENT_TIMED_TYPE_EVENT = 1, // Timer is started by internal event with id in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_QUEST = 2, // Timer is started by accepting quest with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER = 5, // Timer is started by casting a spell with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET = 6, // Timer is started by being target of spell with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_CREATURE = 7, // Timer is started by killing creature with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_ITEM = 9, // Timer is started by using item with entry in timerStartEvent
ACHIEVEMENT_TIMED_TYPE_UNK = 10, // Unknown
None = 0,
Death = 1, // Death
Hours24WithoutCompletingDailyQuest = 2, // 24 hours without completing a daily quest
LeaveBattleground = 3, // Leave a battleground
LoseRankedArenaMatchWithTeamSize = 4, // Lose a ranked arena match with team size {#Team Size}
LoseAura = 5, // Lose aura "{Spell}"
GainAura = 6, // Gain aura "{Spell}"
GainAuraEffect = 7, // Gain aura effect "{SpellAuraNames.EnumID}"
CastSpell = 8, // Cast spell "{Spell}"
BeSpellTarget = 9, // Have spell "{Spell}" cast on you
ModifyPartyStatus = 10, // Modify your party status
ACHIEVEMENT_TIMED_TYPE_MAX
Count
};
enum class AchievementCriteriaStartEvent : uint8
{
None = 0, // - NONE -
ReachLevel = 1, // Reach level {#Level}
CompleteDailyQuest = 2, // Complete daily quest "{QuestV2}"
StartBattleground = 3, // Start battleground "{Map}"
WinRankedArenaMatchWithTeamSize = 4, // Win a ranked arena match with team size {#Team Size}
GainAura = 5, // Gain aura "{Spell}"
GainAuraEffect = 6, // Gain aura effect "{SpellAuraNames.EnumID}"
CastSpell = 7, // Cast spell "{Spell}"
BeSpellTarget = 8, // Have spell "{Spell}" cast on you
AcceptQuest = 9, // Accept quest "{QuestV2}"
KillNPC = 10, // Kill NPC "{Creature}"
KillPlayer = 11, // Kill player
UseItem = 12, // Use item "{Item}"
SendEvent = 13, // Send event "{GameEvents}" (player-sent/instance only)
Count
};
enum class AchievementCriteriaTimerStartEvent : uint8
{
None = 0,
SendEvent = 1,
AcceptQuest = 2,
Unused3 = 3,
Unused4 = 4,
CastSpell = 5,
GainAura = 6,
KillNPC = 7,
Unused8 = 8,
UseItem = 9,
Count
};
enum AchievementCriteriaTypes : uint8
+12 -18
View File
@@ -58,7 +58,7 @@ struct AchievementCategoryEntry
struct AchievementCriteriaEntry
{
uint32 ID; // 0
uint32 ReferredAchievement; // 1
uint32 AchievementID; // 1
uint32 Type; // 2
union
@@ -164,25 +164,19 @@ struct AchievementCriteriaEntry
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138
uint32 GuildChallengeType;
} Asset;
uint64 Amount;
struct
{
uint32 Type;
uint32 Asset;
} AdditionalRequirements[MAX_CRITERIA_REQUIREMENTS];
} Asset; // 3
uint64 Quantity; // 4
uint32 StartEvent; // 5
int32 StartAsset; // 6
uint32 FailEvent; // 7
int32 FailAsset; // 8
char* Description; // 9
uint32 Flags; // 10
uint32 StartEvent; // 11 Only appears with timed achievements, seems to be the type of starting a timed Achievement, only type 1 and some of type 6 need manual starting
// 1: ByEventId(?) (serverside IDs), 2: ByQuestId, 5: ByCastSpellId(?)
// 6: BySpellIdTarget(some of these are unknown spells, some not, some maybe spells)
// 7: ByKillNpcId, 9: ByUseItemId
uint32 StartAsset; // 12 Alway appears with timed events, used internally to start the achievement, store
uint32 StartTimer; // 13 time limit in seconds
uint32 OrderIndex; // 14 also used in achievement shift-links as index in state bitmask
uint32 Flags; // 10
uint32 TimerStartEvent; // 11
uint32 TimerAsset; // 12
uint32 TimerTime; // 13
uint32 OrderIndex; // 14
uint32 RequiredWorldStateID; // 15
int32 RequiredWorldStateValue; // 16
uint32 AdditionalConditionType[MAX_ADDITIONAL_CRITERIA_CONDITIONS]; // 17-19
+11 -14
View File
@@ -1031,7 +1031,7 @@ void Player::Update(uint32 p_time)
}
}
m_achievementMgr->UpdateTimedAchievements(p_time);
m_achievementMgr->UpdateTimedAchievementCriteria(Milliseconds(p_time));
if (HasUnitState(UNIT_STATE_MELEE_ATTACKING) && !HasUnitState(UNIT_STATE_CASTING))
{
@@ -1350,7 +1350,7 @@ void Player::setDeathState(DeathState s)
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1);
// reset all death criterias
ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH, 0);
FailAchievementCriteria(AchievementCriteriaFailEvent::Death, 0);
}
Unit::setDeathState(s);
@@ -2340,6 +2340,7 @@ void Player::GiveLevel(uint8 level)
CharacterDatabase.CommitTransaction(trans);
}
StartAchievementCriteria(AchievementCriteriaStartEvent::ReachLevel, level);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL);
// Refer-A-Friend
@@ -14188,7 +14189,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
m_QuestStatusSave[quest_id] = QUEST_DEFAULT_SAVE_TYPE;
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest_id);
StartAchievementCriteria(AchievementCriteriaStartEvent::AcceptQuest, quest_id);
SendQuestUpdate(quest_id);
@@ -14409,6 +14410,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
SetDailyQuestStatus(quest_id);
if (quest->IsDaily())
{
StartAchievementCriteria(AchievementCriteriaStartEvent::CompleteDailyQuest, 0);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, quest_id);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY, quest_id);
}
@@ -15653,7 +15655,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E
real_entry = killed->GetEntry();
}
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_CREATURE, real_entry); // MUST BE CALLED FIRST
StartAchievementCriteria(AchievementCriteriaStartEvent::KillNPC, real_entry); // MUST BE CALLED FIRST
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addkillcount, 0, killed);
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
@@ -15709,6 +15711,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E
void Player::KilledPlayerCredit(uint16 count)
{
StartAchievementCriteria(AchievementCriteriaStartEvent::KillPlayer, 0);
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
{
uint32 questid = GetQuestSlotQuestId(i);
@@ -23357,7 +23360,6 @@ void Player::ResetWeeklyQuestStatus()
m_weeklyquests.clear();
// DB data deleted in caller
m_WeeklyQuestChanged = false;
}
void Player::ResetSeasonalQuestStatus(uint16 event_id, time_t eventStartTime)
@@ -25319,19 +25321,14 @@ bool Player::HasAchieved(uint32 achievementId) const
return m_achievementMgr->HasAchieved(achievementId);
}
void Player::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost/* = 0*/)
void Player::StartAchievementCriteria(AchievementCriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost/* = Milliseconds::zero()*/)
{
m_achievementMgr->StartTimedAchievement(type, entry, timeLost);
m_achievementMgr->StartAchievementCriteria(startEvent, entry, timeLost);
}
void Player::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
void Player::FailAchievementCriteria(AchievementCriteriaFailEvent failEvent, int32 failAsset)
{
m_achievementMgr->RemoveTimedAchievement(type, entry);
}
void Player::ResetAchievementCriteria(AchievementCriteriaCondition condition, uint64 value, bool evenIfCriteriaComplete /* = false*/)
{
m_achievementMgr->ResetAchievementCriteria(condition, value, evenIfCriteriaComplete);
m_achievementMgr->FailAchievementCriteria(failEvent, failAsset);
}
void Player::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, WorldObject* ref /*= nullptr*/, GameObject* go /*= nullptr*/)
+2 -3
View File
@@ -2324,10 +2324,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 GetAchievementPoints() const;
bool HasAchieved(uint32 achievementId) const;
void ResetAchievements();
void ResetAchievementCriteria(AchievementCriteriaCondition condition, uint64 value, bool evenIfCriteriaComplete = false);
void FailAchievementCriteria(AchievementCriteriaFailEvent condition, int32 failAsset);
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, WorldObject* ref = nullptr, GameObject* go = nullptr);
void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
void StartAchievementCriteria(AchievementCriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost = Milliseconds::zero());
void CompletedAchievement(AchievementEntry const* entry);
bool HasTitle(uint32 bitIndex) const;
+17
View File
@@ -3167,8 +3167,14 @@ void Unit::_ApplyAura(AuraApplication* aurApp, uint8 effMask)
}
if (Player* player = ToPlayer())
{
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
player->UpdateVisibleGameobjectsOrSpellClicks();
player->FailAchievementCriteria(AchievementCriteriaFailEvent::GainAura, aurApp->GetBase()->GetId());
player->StartAchievementCriteria(AchievementCriteriaStartEvent::GainAura, aurApp->GetBase()->GetId());
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, aurApp->GetBase()->GetId());
}
}
// removes aura application from lists and unapplies effects
@@ -3246,9 +3252,13 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveFlags removeM
aura->HandleAuraSpecificMods(aurApp, caster, false, false);
if (Player* player = ToPlayer())
{
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
player->UpdateVisibleGameobjectsOrSpellClicks();
player->FailAchievementCriteria(AchievementCriteriaFailEvent::LoseAura, aurApp->GetBase()->GetId());
}
i = m_appliedAuras.begin();
}
@@ -3309,7 +3319,14 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura)
void Unit::_RegisterAuraEffect(AuraEffect* aurEff, bool apply)
{
if (apply)
{
m_modAuras[aurEff->GetAuraType()].push_back(aurEff);
if (Player* player = ToPlayer())
{
player->StartAchievementCriteria(AchievementCriteriaStartEvent::GainAuraEffect, aurEff->GetAuraType());
player->FailAchievementCriteria(AchievementCriteriaFailEvent::GainAuraEffect, aurEff->GetAuraType());
}
}
else
m_modAuras[aurEff->GetAuraType()].remove(aurEff);
}
+1 -1
View File
@@ -56,7 +56,7 @@ void GameEvents::TriggerForPlayer(uint32 gameEventId, Player* source)
{
Map* map = source->GetMap();
if (map->Instanceable())
source->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, gameEventId);
source->StartAchievementCriteria(AchievementCriteriaStartEvent::SendEvent, gameEventId);
}
void GameEvents::TriggerForMap(uint32 gameEventId, Map* map, WorldObject* source, WorldObject* target)
+5
View File
@@ -499,6 +499,8 @@ bool Group::AddMember(Player* player)
if (isRaidGroup())
player->UpdateVisibleGameobjectsOrSpellClicks();
player->FailAchievementCriteria(AchievementCriteriaFailEvent::ModifyPartyStatus, 0);
{
// Broadcast new player group member fields to rest of the group
player->SetFieldNotifyFlag(UF_FLAG_PARTY_MEMBER);
@@ -579,6 +581,9 @@ bool Group::RemoveMember(ObjectGuid guid, const RemoveMethod& method /*= GROUP_R
if (isLFGGroup() && method == GROUP_REMOVEMETHOD_KICK)
return !m_memberSlots.empty();
if (player)
player->FailAchievementCriteria(AchievementCriteriaFailEvent::ModifyPartyStatus, 0);
// remove member and change leader (if need) only if strong more 2 members _before_ member remove (BG/BF allow 1 member group)
if (GetMembersCount() > ((isBGGroup() || isLFGGroup() || isBFGroup()) ? 1u : 2u))
{
@@ -409,7 +409,6 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemove
_player->TakeQuestSourceItem(questId, true); // remove quest src item from player
_player->AbandonQuest(questId); // remove all quest items player received before abandoning quest. Note, this does not remove normal drop items that happen to be quest requirements.
_player->RemoveActiveQuest(questId);
_player->RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, questId);
TC_LOG_INFO("network", "Player %u abandoned quest %u", _player->GetGUID().GetCounter(), questId);
+20 -22
View File
@@ -22,6 +22,7 @@
#include "CreatureAIImpl.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
#include "GameEventSender.h"
#include "GameObject.h"
#include "Group.h"
#include "Guild.h"
@@ -121,6 +122,25 @@ ObjectGuid InstanceScript::GetGuidData(uint32 type) const
return GetObjectGuid(type);
}
void InstanceScript::TriggerGameEvent(uint32 gameEventId, WorldObject* source /*= nullptr*/, WorldObject* target /*= nullptr*/)
{
if (source)
{
ZoneScript::TriggerGameEvent(gameEventId, source, target);
return;
}
ProcessEvent(target, gameEventId, source);
instance->DoOnPlayers([gameEventId](Player* player)
{
GameEvents::TriggerForPlayer(gameEventId, player);
});
GameEvents::TriggerForMap(gameEventId, instance);
}
Creature* InstanceScript::GetCreature(uint32 type)
{
return instance->GetCreature(GetObjectGuid(type));
@@ -611,28 +631,6 @@ void InstanceScript::DoUpdateAchievementCriteria(AchievementCriteriaTypes type,
player->UpdateAchievementCriteria(type, miscValue1, miscValue2, 0, unit);
}
// Start timed achievement for all players in instance
void InstanceScript::DoStartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
{
Map::PlayerList const& PlayerList = instance->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->GetSource())
player->StartTimedAchievement(type, entry);
}
// Stop timed achievement for all players in instance
void InstanceScript::DoStopTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
{
Map::PlayerList const& PlayerList = instance->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->GetSource())
player->RemoveTimedAchievement(type, entry);
}
// Remove Auras due to Spell on all players in instance
void InstanceScript::DoRemoveAurasDueToSpellOnPlayers(uint32 spell)
{
+5 -5
View File
@@ -40,8 +40,8 @@ class Player;
class Unit;
class WorldPacket;
enum AchievementCriteriaTypes : uint8;
enum AchievementCriteriaTimedTypes : uint8;
enum EncounterCreditType : uint8;
enum class AchievementCriteriaStartEvent : uint8;
enum EncounterFrameType
{
@@ -187,6 +187,10 @@ class TC_GAME_API InstanceScript : public ZoneScript
ObjectGuid GetObjectGuid(uint32 type) const;
virtual ObjectGuid GetGuidData(uint32 type) const override;
// Triggers a GameEvent
// * If source is nullptr then event is triggered for each player in the instance as "source"
void TriggerGameEvent(uint32 gameEventId, WorldObject* source = nullptr, WorldObject* target = nullptr) override;
Creature* GetCreature(uint32 type);
GameObject* GetGameObject(uint32 type);
@@ -214,10 +218,6 @@ class TC_GAME_API InstanceScript : public ZoneScript
// Update Achievement Criteria for all players in instance
void DoUpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = nullptr);
// Start/Stop Timed Achievement Criteria for all players in instance
void DoStartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
void DoStopTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
// Remove Auras due to Spell on all players in instance
void DoRemoveAurasDueToSpellOnPlayers(uint32 spell);
+9
View File
@@ -25,6 +25,7 @@
#include "GridDefines.h"
#include "GridRefManager.h"
#include "MapDefines.h"
#include "MapReference.h"
#include "MapRefManager.h"
#include "MPSCQueue.h"
#include "ObjectGuid.h"
@@ -335,6 +336,14 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
typedef MapRefManager PlayerList;
PlayerList const& GetPlayers() const { return m_mapRefManager; }
template <typename T>
void DoOnPlayers(T&& fn)
{
for (MapReference const& ref : GetPlayers())
if (Player* player = ref.GetSource())
fn(player);
}
//per-map script storage
void ScriptsStart(std::map<uint32, std::multimap<uint32, ScriptInfo>> const& scripts, uint32 id, Object* source, Object* target);
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
+17
View File
@@ -17,8 +17,25 @@
#include "ZoneScript.h"
#include "Creature.h"
#include "GameEventSender.h"
ZoneScript::ZoneScript()
{
}
ZoneScript::~ZoneScript()
{
}
uint32 ZoneScript::GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data)
{
return data->id;
}
void ZoneScript::TriggerGameEvent(uint32 gameEventId, WorldObject* source /*= nullptr*/, WorldObject* target /*= nullptr*/)
{
if (source)
GameEvents::Trigger(gameEventId, source, target);
else
ProcessEvent(nullptr, gameEventId, nullptr);
}
+3 -2
View File
@@ -30,8 +30,8 @@ struct CreatureData;
class TC_GAME_API ZoneScript
{
public:
ZoneScript() { }
virtual ~ZoneScript() { }
ZoneScript();
virtual ~ZoneScript();
virtual uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data);
virtual uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) { return entry; }
@@ -55,6 +55,7 @@ class TC_GAME_API ZoneScript
virtual uint32 GetData(uint32 /*DataId*/) const { return 0; }
virtual void SetData(uint32 /*DataId*/, uint32 /*Value*/) { }
virtual void TriggerGameEvent(uint32 gameEventId, WorldObject* source = nullptr, WorldObject* target = nullptr);
virtual void ProcessEvent(WorldObject* /*obj*/, uint32 /*eventId*/, WorldObject* /*invoker*/) { }
};
+5 -6
View File
@@ -2930,16 +2930,13 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, bool scaleAura, TargetInfo&
if (Player* player = unit->ToPlayer())
{
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id);
player->FailAchievementCriteria(AchievementCriteriaFailEvent::BeSpellTarget, m_spellInfo->Id);
player->StartAchievementCriteria(AchievementCriteriaStartEvent::BeSpellTarget, m_spellInfo->Id);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, 0, m_caster);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
}
if (Player* player = m_caster->ToPlayer())
{
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER, m_spellInfo->Id);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, 0, unit);
}
if (m_caster != unit)
{
@@ -3669,10 +3666,12 @@ void Spell::_cast(bool skipCheck)
{
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_ITEM) && m_CastItem)
{
player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_ITEM, m_CastItem->GetEntry());
player->StartAchievementCriteria(AchievementCriteriaStartEvent::UseItem, m_CastItem->GetEntry());
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry());
}
player->FailAchievementCriteria(AchievementCriteriaFailEvent::CastSpell, m_spellInfo->Id);
player->StartAchievementCriteria(AchievementCriteriaStartEvent::CastSpell, m_spellInfo->Id);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id);
}
@@ -303,7 +303,7 @@ class instance_halls_of_origination : public InstanceMapScript
if (GameObject* door = GetGameObject(DATA_VAULT_OF_LIGHTS_ENTRANCE_DOOR))
door->SetGoState(GO_STATE_ACTIVE);
DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_VAULT_OF_LIGHTS_START_EVENT);
TriggerGameEvent(ACHIEV_VAULT_OF_LIGHTS_START_EVENT);
_events.ScheduleEvent(EVENT_FAIL_VAULTS_OF_LIGHT_ACHIEVEMENT, 5min);
}
else if (value == DONE)
@@ -157,7 +157,6 @@ public:
_Reset();
me->SetReactState(REACT_AGGRESSIVE);
instance->SetData(DATA_ONYXIA_PHASE, Phase);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void JustEngagedWith(Unit* who) override
@@ -168,7 +167,7 @@ public:
events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(15000, 20000));
events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 5000));
events.ScheduleEvent(EVENT_WING_BUFFET, urand(10000, 20000));
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
instance->TriggerGameEvent(ACHIEV_TIMED_START_EVENT);
}
void JustSummoned(Creature* summoned) override
@@ -171,7 +171,6 @@ public:
Initialize();
instance->SetBossState(DATA_HERALD_VOLAZJ, NOT_STARTED);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
// Visible for all players in insanity
for (uint32 i = 173; i <= 177; ++i)
@@ -191,7 +190,7 @@ public:
Talk(SAY_AGGRO);
instance->SetBossState(DATA_HERALD_VOLAZJ, IN_PROGRESS);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
instance->TriggerGameEvent(ACHIEV_QUICK_DEMISE_START_EVENT);
}
void JustSummoned(Creature* summon) override
@@ -122,7 +122,6 @@ public:
{
BossAI::Reset();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOTTA_GO_START_EVENT);
_nextSubmerge = 75;
_petCount = 0;
}
@@ -139,7 +138,7 @@ public:
door2->SetGoState(GO_STATE_ACTIVE);
Talk(SAY_AGGRO);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOTTA_GO_START_EVENT);
instance->TriggerGameEvent(ACHIEV_GOTTA_GO_START_EVENT);
events.SetPhase(PHASE_EMERGE);
events.ScheduleEvent(EVENT_CLOSE_DOOR, Seconds(5));
@@ -370,8 +370,6 @@ class boss_fjola : public CreatureScript
TwinPactSpellId = SPELL_LIGHT_TWIN_PACT;
TouchSpellId = SPELL_LIGHT_TOUCH;
SpikeSpellId = SPELL_LIGHT_TWIN_SPIKE;
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT);
boss_twin_baseAI::Reset();
}
@@ -410,7 +408,7 @@ class boss_fjola : public CreatureScript
void JustEngagedWith(Unit* who) override
{
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT);
instance->TriggerGameEvent(EVENT_START_TWINS_FIGHT);
events.ScheduleEvent(EVENT_SPECIAL_ABILITY, 45 * IN_MILLISECONDS);
me->SummonCreature(NPC_BULLET_CONTROLLER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 0.0f, TEMPSUMMON_MANUAL_DESPAWN);
boss_twin_baseAI::JustEngagedWith(who);
@@ -812,7 +812,6 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
_events.Reset();
_icewall = 0;
_events.ScheduleEvent(EVENT_ESCAPE, 1000);
_instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
}
void JustDied(Unit* /*killer*/) override
@@ -1062,7 +1061,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
}
}
_invincibility = false;
_instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
_instance->TriggerGameEvent(ACHIEV_NOT_RETREATING_EVENT);
_events.ScheduleEvent(EVENT_ESCAPE_7, 1000);
break;
case EVENT_ESCAPE_7:
@@ -348,8 +348,6 @@ class instance_halls_of_reflection : public InstanceMapScript
}
break;
case FAIL:
DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID))
jainaOrSylvanas->DespawnOrUnsummon(10000);
@@ -148,7 +148,7 @@ public:
_JustDied();
// start achievement timer (kill Maexna within 20 min)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
instance->TriggerGameEvent(ACHIEV_TIMED_START_EVENT);
}
void JustEngagedWith(Unit* who) override
@@ -72,8 +72,6 @@ public:
void Reset() override
{
_Reset();
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
}
void KilledUnit(Unit* /*Victim*/) override
@@ -96,7 +94,7 @@ public:
events.ScheduleEvent(EVENT_HATEFUL, Seconds(1));
events.ScheduleEvent(EVENT_BERSERK, Minutes(6));
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
instance->TriggerGameEvent(ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
}
void UpdateAI(uint32 diff) override
@@ -381,7 +381,6 @@ public:
SetPhase(PHASE_NOT_STARTED, true);
me->SetReactState(REACT_PASSIVE);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
instance->SetBossState(DATA_MALYGOS_EVENT, NOT_STARTED);
}
@@ -573,7 +572,7 @@ public:
Talk(SAY_START_P_ONE);
DoCast(SPELL_BERSERK); // periodic aura, first tick in 10 minutes
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
instance->TriggerGameEvent(ACHIEV_TIMED_START_EVENT);
}
void EnterEvadeMode(EvadeReason /*why*/) override
@@ -138,7 +138,7 @@ class boss_drakos : public CreatureScript
Talk(SAY_DEATH);
// start achievement timer (kill Eregos within 20 min)
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
instance->TriggerGameEvent(ACHIEV_TIMED_START_EVENT);
}
void KilledUnit(Unit* /*victim*/) override
@@ -82,7 +82,7 @@ struct boss_loken : public BossAI
events.ScheduleEvent(EVENT_ARC_LIGHTNING, 15s);
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 20s);
events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, 1s);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
instance->TriggerGameEvent(ACHIEV_TIMELY_DEATH_START_EVENT);
me->SetStandState(UNIT_STAND_STATE_STAND);
}
@@ -95,7 +95,6 @@ struct boss_loken : public BossAI
void EnterEvadeMode(EvadeReason /*why*/) override
{
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
_DespawnAtEvade();
}
@@ -67,8 +67,6 @@ class boss_maiden_of_grief : public CreatureScript
events.ScheduleEvent(EVENT_STORM_OF_GRIEF, 10000);
events.ScheduleEvent(EVENT_SHOCK_OF_SORROW, urand(20000, 25000));
events.ScheduleEvent(EVENT_PILLAR_OF_WOE, urand(5000, 15000));
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT);
}
void JustEngagedWith(Unit* who) override
@@ -76,7 +74,7 @@ class boss_maiden_of_grief : public CreatureScript
BossAI::JustEngagedWith(who);
Talk(SAY_AGGRO);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT);
instance->TriggerGameEvent(ACHIEV_GOOD_GRIEF_START_EVENT);
}
void KilledUnit(Unit* who) override
@@ -787,7 +787,7 @@ class npc_living_constellation : public CreatureScript
me->DespawnOrUnsummon(1);
if (InstanceScript* instance = me->GetInstanceScript())
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_ID_SUPERMASSIVE_START);
instance->TriggerGameEvent(EVENT_ID_SUPERMASSIVE_START);
caster->CastSpell((Unit*)nullptr, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK);
caster->ToCreature()->DespawnOrUnsummon(1);
}
@@ -1329,33 +1329,6 @@ class spell_algalon_cosmic_smash_damage : public SpellScriptLoader
}
};
class spell_algalon_supermassive_fail : public SpellScriptLoader
{
public:
spell_algalon_supermassive_fail() : SpellScriptLoader("spell_algalon_supermassive_fail") { }
class spell_algalon_supermassive_fail_SpellScript : public SpellScript
{
void RecalculateDamage()
{
if (!GetHitPlayer())
return;
GetHitPlayer()->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true);
}
void Register() override
{
OnHit.Register(&spell_algalon_supermassive_fail_SpellScript::RecalculateDamage);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_algalon_supermassive_fail_SpellScript();
}
};
void AddSC_boss_algalon_the_observer()
{
new boss_algalon_the_observer();
@@ -1371,5 +1344,4 @@ void AddSC_boss_algalon_the_observer()
new spell_algalon_remove_phase();
new spell_algalon_cosmic_smash();
new spell_algalon_cosmic_smash_damage();
new spell_algalon_supermassive_fail();
}
@@ -137,8 +137,6 @@ class boss_ignis : public CreatureScript
_Reset();
if (Vehicle* _vehicle = me->GetVehicleKit())
_vehicle->RemoveAllPassengers();
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT);
}
void JustEngagedWith(Unit* who) override
@@ -152,7 +150,7 @@ class boss_ignis : public CreatureScript
events.ScheduleEvent(EVENT_END_POT, 40000);
events.ScheduleEvent(EVENT_BERSERK, 480000);
Initialize();
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT);
instance->TriggerGameEvent(ACHIEVEMENT_IGNIS_START_EVENT);
}
void JustDied(Unit* /*killer*/) override
@@ -200,7 +200,7 @@ class boss_kologarn : public CreatureScript
if (!right && !left)
events.ScheduleEvent(EVENT_STONE_SHOUT, 5000);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, CRITERIA_DISARMED);
instance->TriggerGameEvent(CRITERIA_DISARMED);
}
else
{
@@ -203,8 +203,6 @@ class boss_xt002 : public CreatureScript
DoCastSelf(SPELL_STAND);
Initialize();
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MUST_DECONSTRUCT_FASTER);
}
void EnterEvadeMode(EvadeReason /*why*/) override
@@ -224,7 +222,7 @@ class boss_xt002 : public CreatureScript
//Tantrum is cast a bit slower the first time.
events.ScheduleEvent(EVENT_TYMPANIC_TANTRUM, urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX) * 2);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MUST_DECONSTRUCT_FASTER);
instance->TriggerGameEvent(ACHIEV_MUST_DECONSTRUCT_FASTER);
}
void DoAction(int32 action) override
@@ -493,7 +493,6 @@ class boss_voice_of_yogg_saron : public CreatureScript
events.SetPhase(PHASE_ONE);
instance->SetData(DATA_DRIVE_ME_CRAZY, uint32(true));
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
Initialize();
@@ -517,7 +516,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
if (Creature* keeper = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i)))
keeper->SetInCombatWith(me);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
instance->TriggerGameEvent(ACHIEV_TIMED_START_EVENT);
DoCastAOE(SPELL_SUMMON_GUARDIAN_2, { SPELLVALUE_MAX_TARGETS, 1 });
DoCast(me, SPELL_SANITY_PERIODIC);
@@ -558,7 +558,7 @@ class instance_ulduar : public InstanceMapScript
case NPC_GUARDIAN_OF_LIFE:
if (!conSpeedAtory)
{
DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, CRITERIA_CON_SPEED_ATORY);
TriggerGameEvent(CRITERIA_CON_SPEED_ATORY);
conSpeedAtory = true;
}
break;
@@ -567,7 +567,7 @@ class instance_ulduar : public InstanceMapScript
case NPC_BRIGHTLEAF:
if (!lumberjacked)
{
DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, CRITERIA_LUMBERJACKED);
TriggerGameEvent(CRITERIA_LUMBERJACKED);
lumberjacked = true;
}
break;
@@ -169,8 +169,6 @@ public:
me->SetReactState(REACT_PASSIVE);
if (!instance->GetCreature(DATA_GRAUF))
me->SummonCreature(NPC_GRAUF, GraufLoc);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_LODI_DODI_WE_LOVES_THE_SKADI);
}
void EnterEvadeMode(EvadeReason /*why*/) override
@@ -234,7 +232,7 @@ public:
SpawnFirstWave();
Talk(SAY_AGGRO);
_phase = PHASE_FLYING;
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_LODI_DODI_WE_LOVES_THE_SKADI);
instance->TriggerGameEvent(ACHIEV_LODI_DODI_WE_LOVES_THE_SKADI);
scheduler
.Schedule(Seconds(6), [this](TaskContext resetCheck)