aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-09-25 00:53:56 +0200
committerShauren <shauren.trinity@gmail.com>2023-09-25 00:53:56 +0200
commit41a20b1e4008d450d075847ef1fe367f0e3a240f (patch)
tree4e202edb0d037a4a406926e6cacd686c7afcbca1
parente1f345756ba34ccf4d4dd07b90c254097a240b51 (diff)
Core/Achievements: Fixed achievement criteria StartEvent and FailEvent
* Criteria using StartEvent cannot be updated without that event triggering first (not only for timed achievements) * Implemented most StartEvent and FailEvent types * Fixed saving criteria removed by RemoveCriteriaProgress
-rw-r--r--sql/updates/world/master/2023_09_25_00_world.sql1
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp39
-rw-r--r--src/server/game/Achievements/AchievementMgr.h2
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp183
-rw-r--r--src/server/game/Achievements/CriteriaHandler.h31
-rw-r--r--src/server/game/Battlegrounds/Arena.cpp3
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp13
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp28
-rw-r--r--src/server/game/Entities/Player/Player.h5
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp17
-rw-r--r--src/server/game/Events/GameEventSender.cpp4
-rw-r--r--src/server/game/Groups/Group.cpp5
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp1
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp32
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.h1
-rw-r--r--src/server/game/Scenarios/Scenario.cpp7
-rw-r--r--src/server/game/Scenarios/Scenario.h1
-rw-r--r--src/server/game/Spells/Spell.cpp11
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp16
20 files changed, 163 insertions, 239 deletions
diff --git a/sql/updates/world/master/2023_09_25_00_world.sql b/sql/updates/world/master/2023_09_25_00_world.sql
new file mode 100644
index 00000000000..2f96b91d845
--- /dev/null
+++ b/sql/updates/world/master/2023_09_25_00_world.sql
@@ -0,0 +1 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_algalon_supermassive_fail';
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index e223a9ae9dd..39328c9f9c2 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -98,13 +98,6 @@ bool AchievementMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTre
return false;
}
- if (achievement->InstanceID != -1 && referencePlayer->GetMapId() != uint32(achievement->InstanceID))
- {
- TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: {} Type {} Achievement {}) Wrong map",
- criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), achievement->ID);
- return false;
- }
-
if ((achievement->Faction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) ||
(achievement->Faction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE))
{
@@ -369,38 +362,6 @@ void PlayerAchievementMgr::SaveToDB(CharacterDatabaseTransaction trans)
}
}
-void PlayerAchievementMgr::ResetCriteria(CriteriaFailEvent failEvent, int32 failAsset, bool evenIfCriteriaComplete)
-{
- TC_LOG_DEBUG("criteria.achievement", "PlayerAchievementMgr::ResetCriteria({}, {}, {})", uint32(failEvent), failAsset, evenIfCriteriaComplete ? "true" : "false");
-
- // Disable for GameMasters with GM-mode enabled or for players that don't have the related RBAC permission
- if (_owner->IsGameMaster() || _owner->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS))
- return;
-
- if (CriteriaList const* achievementCriteriaList = sCriteriaMgr->GetCriteriaByFailEvent(failEvent, failAsset))
- {
- for (Criteria const* achievementCriteria : *achievementCriteriaList)
- {
- std::vector<CriteriaTree const*> const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(achievementCriteria->ID);
- bool allComplete = true;
- for (CriteriaTree const* tree : *trees)
- {
- // don't update already completed criteria if not forced or achievement already complete
- if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete) || !HasAchieved(tree->Achievement->ID))
- {
- allComplete = false;
- break;
- }
- }
-
- if (allComplete)
- continue;
-
- RemoveCriteriaProgress(achievementCriteria);
- }
- }
-}
-
void PlayerAchievementMgr::SendAllData(Player const* /*receiver*/) const
{
VisibleAchievementCheck filterInvisible;
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index cc17fb4c358..1d1090128a4 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -85,8 +85,6 @@ public:
void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
void SaveToDB(CharacterDatabaseTransaction trans);
- void ResetCriteria(CriteriaFailEvent failEvent, int32 failAsset, bool evenIfCriteriaComplete = false);
-
void SendAllData(Player const* receiver) const override;
void SendAchievementInfo(Player* receiver, uint32 achievementId = 0) const;
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 2f10bc605fd..9abf7721db4 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -859,75 +859,94 @@ void CriteriaHandler::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*
}
}
-void CriteriaHandler::UpdateTimedCriteria(uint32 timeDiff)
+void CriteriaHandler::UpdateTimedCriteria(Milliseconds timeDiff)
{
- if (!_timeCriteriaTrees.empty())
+ for (auto itr = _startedCriteria.begin(); itr != _startedCriteria.end();)
{
- for (auto itr = _timeCriteriaTrees.begin(); itr != _timeCriteriaTrees.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)
- {
- CriteriaTree const* criteriaTree = sCriteriaMgr->GetCriteriaTree(itr->first);
- if (criteriaTree->Criteria)
- RemoveCriteriaProgress(criteriaTree->Criteria);
+ RemoveCriteriaProgress(sCriteriaMgr->GetCriteria(itr->first));
- itr = _timeCriteriaTrees.erase(itr);
- }
- else
- {
- itr->second -= timeDiff;
- ++itr;
- }
+ itr = _startedCriteria.erase(itr);
+ }
+ else
+ {
+ itr->second -= timeDiff;
+ ++itr;
}
}
}
-void CriteriaHandler::StartCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry, uint32 timeLost /* = 0 */)
+void CriteriaHandler::StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost /*= Milliseconds::zero()*/)
{
- CriteriaList const& criteriaList = sCriteriaMgr->GetTimedCriteriaByType(startEvent);
- for (Criteria const* criteria : criteriaList)
+ CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByStartEvent(startEvent, entry);
+ if (!criteriaList)
+ return;
+
+ for (Criteria const* criteria : *criteriaList)
{
- if (criteria->Entry->StartAsset != int32(entry))
+ Milliseconds timeLimit = Milliseconds::max(); // this value is for criteria that have a start event requirement but no time limit
+ if (criteria->Entry->StartTimer)
+ timeLimit = Seconds(criteria->Entry->StartTimer);
+
+ timeLimit -= timeLost;
+
+ if (timeLimit <= Milliseconds::zero())
continue;
CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
- bool canStart = false;
- for (CriteriaTree const* tree : *trees)
+ bool canStart = std::any_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
{
- if ((_timeCriteriaTrees.find(tree->ID) == _timeCriteriaTrees.end() || criteria->Entry->GetFlags().HasFlag(CriteriaFlags::ResetOnStart)) && !IsCompletedCriteriaTree(tree))
- {
- // Start the timer
- if (criteria->Entry->StartTimer * uint32(IN_MILLISECONDS) > timeLost)
- {
- _timeCriteriaTrees[tree->ID] = criteria->Entry->StartTimer * IN_MILLISECONDS - timeLost;
- canStart = true;
- }
- }
- }
+ return !IsCompletedCriteriaTree(tree);
+ });
if (!canStart)
continue;
+ auto [itr, isNew] = _startedCriteria.try_emplace(criteria->ID, timeLimit);
+ if (!isNew)
+ {
+ if (!criteria->Entry->GetFlags().HasFlag(CriteriaFlags::ResetOnStart))
+ continue;
+
+ itr->second = timeLimit;
+ }
+
// and at client too
SetCriteriaProgress(criteria, 0, nullptr, PROGRESS_SET);
}
}
-void CriteriaHandler::RemoveCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry)
+void CriteriaHandler::FailCriteria(CriteriaFailEvent failEvent, uint32 asset)
{
- CriteriaList const& criteriaList = sCriteriaMgr->GetTimedCriteriaByType(startEvent);
- for (Criteria const* criteria : criteriaList)
+ CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByFailEvent(failEvent, asset);
+ if (!criteriaList)
+ return;
+
+ for (Criteria const* criteria : *criteriaList)
{
- if (criteria->Entry->StartAsset != int32(entry))
- continue;
+ _startedCriteria.erase(criteria->ID);
CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
- // Remove the timer from all trees
- for (CriteriaTree const* tree : *trees)
- _timeCriteriaTrees.erase(tree->ID);
+ bool allTreesFullyComplete = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
+ {
+ CriteriaTree const* root = tree;
+ if (CriteriaTree const* parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent))
+ {
+ do
+ {
+ root = parent;
+ parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent);
+ } while (parent);
+ }
+
+ return IsCompletedCriteriaTree(root);
+ });
+
+ if (allTreesFullyComplete)
+ continue;
- // remove progress
RemoveCriteriaProgress(criteria);
}
}
@@ -943,29 +962,6 @@ CriteriaProgress* CriteriaHandler::GetCriteriaProgress(Criteria const* entry)
void CriteriaHandler::SetCriteriaProgress(Criteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType progressType)
{
- // Don't allow to cheat - doing timed criteria without timer active
- CriteriaTreeList const* trees = nullptr;
- if (criteria->Entry->StartTimer)
- {
- trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
- if (!trees)
- return;
-
- bool hasTreeForTimed = false;
- for (CriteriaTree const* tree : *trees)
- {
- auto timedIter = _timeCriteriaTrees.find(tree->ID);
- if (timedIter != _timeCriteriaTrees.end())
- {
- hasTreeForTimed = true;
- break;
- }
- }
-
- if (!hasTreeForTimed)
- return;
- }
-
TC_LOG_DEBUG("criteria", "CriteriaHandler::SetCriteriaProgress({}, {}) for {}", criteria->ID, changeValue, GetOwnerInfo());
CriteriaProgress* progress = GetCriteriaProgress(criteria);
@@ -1014,20 +1010,22 @@ void CriteriaHandler::SetCriteriaProgress(Criteria const* criteria, uint64 chang
if (criteria->Entry->StartTimer)
{
- ASSERT(trees);
-
- for (CriteriaTree const* tree : *trees)
+ auto startedItr = _startedCriteria.find(criteria->ID);
+ if (startedItr != _startedCriteria.end())
{
- auto timedIter = _timeCriteriaTrees.find(tree->ID);
- if (timedIter != _timeCriteriaTrees.end())
+ // Client expects this in packet
+ timeElapsed = duration_cast<Seconds>(Seconds(criteria->Entry->StartTimer) - startedItr->second);
+
+ // Remove the timer, we wont need it anymore
+ CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
+
+ bool allTreesCompleted = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
{
- // Client expects this in packet
- timeElapsed = Seconds(criteria->Entry->StartTimer - (timedIter->second / IN_MILLISECONDS));
+ return IsCompletedCriteriaTree(tree);
+ });
- // Remove the timer, we wont need it anymore
- if (IsCompletedCriteriaTree(tree))
- _timeCriteriaTrees.erase(timedIter);
- }
+ if (allTreesCompleted)
+ _startedCriteria.erase(startedItr);
}
}
@@ -1045,7 +1043,8 @@ void CriteriaHandler::RemoveCriteriaProgress(Criteria const* criteria)
SendCriteriaProgressRemoved(criteria->ID);
- _criteriaProgress.erase(criteriaProgress);
+ criteriaProgress->second.Counter = 0;
+ criteriaProgress->second.Changed = true;
}
bool CriteriaHandler::IsCompletedCriteriaTree(CriteriaTree const* tree)
@@ -1322,24 +1321,10 @@ bool CriteriaHandler::CanUpdateCriteria(Criteria const* criteria, CriteriaTreeLi
return true;
}
-bool CriteriaHandler::ConditionsSatisfied(Criteria const* criteria, Player* referencePlayer) const
+bool CriteriaHandler::ConditionsSatisfied(Criteria const* criteria, Player* /*referencePlayer*/) const
{
- if (!criteria->Entry->FailEvent)
- return true;
-
- switch (CriteriaFailEvent(criteria->Entry->FailEvent))
- {
- case CriteriaFailEvent::LeaveBattleground:
- if (!referencePlayer->InBattleground())
- return false;
- break;
- case CriteriaFailEvent::ModifyPartyStatus:
- if (referencePlayer->GetGroup())
- return false;
- break;
- default:
- break;
- }
+ if (criteria->Entry->StartEvent && !_startedCriteria.contains(criteria->ID))
+ return false;
return true;
}
@@ -4496,6 +4481,16 @@ CriteriaList const& CriteriaMgr::GetScenarioCriteriaByTypeAndScenario(CriteriaTy
return EmptyCriteriaList;
}
+CriteriaList const* CriteriaMgr::GetCriteriaByStartEvent(CriteriaStartEvent startEvent, int32 asset) const
+{
+ return Trinity::Containers::MapGetValuePtr(_criteriasByStartEvent[size_t(startEvent)], asset);
+}
+
+CriteriaList const* CriteriaMgr::GetCriteriaByFailEvent(CriteriaFailEvent failEvent, int32 asset) const
+{
+ return Trinity::Containers::MapGetValuePtr(_criteriasByFailEvent[size_t(failEvent)], asset);
+}
+
CriteriaMgr::CriteriaMgr() = default;
//==========================================================
@@ -4720,7 +4715,7 @@ void CriteriaMgr::LoadCriteriaList()
}
if (criteriaEntry->StartTimer)
- _criteriasByTimedType[criteriaEntry->StartEvent].push_back(criteria);
+ _criteriasByStartEvent[criteriaEntry->StartEvent][criteriaEntry->StartAsset].push_back(criteria);
if (criteriaEntry->FailEvent)
_criteriasByFailEvent[criteriaEntry->FailEvent][criteriaEntry->FailAsset].push_back(criteria);
diff --git a/src/server/game/Achievements/CriteriaHandler.h b/src/server/game/Achievements/CriteriaHandler.h
index 351f97bdf6f..0205130cdc0 100644
--- a/src/server/game/Achievements/CriteriaHandler.h
+++ b/src/server/game/Achievements/CriteriaHandler.h
@@ -22,7 +22,6 @@
#include "DBCEnums.h"
#include "Duration.h"
#include "ObjectGuid.h"
-#include <map>
#include <unordered_map>
#include <vector>
#include <ctime>
@@ -69,8 +68,8 @@ struct CriteriaTree
CriteriaTreeEntry const* Entry = nullptr;
AchievementEntry const* Achievement = nullptr;
ScenarioStepEntry const* ScenarioStep = nullptr;
- struct QuestObjective const* QuestObjective = nullptr;
- struct Criteria const* Criteria = nullptr;
+ ::QuestObjective const* QuestObjective = nullptr;
+ ::Criteria const* Criteria = nullptr;
std::vector<CriteriaTree const*> Children;
};
@@ -252,7 +251,6 @@ private:
std::vector<CriteriaData> _storage;
};
-typedef std::map<uint32, CriteriaDataSet> CriteriaDataMap;
typedef std::unordered_map<uint32, CriteriaProgress> CriteriaProgressMap;
enum ProgressType
@@ -279,9 +277,9 @@ public:
virtual void SendAllData(Player const* receiver) const = 0;
- void UpdateTimedCriteria(uint32 timeDiff);
- void StartCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry, uint32 timeLost = 0);
- void RemoveCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry); // used for quest and scripted timed s
+ void UpdateTimedCriteria(Milliseconds timeDiff);
+ void StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost = Milliseconds::zero());
+ virtual void FailCriteria(CriteriaFailEvent failEvent, uint32 asset);
protected:
virtual void SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, Seconds timeElapsed, bool timedCompleted) const = 0;
@@ -312,7 +310,7 @@ protected:
virtual CriteriaList const& GetCriteriaByType(CriteriaType type, uint32 asset) const = 0;
CriteriaProgressMap _criteriaProgress;
- std::map<uint32, uint32 /*ms time left*/> _timeCriteriaTrees;
+ std::unordered_map<uint32 /*criteriaID*/, Milliseconds /*time left*/> _startedCriteria;
};
class TC_GAME_API CriteriaMgr
@@ -351,20 +349,13 @@ public:
return itr != _criteriaTreeByCriteria.end() ? &itr->second : nullptr;
}
- CriteriaList const& GetTimedCriteriaByType(CriteriaStartEvent startEvent) const
- {
- return _criteriasByTimedType[size_t(startEvent)];
- }
+ CriteriaList const* GetCriteriaByStartEvent(CriteriaStartEvent startEvent, int32 asset) const;
- CriteriaList const* GetCriteriaByFailEvent(CriteriaFailEvent condition, int32 asset)
- {
- auto itr = _criteriasByFailEvent[size_t(condition)].find(asset);
- return itr != _criteriasByFailEvent[size_t(condition)].end() ? &itr->second : nullptr;
- }
+ CriteriaList const* GetCriteriaByFailEvent(CriteriaFailEvent failEvent, int32 asset) const;
CriteriaDataSet const* GetCriteriaDataSet(Criteria const* Criteria) const
{
- CriteriaDataMap::const_iterator iter = _criteriaDataMap.find(Criteria->ID);
+ auto iter = _criteriaDataMap.find(Criteria->ID);
return iter != _criteriaDataMap.end() ? &iter->second : nullptr;
}
@@ -403,7 +394,7 @@ public:
ModifierTreeNode const* GetModifierTree(uint32 modifierTreeId) const;
private:
- CriteriaDataMap _criteriaDataMap;
+ std::unordered_map<uint32, CriteriaDataSet> _criteriaDataMap;
std::unordered_map<uint32, CriteriaTree*> _criteriaTrees;
std::unordered_map<uint32, Criteria*> _criteria;
@@ -419,7 +410,7 @@ private:
CriteriaListByAsset _scenarioCriteriasByTypeAndScenarioId[size_t(CriteriaType::Count)];
CriteriaList _questObjectiveCriteriasByType[size_t(CriteriaType::Count)];
- CriteriaList _criteriasByTimedType[size_t(CriteriaStartEvent::Count)];
+ std::unordered_map<int32, CriteriaList> _criteriasByStartEvent[size_t(CriteriaStartEvent::Count)];
std::unordered_map<int32, CriteriaList> _criteriasByFailEvent[size_t(CriteriaFailEvent::Count)];
};
diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp
index d90a18bc153..c5060c40ce6 100644
--- a/src/server/game/Battlegrounds/Arena.cpp
+++ b/src/server/game/Battlegrounds/Arena.cpp
@@ -244,6 +244,7 @@ void Arena::EndBattleground(uint32 winner)
{
// update achievement BEFORE personal rating update
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
+ player->StartCriteria(CriteriaStartEvent::WinRankedArenaMatchWithTeamSize, 0);
player->UpdateCriteria(CriteriaType::WinAnyRankedArena, rating ? rating : 1);
player->UpdateCriteria(CriteriaType::WinArena, GetMapId());
@@ -269,7 +270,7 @@ void Arena::EndBattleground(uint32 winner)
loserArenaTeam->MemberLost(player, winnerMatchmakerRating, loserMatchmakerChange);
// Arena lost => reset the win_rated_arena having the "no_lose" condition
- player->ResetCriteria(CriteriaFailEvent::LoseRankedArenaMatchWithTeamSize, 0);
+ player->FailCriteria(CriteriaFailEvent::LoseRankedArenaMatchWithTeamSize, 0);
}
}
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 35c037159f9..56788c7d520 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -418,8 +418,13 @@ inline void Battleground::_ProcessJoin(uint32 diff)
SendPacketToAll(WorldPackets::Battleground::PVPMatchSetState(WorldPackets::Battleground::PVPMatchState::Engaged).Write());
for (auto const& [guid, _] : GetPlayers())
- if (Player* player = ObjectAccessor::FindPlayer(guid))
+ {
+ if (Player* player = ObjectAccessor::GetPlayer(GetBgMap(), guid))
+ {
+ player->StartCriteria(CriteriaStartEvent::StartBattleground, GetBgMap()->GetId());
player->AtStartOfEncounter(EncounterType::Battleground);
+ }
+ }
// Remove preparation
if (isArena())
@@ -929,7 +934,7 @@ void Battleground::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen
player->SetBGTeam(0);
// remove all criterias on bg leave
- player->ResetCriteria(CriteriaFailEvent::LeaveBattleground, GetMapId(), true);
+ player->FailCriteria(CriteriaFailEvent::LeaveBattleground, 0);
if (Transport)
player->TeleportToBGEntryPoint();
@@ -1096,10 +1101,6 @@ void Battleground::AddPlayer(Player* player, BattlegroundQueueTypeId queueId)
}
}
- // reset all map criterias on map enter
- if (!isInBattleground)
- player->ResetCriteria(CriteriaFailEvent::LeaveBattleground, GetMapId(), true);
-
// setup BG group membership
PlayerAddedToBGCheckIfBGIsRunning(player);
AddOrSetPlayerToCorrectBgGroup(player, team);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index 6a64373e8ef..b41fb4a8966 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -472,7 +472,7 @@ void BattlegroundWS::OnFlagStateChange(GameObject* flagInBase, FlagState /*oldVa
ApplyAssaultDebuffToPlayer(player);
flagInBase->CastSpell(player, BG_WS_SPELL_QUICK_CAP_TIMER, true);
- player->StartCriteriaTimer(CriteriaStartEvent::BeSpellTarget, BG_WS_SPELL_QUICK_CAP_TIMER, uint32(GameTime::GetGameTime() - flagInBase->GetFlagTakenFromBaseTime()));
+ player->StartCriteria(CriteriaStartEvent::BeSpellTarget, BG_WS_SPELL_QUICK_CAP_TIMER, Seconds(GameTime::GetGameTime() - flagInBase->GetFlagTakenFromBaseTime()));
break;
}
case FlagState::Respawning:
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 54d37c7bbb7..10f11f08bf5 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1004,7 +1004,7 @@ void Player::Update(uint32 p_time)
}
}
- m_achievementMgr->UpdateTimedCriteria(p_time);
+ m_achievementMgr->UpdateTimedCriteria(Milliseconds(p_time));
if (HasUnitState(UNIT_STATE_MELEE_ATTACKING) && !HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_CHARGING))
{
@@ -1262,7 +1262,7 @@ void Player::setDeathState(DeathState s)
UpdateCriteria(CriteriaType::DieInInstance, 1);
// reset all death criterias
- ResetCriteria(CriteriaFailEvent::Death, 0);
+ FailCriteria(CriteriaFailEvent::Death, 0);
}
Unit::setDeathState(s);
@@ -2408,6 +2408,7 @@ void Player::GiveLevel(uint8 level)
CharacterDatabase.CommitTransaction(trans);
}
+ StartCriteria(CriteriaStartEvent::ReachLevel, level);
UpdateCriteria(CriteriaType::ReachLevel);
UpdateCriteria(CriteriaType::ActivelyReachLevel, level);
@@ -14975,7 +14976,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
m_QuestStatusSave[quest_id] = QUEST_DEFAULT_SAVE_TYPE;
- StartCriteriaTimer(CriteriaStartEvent::AcceptQuest, quest_id);
+ StartCriteria(CriteriaStartEvent::AcceptQuest, quest_id);
SendQuestUpdate(quest_id);
@@ -15306,6 +15307,7 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
SetDailyQuestStatus(quest_id);
if (quest->IsDaily())
{
+ StartCriteria(CriteriaStartEvent::CompleteDailyQuest, 0);
UpdateCriteria(CriteriaType::CompleteDailyQuest, quest_id);
UpdateCriteria(CriteriaType::CompleteAnyDailyQuestPerDay, quest_id);
}
@@ -16546,7 +16548,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E
real_entry = killed->GetEntry();
}
- StartCriteriaTimer(CriteriaStartEvent::KillNPC, real_entry); // MUST BE CALLED FIRST
+ StartCriteria(CriteriaStartEvent::KillNPC, real_entry); // MUST BE CALLED FIRST
UpdateCriteria(CriteriaType::KillCreature, real_entry, addKillCount, 0, killed);
UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_MONSTER, entry, 1, guid);
@@ -16554,6 +16556,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E
void Player::KilledPlayerCredit(ObjectGuid victimGuid)
{
+ StartCriteria(CriteriaStartEvent::KillPlayer, 0);
UpdateQuestObjectiveProgress(QUEST_OBJECTIVE_PLAYERKILLS, 0, 1, victimGuid);
}
@@ -24582,6 +24585,8 @@ void Player::DailyReset()
if (_garrison)
_garrison->ResetFollowerActivationLimit();
+
+ FailCriteria(CriteriaFailEvent::DailyQuestsCleared, 0);
}
void Player::ResetWeeklyQuestStatus()
@@ -26402,20 +26407,15 @@ bool Player::HasAchieved(uint32 achievementId) const
return m_achievementMgr->HasAchieved(achievementId);
}
-void Player::StartCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry, uint32 timeLost/* = 0*/)
-{
- m_achievementMgr->StartCriteriaTimer(startEvent, entry, timeLost);
-}
-
-void Player::RemoveCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry)
+void Player::StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost/* = Milliseconds::zero()*/)
{
- m_achievementMgr->RemoveCriteriaTimer(startEvent, entry);
+ m_achievementMgr->StartCriteria(startEvent, entry, timeLost);
}
-void Player::ResetCriteria(CriteriaFailEvent condition, int32 failAsset, bool evenIfCriteriaComplete /* = false*/)
+void Player::FailCriteria(CriteriaFailEvent condition, int32 failAsset)
{
- m_achievementMgr->ResetCriteria(condition, failAsset, evenIfCriteriaComplete);
- m_questObjectiveCriteriaMgr->ResetCriteria(condition, failAsset, evenIfCriteriaComplete);
+ m_achievementMgr->FailCriteria(condition, failAsset);
+ m_questObjectiveCriteriaMgr->FailCriteria(condition, failAsset);
}
void Player::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, WorldObject* ref /*= nullptr*/)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 58adcd3424f..52cf7d7ffa7 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2638,10 +2638,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
std::vector<uint32> GetCompletedAchievementIds() const;
bool HasAchieved(uint32 achievementId) const;
void ResetAchievements();
- void ResetCriteria(CriteriaFailEvent condition, int32 failAsset, bool evenIfCriteriaComplete = false);
+ void FailCriteria(CriteriaFailEvent condition, int32 failAsset);
void UpdateCriteria(CriteriaType type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, WorldObject* ref = nullptr);
- void StartCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry, uint32 timeLost = 0);
- void RemoveCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry);
+ void StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost = Milliseconds::zero());
void CompletedAchievement(AchievementEntry const* entry);
bool ModifierTreeSatisfied(uint32 modifierTreeId) const;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index c017eb0261c..7f4b58621b5 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -3351,8 +3351,14 @@ void Unit::_ApplyAura(AuraApplication* aurApp, uint32 effMask)
}
if (Player* player = ToPlayer())
+ {
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
player->UpdateVisibleGameobjectsOrSpellClicks();
+
+ player->FailCriteria(CriteriaFailEvent::GainAura, aurApp->GetBase()->GetId());
+ player->StartCriteria(CriteriaStartEvent::GainAura, aurApp->GetBase()->GetId());
+ player->UpdateCriteria(CriteriaType::GainAura, aurApp->GetBase()->GetId());
+ }
}
// removes aura application from lists and unapplies effects
@@ -3440,9 +3446,13 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMo
aura->HandleAuraSpecificMods(aurApp, caster, false, false);
if (Player* player = ToPlayer())
+ {
if (sConditionMgr->IsSpellUsedInSpellClickConditions(aurApp->GetBase()->GetId()))
player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->FailCriteria(CriteriaFailEvent::LoseAura, aurApp->GetBase()->GetId());
+ }
+
i = m_appliedAuras.begin();
}
@@ -3503,7 +3513,14 @@ void Unit::_RemoveNoStackAurasDueToAura(Aura* aura)
void Unit::_RegisterAuraEffect(AuraEffect* aurEff, bool apply)
{
if (apply)
+ {
m_modAuras[aurEff->GetAuraType()].push_front(aurEff);
+ if (Player* player = ToPlayer())
+ {
+ player->StartCriteria(CriteriaStartEvent::GainAuraEffect, aurEff->GetAuraType());
+ player->FailCriteria(CriteriaFailEvent::GainAuraEffect, aurEff->GetAuraType());
+ }
+ }
else
Trinity::Containers::Lists::RemoveUnique(m_modAuras[aurEff->GetAuraType()], aurEff);
}
diff --git a/src/server/game/Events/GameEventSender.cpp b/src/server/game/Events/GameEventSender.cpp
index da1dd86601e..031f806557a 100644
--- a/src/server/game/Events/GameEventSender.cpp
+++ b/src/server/game/Events/GameEventSender.cpp
@@ -56,8 +56,8 @@ void GameEvents::TriggerForPlayer(uint32 gameEventId, Player* source)
Map* map = source->GetMap();
if (map->Instanceable())
{
- source->StartCriteriaTimer(CriteriaStartEvent::SendEvent, gameEventId);
- source->ResetCriteria(CriteriaFailEvent::SendEvent, gameEventId);
+ source->FailCriteria(CriteriaFailEvent::SendEvent, gameEventId);
+ source->StartCriteria(CriteriaStartEvent::SendEvent, gameEventId);
}
source->UpdateCriteria(CriteriaType::PlayerTriggerGameEvent, gameEventId, 0, 0, source);
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index ee431dca54f..38180e3abd6 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -505,6 +505,8 @@ bool Group::AddMember(Player* player)
if (isRaidGroup())
player->UpdateVisibleGameobjectsOrSpellClicks();
+ player->FailCriteria(CriteriaFailEvent::ModifyPartyStatus, 0);
+
{
// Broadcast new player group member fields to rest of the group
UpdateData groupData(player->GetMapId());
@@ -571,6 +573,9 @@ bool Group::RemoveMember(ObjectGuid guid, RemoveMethod method /*= GROUP_REMOVEME
if (isLFGGroup() && method == GROUP_REMOVEMETHOD_KICK)
return !m_memberSlots.empty();
+ if (player)
+ player->FailCriteria(CriteriaFailEvent::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))
{
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 03350379b7f..889a98d8011 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -471,7 +471,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->RemoveCriteriaTimer(CriteriaStartEvent::AcceptQuest, questId);
TC_LOG_INFO("network", "Player {} abandoned quest {}", _player->GetGUID().ToString(), questId);
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
index fe0efd9e1ef..a72c213a042 100644
--- a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
@@ -164,38 +164,6 @@ void QuestObjectiveCriteriaMgr::SaveToDB(CharacterDatabaseTransaction trans)
}
}
-void QuestObjectiveCriteriaMgr::ResetCriteria(CriteriaFailEvent failEvent, int32 failAsset, bool evenIfCriteriaComplete)
-{
- TC_LOG_DEBUG("criteria.quest", "QuestObjectiveCriteriaMgr::ResetCriteria({}, {}, {})", uint32(failEvent), failAsset, evenIfCriteriaComplete ? "true" : "false");
-
- // disable for gamemasters with GM-mode enabled
- if (_owner->IsGameMaster())
- return;
-
- if (CriteriaList const* playerCriteriaList = sCriteriaMgr->GetCriteriaByFailEvent(failEvent, failAsset))
- {
- for (Criteria const* playerCriteria : *playerCriteriaList)
- {
- std::vector<CriteriaTree const*> const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(playerCriteria->ID);
- bool allComplete = true;
- for (CriteriaTree const* tree : *trees)
- {
- // don't update already completed criteria if not forced
- if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete))
- {
- allComplete = false;
- break;
- }
- }
-
- if (allComplete)
- continue;
-
- RemoveCriteriaProgress(playerCriteria);
- }
- }
-}
-
void QuestObjectiveCriteriaMgr::ResetCriteriaTree(uint32 criteriaTreeId)
{
CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(criteriaTreeId);
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.h b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
index ca1eac58a15..a263e153316 100644
--- a/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
@@ -35,7 +35,6 @@ public:
void LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult);
void SaveToDB(CharacterDatabaseTransaction trans);
- void ResetCriteria(CriteriaFailEvent failEvent, int32 failAsset, bool evenIfCriteriaComplete = false);
void ResetCriteriaTree(uint32 criteriaTreeId);
void SendAllData(Player const* receiver) const override;
diff --git a/src/server/game/Scenarios/Scenario.cpp b/src/server/game/Scenarios/Scenario.cpp
index 6d8fd3c1c62..3366781ba39 100644
--- a/src/server/game/Scenarios/Scenario.cpp
+++ b/src/server/game/Scenarios/Scenario.cpp
@@ -93,7 +93,12 @@ void Scenario::SetStep(ScenarioStepEntry const* step)
{
_currentstep = step;
if (step)
+ {
SetStepState(step, SCENARIO_STEP_IN_PROGRESS);
+ for (ObjectGuid const& guid : _players)
+ if (Player* player = ObjectAccessor::GetPlayer(_map, guid))
+ player->StartCriteria(CriteriaStartEvent::BeginScenarioStep, step->ID);
+ }
WorldPackets::Scenario::ScenarioState scenarioState;
BuildScenarioState(&scenarioState);
@@ -133,7 +138,7 @@ ScenarioEntry const* Scenario::GetEntry() const
ScenarioStepState Scenario::GetStepState(ScenarioStepEntry const* step)
{
- std::map<ScenarioStepEntry const*, ScenarioStepState>::const_iterator itr = _stepStates.find(step);
+ auto itr = _stepStates.find(step);
if (itr == _stepStates.end())
return SCENARIO_STEP_INVALID;
diff --git a/src/server/game/Scenarios/Scenario.h b/src/server/game/Scenarios/Scenario.h
index e01884dd9a9..7c632eca0cb 100644
--- a/src/server/game/Scenarios/Scenario.h
+++ b/src/server/game/Scenarios/Scenario.h
@@ -19,6 +19,7 @@
#define Scenario_h__
#include "CriteriaHandler.h"
+#include <map>
#include <unordered_set>
class Map;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 19a68fa341d..4ba4c975c6e 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3087,16 +3087,13 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo)
if (Player* player = unit->ToPlayer())
{
- player->StartCriteriaTimer(CriteriaStartEvent::BeSpellTarget, m_spellInfo->Id);
+ player->FailCriteria(CriteriaFailEvent::BeSpellTarget, m_spellInfo->Id);
+ player->StartCriteria(CriteriaStartEvent::BeSpellTarget, m_spellInfo->Id);
player->UpdateCriteria(CriteriaType::BeSpellTarget, m_spellInfo->Id, 0, 0, m_caster);
- player->UpdateCriteria(CriteriaType::GainAura, m_spellInfo->Id);
}
if (Player* player = m_caster->ToPlayer())
- {
- player->StartCriteriaTimer(CriteriaStartEvent::CastSpell, m_spellInfo->Id);
player->UpdateCriteria(CriteriaType::LandTargetedSpellOnTarget, m_spellInfo->Id, 0, 0, unit);
- }
if (m_caster != unit)
{
@@ -3791,10 +3788,12 @@ void Spell::_cast(bool skipCheck)
{
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_ITEM) && m_CastItem)
{
- player->StartCriteriaTimer(CriteriaStartEvent::UseItem, m_CastItem->GetEntry());
+ player->StartCriteria(CriteriaStartEvent::UseItem, m_CastItem->GetEntry());
player->UpdateCriteria(CriteriaType::UseItem, m_CastItem->GetEntry());
}
+ player->FailCriteria(CriteriaFailEvent::CastSpell, m_spellInfo->Id);
+ player->StartCriteria(CriteriaStartEvent::CastSpell, m_spellInfo->Id);
player->UpdateCriteria(CriteriaType::CastSpell, m_spellInfo->Id);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index 84262234a81..f823561a2ea 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -1183,21 +1183,6 @@ class spell_algalon_cosmic_smash_damage : public SpellScript
}
};
-// 65311 - Supermassive Fail
-class spell_algalon_supermassive_fail : public SpellScript
-{
- void RecalculateDamage()
- {
- if (Player* player = GetHitPlayer())
- player->ResetCriteria(CriteriaFailEvent::BeSpellTarget, GetSpellInfo()->Id, true);
- }
-
- void Register() override
- {
- OnHit += SpellHitFn(spell_algalon_supermassive_fail::RecalculateDamage);
- }
-};
-
// 62168 - Black Hole (Phase Shifts)
// 65250 - Worm Hole (Phase Shifts)
// 64417 - Phase Punch (Phase Shifts)
@@ -1240,6 +1225,5 @@ void AddSC_boss_algalon_the_observer()
RegisterSpellScript(spell_algalon_remove_phase);
RegisterSpellScript(spell_algalon_cosmic_smash);
RegisterSpellScript(spell_algalon_cosmic_smash_damage);
- RegisterSpellScript(spell_algalon_supermassive_fail);
RegisterSpellScript(spell_algalon_black_hole_phase_shifts);
}