TrinityCore
CriteriaHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "CriteriaHandler.h"
19#include "ArenaTeamMgr.h"
20#include "AzeriteItem.h"
21#include "Battleground.h"
22#include "BattlePetMgr.h"
23#include "CollectionMgr.h"
24#include "Containers.h"
25#include "Creature.h"
26#include "DatabaseEnv.h"
27#include "DB2Stores.h"
28#include "DisableMgr.h"
29#include "GameEventMgr.h"
30#include "GameTime.h"
31#include "Garrison.h"
32#include "Group.h"
33#include "InstanceScript.h"
34#include "Item.h"
35#include "ItemBonusMgr.h"
36#include "LanguageMgr.h"
37#include "Log.h"
38#include "Map.h"
39#include "MapManager.h"
40#include "ObjectMgr.h"
41#include "PhasingHandler.h"
42#include "Player.h"
43#include "RBAC.h"
44#include "RealmList.h"
45#include "ReputationMgr.h"
46#include "Scenario.h"
47#include "ScriptMgr.h"
48#include "SpellAuras.h"
49#include "SpellInfo.h"
50#include "SpellMgr.h"
51#include "World.h"
52#include "WorldSession.h"
53#include "WorldStateMgr.h"
54#include "WowTime.h"
55
56bool CriteriaData::IsValid(Criteria const* criteria)
57{
59 {
60 TC_LOG_ERROR("sql.sql", "Table `criteria_data` for criteria (Entry: {}) contains a wrong data type ({}), ignored.", criteria->ID, DataType);
61 return false;
62 }
63 switch (CriteriaType(criteria->Entry->Type))
64 {
69 case CriteriaType::CompleteQuest: // only hardcoded list
84 case CriteriaType::CompleteDailyQuest: // only Children's Week achievements
85 case CriteriaType::UseItem: // only Children's Week achievements
91 break;
92 default:
94 {
95 TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains data for a non-supported criteria type (Entry: {} Type: {}), ignored.", criteria->ID, criteria->Entry->Type);
96 return false;
97 }
98 break;
99 }
100
101 switch (DataType)
102 {
105 return true;
107 if (!Creature.Id || !sObjectMgr->GetCreatureTemplate(Creature.Id))
108 {
109 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_CREATURE ({}) contains a non-existing creature id in value1 ({}), ignored.",
110 criteria->ID, criteria->Entry->Type, DataType, Creature.Id);
111 return false;
112 }
113 return true;
115 if (!ClassRace.Class && !ClassRace.Race)
116 {
117 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({}) must not have 0 in either value field, ignored.",
118 criteria->ID, criteria->Entry->Type, DataType);
119 return false;
120 }
121 if (ClassRace.Class && ((1 << (ClassRace.Class-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
122 {
123 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({}) contains a non-existing class in value1 ({}), ignored.",
124 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Class);
125 return false;
126 }
128 {
129 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({}) contains a non-existing race in value2 ({}), ignored.",
130 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Race);
131 return false;
132 }
133 return true;
135 if (Health.Percent < 1 || Health.Percent > 100)
136 {
137 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH ({}) contains a wrong percent value in value1 ({}), ignored.",
138 criteria->ID, criteria->Entry->Type, DataType, Health.Percent);
139 return false;
140 }
141 return true;
144 {
145 SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(Aura.SpellId, DIFFICULTY_NONE);
146 if (!spellEntry)
147 {
148 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type {} ({}) contains a wrong spell id in value1 ({}), ignored.",
149 criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId);
150 return false;
151 }
152 if (spellEntry->GetEffects().size() <= Aura.EffectIndex)
153 {
154 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type {} ({}) contains a wrong spell effect index in value2 ({}), ignored.",
155 criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.EffectIndex);
156 return false;
157 }
158 if (!spellEntry->GetEffect(SpellEffIndex(Aura.EffectIndex)).ApplyAuraName)
159 {
160 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type {} ({}) contains a non-aura spell effect (ID: {} Effect: {}), ignored.",
161 criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId, Aura.EffectIndex);
162 return false;
163 }
164 return true;
165 }
167 if (Value.ComparisonType >= COMP_TYPE_MAX)
168 {
169 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_VALUE ({}) contains a wrong ComparisionType in value2 ({}), ignored.",
170 criteria->ID, criteria->Entry->Type, DataType, Value.ComparisonType);
171 return false;
172 }
173 return true;
175 if (Level.Min > STRONG_MAX_LEVEL)
176 {
177 TC_LOG_ERROR("sql.sql", "Table `CRITERIA_DATA` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_T_LEVEL ({}) contains a wrong minlevel in value1 ({}), ignored.",
178 criteria->ID, criteria->Entry->Type, DataType, Level.Min);
179 return false;
180 }
181 return true;
183 if (Gender.Gender > GENDER_NONE)
184 {
185 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_T_GENDER ({}) contains a wrong gender value in value1 ({}), ignored.",
186 criteria->ID, criteria->Entry->Type, DataType, Gender.Gender);
187 return false;
188 }
189 return true;
191 if (!ScriptId)
192 {
193 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_SCRIPT ({}) does not have a ScriptName set, ignored.",
194 criteria->ID, criteria->Entry->Type, DataType);
195 return false;
196 }
197 return true;
199 if (MapPlayers.MaxCount <= 0)
200 {
201 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT ({}) contains a wrong max players count in value1 ({}), ignored.",
202 criteria->ID, criteria->Entry->Type, DataType, MapPlayers.MaxCount);
203 return false;
204 }
205 return true;
207 if (Team.Team != ALLIANCE && Team.Team != HORDE)
208 {
209 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_T_TEAM ({}) contains an unknown team value in value1 ({}), ignored.",
210 criteria->ID, criteria->Entry->Type, DataType, Team.Team);
211 return false;
212 }
213 return true;
215 if (Drunk.State >= MAX_DRUNKEN)
216 {
217 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_S_DRUNK ({}) contains an unknown drunken state value in value1 ({}), ignored.",
218 criteria->ID, criteria->Entry->Type, DataType, Drunk.State);
219 return false;
220 }
221 return true;
223 if (!sHolidaysStore.LookupEntry(Holiday.Id))
224 {
225 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_HOLIDAY ({}) contains an unknown holiday entry in value1 ({}), ignored.",
226 criteria->ID, criteria->Entry->Type, DataType, Holiday.Id);
227 return false;
228 }
229 return true;
231 {
232 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
233 if (GameEvent.Id < 1 || GameEvent.Id >= events.size())
234 {
235 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_GAME_EVENT ({}) has unknown game_event in value1 ({}), ignored.",
236 criteria->ID, criteria->Entry->Type, DataType, GameEvent.Id);
237 return false;
238 }
239 return true;
240 }
242 return true; // not check correctness node indexes
244 if (EquippedItem.Quality >= MAX_ITEM_QUALITY)
245 {
246 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM ({}) contains an unknown quality state value in value2 ({}), ignored.",
247 criteria->ID, criteria->Entry->Type, DataType, EquippedItem.Quality);
248 return false;
249 }
250 return true;
252 if (!sMapStore.LookupEntry(Map.Id))
253 {
254 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_MAP_ID ({}) contains an unknown map entry in value1 ({}), ignored.",
255 criteria->ID, criteria->Entry->Type, DataType, Map.Id);
256 }
257 return true;
259 if (!ClassRace.Class && !ClassRace.Race)
260 {
261 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({}) should not have 0 in either value field. Ignored.",
262 criteria->ID, criteria->Entry->Type, DataType);
263 return false;
264 }
265 if (ClassRace.Class && ((1 << (ClassRace.Class-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
266 {
267 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({}) contains a non-existing class entry in value1 ({}), ignored.",
268 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Class);
269 return false;
270 }
272 {
273 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({}) contains a non-existing race entry in value2 ({}), ignored.",
274 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Race);
275 return false;
276 }
277 return true;
279 if (!sCharTitlesStore.LookupEntry(KnownTitle.Id))
280 {
281 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_S_KNOWN_TITLE ({}) contains an unknown title_id in value1 ({}), ignore.",
282 criteria->ID, criteria->Entry->Type, DataType, KnownTitle.Id);
283 return false;
284 }
285 return true;
287 if (ItemQuality.Quality >= MAX_ITEM_QUALITY)
288 {
289 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_S_ITEM_QUALITY ({}) contains an unknown quality state value in value1 ({}), ignored.",
290 criteria->ID, criteria->Entry->Type, DataType, ItemQuality.Quality);
291 return false;
292 }
293 return true;
294 default:
295 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) contains data of a non-supported data type ({}), ignored.", criteria->ID, criteria->Entry->Type, DataType);
296 return false;
297 }
298}
299
300bool CriteriaData::Meets(uint32 criteriaId, Player const* source, WorldObject const* target, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/) const
301{
302 switch (DataType)
303 {
305 return true;
307 if (!target || target->GetTypeId() != TYPEID_UNIT)
308 return false;
309 return target->GetEntry() == Creature.Id;
311 if (!target || target->GetTypeId() != TYPEID_PLAYER)
312 return false;
313 if (ClassRace.Class && ClassRace.Class != target->ToPlayer()->GetClass())
314 return false;
315 if (ClassRace.Race && ClassRace.Race != target->ToPlayer()->GetRace())
316 return false;
317 return true;
319 if (source->GetTypeId() != TYPEID_PLAYER)
320 return false;
321 if (ClassRace.Class && ClassRace.Class != source->ToPlayer()->GetClass())
322 return false;
323 if (ClassRace.Race && ClassRace.Race != source->ToPlayer()->GetRace())
324 return false;
325 return true;
327 if (!target || target->GetTypeId() != TYPEID_PLAYER)
328 return false;
329 return !target->ToPlayer()->HealthAbovePct(Health.Percent);
331 return source->HasAuraEffect(Aura.SpellId, uint8(Aura.EffectIndex));
333 {
334 if (!target)
335 return false;
336 Unit const* unitTarget = target->ToUnit();
337 if (!unitTarget)
338 return false;
339 return unitTarget->HasAuraEffect(Aura.SpellId, uint8(Aura.EffectIndex));
340 }
342 return CompareValues(ComparisionType(Value.ComparisonType), miscValue1, Value.Value);
344 if (!target)
345 return false;
346 return target->GetLevelForTarget(source) >= Level.Min;
348 {
349 if (!target)
350 return false;
351 Unit const* unitTarget = target->ToUnit();
352 if (!unitTarget)
353 return false;
354 return unitTarget->GetGender() == static_cast<::Gender>(Gender.Gender);
355 }
357 {
358 Unit const* unitTarget = nullptr;
359 if (target)
360 unitTarget = target->ToUnit();
361 return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(unitTarget));
362 }
364 return source->GetMap()->GetPlayersCountExceptGMs() <= MapPlayers.MaxCount;
366 if (!target || target->GetTypeId() != TYPEID_PLAYER)
367 return false;
368 return target->ToPlayer()->GetTeam() == ::Team(Team.Team);
374 return IsEventActive(uint16(GameEvent.Id));
376 {
377 Battleground* bg = source->GetBattleground();
378 if (!bg)
379 return false;
380
381 uint32 score = bg->GetTeamScore(bg->GetPlayerTeam(source->GetGUID()) == ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE);
382 return score >= BattlegroundScore.Min && score <= BattlegroundScore.Max;
383 }
385 {
386 if (!source->IsInWorld())
387 return false;
388 class Map* map = source->GetMap();
389 if (!map->IsDungeon())
390 {
391 TC_LOG_ERROR("criteria", "Criteria system call CRITERIA_DATA_TYPE_INSTANCE_SCRIPT ({}) for criteria {} in a non-dungeon/non-raid map {}",
392 DataType, criteriaId, map->GetId());
393 return false;
394 }
395 InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript();
396 if (!instance)
397 {
398 TC_LOG_ERROR("criteria", "Criteria system call CRITERIA_DATA_TYPE_INSTANCE_SCRIPT ({}) for criteria {} in map {}, but the map does not have an instance script.",
399 DataType, criteriaId, map->GetId());
400 return false;
401 }
402
403 Unit const* unitTarget = nullptr;
404 if (target)
405 unitTarget = target->ToUnit();
406 return instance->CheckAchievementCriteriaMeet(criteriaId, source, unitTarget, miscValue1);
407 }
409 {
410 Criteria const* entry = ASSERT_NOTNULL(sCriteriaMgr->GetCriteria(criteriaId));
411
412 uint32 itemId = (CriteriaType(entry->Entry->Type) == CriteriaType::EquipItemInSlot ? miscValue2 : miscValue1);
413 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
414 if (!itemTemplate)
415 return false;
416 return itemTemplate->GetBaseItemLevel() >= EquippedItem.ItemLevel && itemTemplate->GetQuality() >= EquippedItem.Quality;
417 }
419 return source->GetMapId() == Map.Id;
421 {
422 if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(KnownTitle.Id))
423 return source && source->HasTitle(titleInfo->MaskID);
424
425 return false;
426 }
428 {
429 ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
430 if (!pProto)
431 return false;
432 return pProto->GetQuality() == ItemQuality.Quality;
433 }
434 default:
435 break;
436 }
437 return false;
438}
439
440bool CriteriaDataSet::Meets(Player const* source, WorldObject const* target, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/) const
441{
442 for (CriteriaData const& criteriadata : _storage)
443 if (!criteriadata.Meets(_criteriaId, source, target, miscValue1, miscValue2))
444 return false;
445
446 return true;
447}
448
450
452
454{
455 for (std::pair<uint32 const, CriteriaProgress> const& criteriaprogress : _criteriaProgress)
456 SendCriteriaProgressRemoved(criteriaprogress.first);
457
458 _criteriaProgress.clear();
459}
460
464void CriteriaHandler::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, WorldObject const* ref /*= nullptr*/, Player* referencePlayer /*= nullptr*/)
465{
466 if (type >= CriteriaType::Count)
467 {
468 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: Wrong criteria type {}", uint32(type));
469 return;
470 }
471
472 if (!referencePlayer)
473 {
474 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: Player is NULL! Cant update criteria");
475 return;
476 }
477
478 // Disable for GameMasters with GM-mode enabled or for players that don't have the related RBAC permission
479 if (referencePlayer->IsGameMaster() || referencePlayer->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS))
480 {
481 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: [Player {} {}] {}, {} ({}), {}, {}, " UI64FMTD,
482 referencePlayer->GetName(), referencePlayer->IsGameMaster() ? "GM mode on" : "disallowed by RBAC",
483 GetOwnerInfo(), CriteriaMgr::GetCriteriaTypeString(type), uint32(type), miscValue1, miscValue2, miscValue3);
484 return;
485 }
486
487 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria({}, {}, {}, {}, {}) {}",
488 CriteriaMgr::GetCriteriaTypeString(type), uint32(type), miscValue1, miscValue2, miscValue3, GetOwnerInfo());
489
490 CriteriaList const& criteriaList = GetCriteriaByType(type, uint32(miscValue1));
491 for (Criteria const* criteria : criteriaList)
492 {
493 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
494 if (!CanUpdateCriteria(criteria, trees, miscValue1, miscValue2, miscValue3, ref, referencePlayer))
495 continue;
496
497 // requirements not found in the dbc
498 if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
499 if (!data->Meets(referencePlayer, ref, uint32(miscValue1), uint32(miscValue2)))
500 continue;
501
502 switch (type)
503 {
504 // std. case: increment at 1
509 case CriteriaType::AuctionsWon: /* FIXME: for online player only currently */
544 case CriteriaType::WinArena: // This also behaves like CriteriaType::WinAnyRankedArena
560 SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
561 break;
562 // std case: increment at miscValue1
570 case CriteriaType::MoneyEarnedFromAuctions:/* FIXME: for online player only currently */
578 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
579 break;
586 SetCriteriaProgress(criteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
587 break;
588 // std case: high value at miscValue1
590 case CriteriaType::HighestAuctionSale: /* FIXME: for online player only currently */
596 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
597 break;
599 SetCriteriaProgress(criteria, referencePlayer->GetLevel(), referencePlayer);
600 break;
602 if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(criteria->Entry->Asset.SkillID))
603 SetCriteriaProgress(criteria, skillvalue, referencePlayer);
604 break;
606 if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(criteria->Entry->Asset.SkillID))
607 SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer);
608 break;
610 SetCriteriaProgress(criteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
611 break;
613 {
614 time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
615 CriteriaProgress *progress = GetCriteriaProgress(criteria);
616
617 if (!miscValue1) // Login case.
618 {
619 // reset if player missed one day.
620 if (progress && progress->Date < (nextDailyResetTime - 2 * DAY))
621 SetCriteriaProgress(criteria, 0, referencePlayer, PROGRESS_SET);
622 continue;
623 }
624
625 ProgressType progressType;
626 if (!progress)
627 // 1st time. Start count.
628 progressType = PROGRESS_SET;
629 else if (progress->Date < (nextDailyResetTime - 2 * DAY))
630 // last progress is older than 2 days. Player missed 1 day => Restart count.
631 progressType = PROGRESS_SET;
632 else if (progress->Date < (nextDailyResetTime - DAY))
633 // last progress is between 1 and 2 days. => 1st time of the day.
634 progressType = PROGRESS_ACCUMULATE;
635 else
636 // last progress is within the day before the reset => Already counted today.
637 continue;
638
639 SetCriteriaProgress(criteria, 1, referencePlayer, progressType);
640 break;
641 }
643 {
644 if (miscValue1)
645 {
646 SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
647 }
648 else // login case
649 {
650 uint32 counter = 0;
651
652 RewardedQuestSet const& rewQuests = referencePlayer->getRewardedQuests();
653 for (uint32 rewQuest : rewQuests)
654 {
655 Quest const* quest = sObjectMgr->GetQuestTemplate(rewQuest);
656 if (quest && quest->GetZoneOrSort() >= 0 && quest->GetZoneOrSort() == criteria->Entry->Asset.ZoneID)
657 ++counter;
658 }
659 SetCriteriaProgress(criteria, counter, referencePlayer, PROGRESS_HIGHEST);
660 }
661 break;
662 }
664 // miscValue1 is the ingame fallheight*100 as stored in dbc
665 SetCriteriaProgress(criteria, miscValue1, referencePlayer);
666 break;
682 SetCriteriaProgress(criteria, 1, referencePlayer);
683 break;
685 SetCriteriaProgress(criteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
686 break;
688 {
689 int32 reputation = referencePlayer->GetReputationMgr().GetReputation(criteria->Entry->Asset.FactionID);
690 if (reputation > 0)
691 SetCriteriaProgress(criteria, reputation, referencePlayer);
692 break;
693 }
695 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
696 break;
699 {
700 uint32 spellCount = 0;
701 for (auto& [spellId, _] : referencePlayer->GetSpellMap())
702 {
703 SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
704 for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter)
705 {
706 if (skillIter->second->SkillLine == int32(criteria->Entry->Asset.SkillID))
707 {
708 // do not add couter twice if by any chance skill is listed twice in dbc (eg. skill 777 and spell 22717)
709 ++spellCount;
710 break;
711 }
712 }
713 }
714 SetCriteriaProgress(criteria, spellCount, referencePlayer);
715 break;
716 }
718 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
719 break;
721 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
722 break;
724 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
725 break;
727 SetCriteriaProgress(criteria, referencePlayer->m_activePlayerData->LifetimeHonorableKills, referencePlayer);
728 break;
730 SetCriteriaProgress(criteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
731 break;
733 if (!miscValue1)
734 continue;
735 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
736 break;
738 {
739 uint32 reqTeamType = criteria->Entry->Asset.TeamType;
740
741 if (miscValue1)
742 {
743 if (miscValue2 != reqTeamType)
744 continue;
745
746 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
747 }
748 else // login case
749 {
750 for (uint8 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
751 {
752 uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
753 if (!teamId)
754 continue;
755
756 ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
757 if (!team || team->GetType() != reqTeamType)
758 continue;
759
760 if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
761 {
762 SetCriteriaProgress(criteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
763 break;
764 }
765 }
766 }
767 break;
768 }
770 SetCriteriaProgress(criteria, referencePlayer->GetSession()->GetBattlePetMgr()->GetPetUniqueSpeciesCount(), referencePlayer);
771 break;
773 SetCriteriaProgress(criteria, miscValue1, referencePlayer);
774 break;
775 // FIXME: not triggered in code as result, need to implement
851 default:
852 break; // Not implemented yet :(
853 }
854
855 for (CriteriaTree const* tree : *trees)
856 {
857 if (IsCompletedCriteriaTree(tree))
858 CompletedCriteriaTree(tree, referencePlayer);
859
860 AfterCriteriaTreeUpdate(tree, referencePlayer);
861 }
862 }
863}
864
866{
867 for (auto itr = _startedCriteria.begin(); itr != _startedCriteria.end();)
868 {
869 // Time is up, remove timer and reset progress
870 if (itr->second <= timeDiff)
871 {
872 RemoveCriteriaProgress(sCriteriaMgr->GetCriteria(itr->first));
873
874 itr = _startedCriteria.erase(itr);
875 }
876 else
877 {
878 itr->second -= timeDiff;
879 ++itr;
880 }
881 }
882}
883
884void CriteriaHandler::StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost /*= Milliseconds::zero()*/)
885{
886 CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByStartEvent(startEvent, entry);
887 if (!criteriaList)
888 return;
889
890 for (Criteria const* criteria : *criteriaList)
891 {
892 Milliseconds timeLimit = Milliseconds::max(); // this value is for criteria that have a start event requirement but no time limit
893 if (criteria->Entry->StartTimer)
894 timeLimit = Seconds(criteria->Entry->StartTimer);
895
896 timeLimit -= timeLost;
897
898 if (timeLimit <= Milliseconds::zero())
899 continue;
900
901 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
902 bool canStart = std::any_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
903 {
904 return !IsCompletedCriteriaTree(tree);
905 });
906
907 if (!canStart)
908 continue;
909
910 auto [itr, isNew] = _startedCriteria.try_emplace(criteria->ID, timeLimit);
911 if (!isNew)
912 {
913 if (!criteria->Entry->GetFlags().HasFlag(CriteriaFlags::ResetOnStart))
914 continue;
915
916 itr->second = timeLimit;
917 }
918
919 // and at client too
920 SetCriteriaProgress(criteria, 0, nullptr, PROGRESS_SET);
921 }
922}
923
925{
926 CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByFailEvent(failEvent, asset);
927 if (!criteriaList)
928 return;
929
930 for (Criteria const* criteria : *criteriaList)
931 {
932 _startedCriteria.erase(criteria->ID);
933
934 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
935 bool allTreesFullyComplete = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
936 {
937 CriteriaTree const* root = tree;
938 if (CriteriaTree const* parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent))
939 {
940 do
941 {
942 root = parent;
943 parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent);
944 } while (parent);
945 }
946
947 return IsCompletedCriteriaTree(root);
948 });
949
950 if (allTreesFullyComplete)
951 continue;
952
953 RemoveCriteriaProgress(criteria);
954 }
955}
956
958{
959 auto iter = _criteriaProgress.find(entry->ID);
960 if (iter == _criteriaProgress.end())
961 return nullptr;
962
963 return &iter->second;
964}
965
966void CriteriaHandler::SetCriteriaProgress(Criteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType progressType)
967{
968 TC_LOG_DEBUG("criteria", "CriteriaHandler::SetCriteriaProgress({}, {}) for {}", criteria->ID, changeValue, GetOwnerInfo());
969
970 CriteriaProgress* progress = GetCriteriaProgress(criteria);
971 if (!progress)
972 {
973 // not create record for 0 counter but allow it for timed criteria
974 // we will need to send 0 progress to client to start the timer
975 if (changeValue == 0 && !criteria->Entry->StartTimer)
976 return;
977
978 progress = &_criteriaProgress[criteria->ID];
979 progress->Counter = changeValue;
980 }
981 else
982 {
983 uint64 newValue = 0;
984 switch (progressType)
985 {
986 case PROGRESS_SET:
987 newValue = changeValue;
988 break;
990 {
991 // avoid overflow
992 uint64 max_value = std::numeric_limits<uint64>::max();
993 newValue = max_value - progress->Counter > changeValue ? progress->Counter + changeValue : max_value;
994 break;
995 }
996 case PROGRESS_HIGHEST:
997 newValue = progress->Counter < changeValue ? changeValue : progress->Counter;
998 break;
999 }
1000
1001 // not update (not mark as changed) if counter will have same value
1002 if (progress->Counter == newValue && !criteria->Entry->StartTimer)
1003 return;
1004
1005 progress->Counter = newValue;
1006 }
1007
1008 progress->Changed = true;
1009 progress->Date = GameTime::GetGameTime(); // set the date to the latest update.
1010 progress->PlayerGUID = referencePlayer ? referencePlayer->GetGUID() : ObjectGuid::Empty;
1011
1012 Seconds timeElapsed = Seconds::zero();
1013
1014 if (criteria->Entry->StartTimer)
1015 {
1016 auto startedItr = _startedCriteria.find(criteria->ID);
1017 if (startedItr != _startedCriteria.end())
1018 {
1019 // Client expects this in packet
1020 timeElapsed = duration_cast<Seconds>(Seconds(criteria->Entry->StartTimer) - startedItr->second);
1021
1022 // Remove the timer, we wont need it anymore
1023 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
1024
1025 bool allTreesCompleted = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
1026 {
1027 return IsCompletedCriteriaTree(tree);
1028 });
1029
1030 if (allTreesCompleted)
1031 _startedCriteria.erase(startedItr);
1032 }
1033 }
1034
1035 SendCriteriaUpdate(criteria, progress, timeElapsed, true);
1036}
1037
1039{
1040 if (!criteria)
1041 return;
1042
1043 auto criteriaProgress = _criteriaProgress.find(criteria->ID);
1044 if (criteriaProgress == _criteriaProgress.end())
1045 return;
1046
1048
1049 criteriaProgress->second.Counter = 0;
1050 criteriaProgress->second.Changed = true;
1051}
1052
1054{
1055 if (!CanCompleteCriteriaTree(tree))
1056 return false;
1057
1058 uint64 requiredCount = tree->Entry->Amount;
1059 switch (CriteriaTreeOperator(tree->Entry->Operator))
1060 {
1062 return tree->Criteria && IsCompletedCriteria(tree->Criteria, requiredCount);
1064 return !tree->Criteria || !IsCompletedCriteria(tree->Criteria, requiredCount);
1066 for (CriteriaTree const* node : tree->Children)
1067 if (!IsCompletedCriteriaTree(node))
1068 return false;
1069 return true;
1071 {
1072 uint64 progress = 0;
1073 CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree)
1074 {
1075 if (criteriaTree->Criteria)
1076 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria))
1077 progress += criteriaProgress->Counter;
1078 });
1079 return progress >= requiredCount;
1080 }
1082 {
1083 uint64 progress = 0;
1084 CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree)
1085 {
1086 if (criteriaTree->Criteria)
1087 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria))
1088 if (criteriaProgress->Counter > progress)
1089 progress = criteriaProgress->Counter;
1090 });
1091 return progress >= requiredCount;
1092 }
1094 {
1095 uint64 progress = 0;
1096 for (CriteriaTree const* node : tree->Children)
1097 if (node->Criteria)
1098 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(node->Criteria))
1099 if (criteriaProgress->Counter >= 1)
1100 if (++progress >= requiredCount)
1101 return true;
1102
1103 return false;
1104 }
1106 {
1107 uint64 progress = 0;
1108 for (CriteriaTree const* node : tree->Children)
1109 if (IsCompletedCriteriaTree(node))
1110 if (++progress >= requiredCount)
1111 return true;
1112
1113 return false;
1114 }
1116 {
1117 uint64 progress = 0;
1118 CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree)
1119 {
1120 if (criteriaTree->Criteria)
1121 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria))
1122 progress += criteriaProgress->Counter * criteriaTree->Entry->Amount;
1123 });
1124 return progress >= requiredCount;
1125 }
1126 default:
1127 break;
1128 }
1129
1130 return false;
1131}
1132
1133bool CriteriaHandler::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
1134{
1135 if ((tree->Entry->GetFlags().HasFlag(CriteriaTreeFlags::HordeOnly) && referencePlayer->GetTeam() != HORDE) ||
1136 (tree->Entry->GetFlags().HasFlag(CriteriaTreeFlags::AllianceOnly) && referencePlayer->GetTeam() != ALLIANCE))
1137 {
1138 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteriaTree: (Id: {} Type {} CriteriaTree {}) Wrong faction",
1139 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Entry->ID);
1140 return false;
1141 }
1142
1143 return true;
1144}
1145
1147{
1148 return true;
1149}
1150
1151bool CriteriaHandler::IsCompletedCriteria(Criteria const* criteria, uint64 requiredAmount)
1152{
1153 CriteriaProgress const* progress = GetCriteriaProgress(criteria);
1154 if (!progress)
1155 return false;
1156
1157 switch (CriteriaType(criteria->Entry->Type))
1158 {
1221 return progress->Counter >= requiredAmount;
1239 return progress->Counter >= 1;
1241 return progress->Counter >= (requiredAmount * 75);
1243 return progress->Counter >= 9000;
1245 return requiredAmount && progress->Counter >= requiredAmount;
1247 return true;
1248 // handle all statistic-only criteria here
1280 default:
1281 break;
1282 }
1283
1284 return false;
1285}
1286
1287bool CriteriaHandler::CanUpdateCriteria(Criteria const* criteria, CriteriaTreeList const* trees, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const* ref, Player* referencePlayer)
1288{
1289 if (DisableMgr::IsDisabledFor(DISABLE_TYPE_CRITERIA, criteria->ID, nullptr))
1290 {
1291 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Disabled", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1292 return false;
1293 }
1294
1295 bool treeRequirementPassed = false;
1296 for (CriteriaTree const* tree : *trees)
1297 {
1298 if (!CanUpdateCriteriaTree(criteria, tree, referencePlayer))
1299 continue;
1300
1301 treeRequirementPassed = true;
1302 break;
1303 }
1304
1305 if (!treeRequirementPassed)
1306 return false;
1307
1308 if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, miscValue3, ref, referencePlayer))
1309 {
1310 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Requirements not satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1311 return false;
1312 }
1313
1314 if (criteria->Modifier && !ModifierTreeSatisfied(criteria->Modifier, miscValue1, miscValue2, ref, referencePlayer))
1315 {
1316 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Requirements have not been satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1317 return false;
1318 }
1319
1320 if (!ConditionsSatisfied(criteria, referencePlayer))
1321 {
1322 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Conditions have not been satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1323 return false;
1324 }
1325
1326 if (criteria->Entry->EligibilityWorldStateID != 0)
1327 if (sWorldStateMgr->GetValue(criteria->Entry->EligibilityWorldStateID, referencePlayer->GetMap()) != criteria->Entry->EligibilityWorldStateValue)
1328 return false;
1329
1330 return true;
1331}
1332
1333bool CriteriaHandler::ConditionsSatisfied(Criteria const* criteria, Player* /*referencePlayer*/) const
1334{
1335 if (criteria->Entry->StartEvent && !_startedCriteria.contains(criteria->ID))
1336 return false;
1337
1338 return true;
1339}
1340
1341bool CriteriaHandler::RequirementsSatisfied(Criteria const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const* ref, Player* referencePlayer) const
1342{
1343 switch (CriteriaType(criteria->Entry->Type))
1344 {
1386 if (!miscValue1)
1387 return false;
1388 break;
1402 break;
1405 return false;
1406 break;
1410 if (!miscValue1 || uint32(criteria->Entry->Asset.MapID) != referencePlayer->GetMapId())
1411 return false;
1412 break;
1415 if (!miscValue1 || uint32(criteria->Entry->Asset.CreatureID) != miscValue1)
1416 return false;
1417 break;
1420 // update at loading or specific skill update
1421 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.SkillID))
1422 return false;
1423 break;
1425 if (miscValue1)
1426 {
1427 Quest const* quest = sObjectMgr->GetQuestTemplate(miscValue1);
1428 if (!quest || quest->GetZoneOrSort() != criteria->Entry->Asset.ZoneID)
1429 return false;
1430 }
1431 break;
1433 {
1434 if (!miscValue1)
1435 return false;
1436 break;
1437 }
1439 {
1440 if (!miscValue1)
1441 return false;
1442
1443 Map const* map = referencePlayer->IsInWorld() ? referencePlayer->GetMap() : sMapMgr->FindMap(referencePlayer->GetMapId(), referencePlayer->GetInstanceId());
1444 if (!map || !map->IsDungeon())
1445 return false;
1446
1447 //FIXME: work only for instances where max == min for players
1448 if (map->ToInstanceMap()->GetMaxPlayers() != uint32(criteria->Entry->Asset.GroupSize))
1449 return false;
1450 break;
1451 }
1453 if (!miscValue1 || !ref || ref->GetTypeId() != TYPEID_PLAYER)
1454 return false;
1455 break;
1457 if (!miscValue1 || miscValue2 != uint32(criteria->Entry->Asset.EnviromentalDamageType))
1458 return false;
1459 break;
1461 {
1462 // if miscValues != 0, it contains the questID.
1463 if (miscValue1)
1464 {
1465 if (miscValue1 != uint32(criteria->Entry->Asset.QuestID))
1466 return false;
1467 }
1468 else
1469 {
1470 // login case.
1471 if (!referencePlayer->GetQuestRewardStatus(criteria->Entry->Asset.QuestID))
1472 return false;
1473 }
1474
1475 if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
1476 if (!data->Meets(referencePlayer, ref))
1477 return false;
1478 break;
1479 }
1484 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.SpellID))
1485 return false;
1486 break;
1488 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.SpellID))
1489 return false;
1490
1491 if (!referencePlayer->HasSpell(criteria->Entry->Asset.SpellID))
1492 return false;
1493 break;
1495 // miscValue1 = itemId - miscValue2 = count of item loot
1496 // miscValue3 = loot_type (note: 0 = LOOT_CORPSE and then it ignored)
1497 if (!miscValue1 || !miscValue2 || !miscValue3 || miscValue3 != uint32(criteria->Entry->Asset.LootType))
1498 return false;
1499 break;
1501 if (miscValue1 && uint32(criteria->Entry->Asset.ItemID) != miscValue1)
1502 return false;
1503 break;
1507 if (!miscValue1 || uint32(criteria->Entry->Asset.ItemID )!= miscValue1)
1508 return false;
1509 break;
1511 {
1512 WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(criteria->Entry->Asset.WorldMapOverlayID);
1513 if (!worldOverlayEntry)
1514 break;
1515
1516 bool matchFound = false;
1517 for (uint32 j : worldOverlayEntry->AreaID)
1518 {
1519 if (referencePlayer->HasExploredZone(j))
1520 {
1521 matchFound = true;
1522 break;
1523 }
1524 }
1525
1526 if (!matchFound)
1527 return false;
1528 break;
1529 }
1531 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.FactionID))
1532 return false;
1533 break;
1536 // miscValue1 = EquipmentSlot miscValue2 = itemid | itemModifiedAppearanceId
1537 if (!miscValue2 || miscValue1 != uint32(criteria->Entry->Asset.EquipmentSlot))
1538 return false;
1539 break;
1542 {
1543 // miscValue1 = itemid miscValue2 = diced value
1544 if (!miscValue1 || miscValue2 != uint32(criteria->Entry->Asset.RollValue))
1545 return false;
1546
1547 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1548 if (!proto)
1549 return false;
1550 break;
1551 }
1553 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.EmoteID))
1554 return false;
1555 break;
1558 if (!miscValue1)
1559 return false;
1560
1562 {
1563 if (!referencePlayer->InBattleground())
1564 return false;
1565
1566 // map specific case (BG in fact) expected player targeted damage/heal
1567 if (!ref || ref->GetTypeId() != TYPEID_PLAYER)
1568 return false;
1569 }
1570 break;
1573 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.GameObjectID))
1574 return false;
1575 break;
1578 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.SkillID))
1579 return false;
1580 break;
1582 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.ClassID))
1583 return false;
1584 break;
1586 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.RaceID))
1587 return false;
1588 break;
1590 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.WorldStateUIID))
1591 return false;
1592 break;
1595 if (!miscValue1 || !DB2Manager::IsInArea(uint32(miscValue1), uint32(criteria->Entry->Asset.AreaID)))
1596 return false;
1597 break;
1599 if (!miscValue1 || DB2Manager::IsInArea(uint32(miscValue1), uint32(criteria->Entry->Asset.AreaID)))
1600 return false;
1601 break;
1603 if (!miscValue1 || !miscValue2 || int64(miscValue2) < 0
1604 || miscValue1 != uint32(criteria->Entry->Asset.CurrencyID))
1605 return false;
1606 break;
1608 if (miscValue1 != uint32(criteria->Entry->Asset.MapID))
1609 return false;
1610 break;
1612 return false;
1615 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.DungeonEncounterID))
1616 return false;
1617 break;
1620 if (miscValue1 != uint32(criteria->Entry->Asset.GarrBuildingID))
1621 return false;
1622 break;
1624 if (miscValue1 != uint32(criteria->Entry->Asset.GarrFollowerID))
1625 return false;
1626 break;
1628 if (miscValue1 != uint32(criteria->Entry->Asset.TransmogSetGroupID))
1629 return false;
1630 break;
1633 if (!miscValue1 || !miscValue2 || miscValue2 != uint32(criteria->Entry->Asset.PetLevel))
1634 return false;
1635 break;
1637 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.PlayerLevel))
1638 return false;
1639 break;
1642 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.ZoneID))
1643 return false;
1644 break;
1647 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.EventID))
1648 return false;
1649 break;
1650 default:
1651 break;
1652 }
1653 return true;
1654}
1655
1656bool CriteriaHandler::ModifierTreeSatisfied(ModifierTreeNode const* tree, uint64 miscValue1, uint64 miscValue2, WorldObject const* ref, Player* referencePlayer) const
1657{
1658 switch (ModifierTreeOperator(tree->Entry->Operator))
1659 {
1661 return tree->Entry->Type && ModifierSatisfied(tree->Entry, miscValue1, miscValue2, ref, referencePlayer);
1663 return tree->Entry->Type && !ModifierSatisfied(tree->Entry, miscValue1, miscValue2, ref, referencePlayer);
1665 for (ModifierTreeNode const* node : tree->Children)
1666 if (!ModifierTreeSatisfied(node, miscValue1, miscValue2, ref, referencePlayer))
1667 return false;
1668 return true;
1670 {
1671 int8 requiredAmount = std::max<int8>(tree->Entry->Amount, 1);
1672 for (ModifierTreeNode const* node : tree->Children)
1673 if (ModifierTreeSatisfied(node, miscValue1, miscValue2, ref, referencePlayer))
1674 if (!--requiredAmount)
1675 return true;
1676
1677 return false;
1678 }
1679 default:
1680 break;
1681 }
1682
1683 return false;
1684}
1685
1686bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint64 miscValue1, uint64 miscValue2, WorldObject const* ref, Player* referencePlayer) const
1687{
1688 uint32 reqValue = modifier->Asset;
1689 uint32 secondaryAsset = modifier->SecondaryAsset;
1690 int32 tertiaryAsset = modifier->TertiaryAsset;
1691
1692 switch (ModifierTreeType(modifier->Type))
1693 {
1695 {
1696 uint32 inebriation = std::min(std::max<uint32>(referencePlayer->GetDrunkValue(), *referencePlayer->m_playerData->FakeInebriation), 100u);
1697 if (inebriation < reqValue)
1698 return false;
1699 break;
1700 }
1702 {
1703 PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(reqValue);
1704 if (!playerCondition || !ConditionMgr::IsPlayerMeetingCondition(referencePlayer, playerCondition))
1705 return false;
1706 break;
1707 }
1709 {
1710 // miscValue1 is itemid
1711 ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1712 if (!item || item->GetBaseItemLevel() < reqValue)
1713 return false;
1714 break;
1715 }
1717 if (!ref || ref->GetEntry() != reqValue)
1718 return false;
1719 break;
1721 if (!ref || ref->GetTypeId() != TYPEID_PLAYER)
1722 return false;
1723 break;
1725 if (!ref || !ref->IsUnit() || ref->ToUnit()->IsAlive())
1726 return false;
1727 break;
1729 if (!ref || !referencePlayer->IsHostileTo(ref))
1730 return false;
1731 break;
1733 if (!referencePlayer->HasAura(reqValue))
1734 return false;
1735 break;
1737 if (!referencePlayer->HasAuraType(AuraType(reqValue)))
1738 return false;
1739 break;
1741 if (!ref || !ref->IsUnit() || !ref->ToUnit()->HasAura(reqValue))
1742 return false;
1743 break;
1745 if (!ref || !ref->IsUnit() || !ref->ToUnit()->HasAuraType(AuraType(reqValue)))
1746 return false;
1747 break;
1749 if (!ref || !ref->IsUnit() || !ref->ToUnit()->HasAuraState(AuraStateType(reqValue)))
1750 return false;
1751 break;
1753 if (!referencePlayer->HasAuraState(AuraStateType(reqValue)))
1754 return false;
1755 break;
1757 {
1758 // miscValue1 is itemid
1759 ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1760 if (!item || item->GetQuality() < reqValue)
1761 return false;
1762 break;
1763 }
1765 {
1766 // miscValue1 is itemid
1767 ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1768 if (!item || item->GetQuality() != reqValue)
1769 return false;
1770 break;
1771 }
1773 if (referencePlayer->isDead())
1774 return false;
1775 break;
1777 {
1778 if (!DB2Manager::IsInArea(referencePlayer->GetAreaId(), reqValue))
1779 return false;
1780 break;
1781 }
1783 {
1784 if (!ref)
1785 return false;
1786 if (!DB2Manager::IsInArea(ref->GetAreaId(), reqValue))
1787 return false;
1788 break;
1789 }
1790 case ModifierTreeType::ItemId: // 19
1791 if (miscValue1 != reqValue)
1792 return false;
1793 break;
1795 {
1796 DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(referencePlayer->GetMap()->GetDifficultyID());
1797 if (!difficulty || difficulty->OldEnumValue == -1 || uint32(difficulty->OldEnumValue) != reqValue)
1798 return false;
1799 break;
1800 }
1802 if (!ref || !ref->IsUnit() || referencePlayer->GetLevel() < ref->ToUnit()->GetLevel() + reqValue)
1803 return false;
1804 break;
1806 if (!ref || !ref->IsUnit() || referencePlayer->GetLevel() + reqValue < ref->ToUnit()->GetLevel())
1807 return false;
1808 break;
1810 if (!ref || !ref->IsUnit() || referencePlayer->GetLevel() != ref->ToUnit()->GetLevel())
1811 return false;
1812 break;
1814 {
1815 Battleground* bg = referencePlayer->GetBattleground();
1816 if (!bg || !bg->isArena() || bg->GetArenaType() != reqValue)
1817 return false;
1818 break;
1819 }
1821 if (referencePlayer->GetRace() != reqValue)
1822 return false;
1823 break;
1825 if (referencePlayer->GetClass() != reqValue)
1826 return false;
1827 break;
1829 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetRace() != reqValue)
1830 return false;
1831 break;
1833 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetClass() != reqValue)
1834 return false;
1835 break;
1837 if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= reqValue)
1838 return false;
1839 break;
1841 {
1842 if (!ref)
1843 return false;
1844 if (!ref->IsUnit() || ref->ToUnit()->GetCreatureType() != reqValue)
1845 return false;
1846 break;
1847 }
1849 {
1850 if (!ref)
1851 return false;
1852 if (!ref->IsCreature() || ref->ToCreature()->GetCreatureTemplate()->family != CreatureFamily(reqValue))
1853 return false;
1854 break;
1855 }
1856 case ModifierTreeType::PlayerMap: // 32
1857 if (referencePlayer->GetMapId() != reqValue)
1858 return false;
1859 break;
1861 if (reqValue < sRealmList->GetMinorMajorBugfixVersionForBuild(realm.Build))
1862 return false;
1863 break;
1865 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
1866 if (slot.Pet.Level < reqValue)
1867 return false;
1868 break;
1870 if (referencePlayer->GetGroup())
1871 return false;
1872 break;
1874 if (!referencePlayer->GetGroup())
1875 return false;
1876 break;
1878 if (referencePlayer->GetMaxPersonalArenaRatingRequirement(0) < reqValue)
1879 return false;
1880 break;
1881 case ModifierTreeType::HasTitle: // 38
1882 if (!referencePlayer->HasTitle(reqValue))
1883 return false;
1884 break;
1886 if (referencePlayer->GetLevel() != reqValue)
1887 return false;
1888 break;
1890 if (!ref || ref->GetLevelForTarget(referencePlayer) != reqValue)
1891 return false;
1892 break;
1894 {
1895 uint32 zoneId = referencePlayer->GetAreaId();
1896 if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId))
1897 if (areaEntry->GetFlags().HasFlag(AreaFlags::IsSubzone))
1898 zoneId = areaEntry->ParentAreaID;
1899 if (zoneId != reqValue)
1900 return false;
1901 break;
1902 }
1904 {
1905 if (!ref)
1906 return false;
1907 uint32 zoneId = ref->GetAreaId();
1908 if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId))
1909 if (areaEntry->GetFlags().HasFlag(AreaFlags::IsSubzone))
1910 zoneId = areaEntry->ParentAreaID;
1911 if (zoneId != reqValue)
1912 return false;
1913 break;
1914 }
1916 if (referencePlayer->GetHealthPct() > float(reqValue))
1917 return false;
1918 break;
1920 if (referencePlayer->GetHealthPct() < float(reqValue))
1921 return false;
1922 break;
1924 if (referencePlayer->GetHealthPct() != float(reqValue))
1925 return false;
1926 break;
1928 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealthPct() > float(reqValue))
1929 return false;
1930 break;
1932 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealthPct() < float(reqValue))
1933 return false;
1934 break;
1936 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealthPct() != float(reqValue))
1937 return false;
1938 break;
1940 if (referencePlayer->GetHealth() > reqValue)
1941 return false;
1942 break;
1944 if (referencePlayer->GetHealth() < reqValue)
1945 return false;
1946 break;
1948 if (referencePlayer->GetHealth() != reqValue)
1949 return false;
1950 break;
1952 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealth() > reqValue)
1953 return false;
1954 break;
1956 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealth() < reqValue)
1957 return false;
1958 break;
1960 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealth() != reqValue)
1961 return false;
1962 break;
1964 {
1965 if (!ref || !ref->IsPlayer())
1966 return false;
1967
1968 PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(reqValue);
1969 if (!playerCondition || !ConditionMgr::IsPlayerMeetingCondition(ref->ToPlayer(), playerCondition))
1970 return false;
1971 break;
1972 }
1974 if (referencePlayer->GetAchievementPoints() <= reqValue)
1975 return false;
1976 break;
1979 return false;
1980 break;
1983 return false;
1984 break;
1987 return false;
1988 break;
1990 {
1991 Battleground const* bg = referencePlayer->GetBattleground();
1992 if (!bg || !bg->isArena() || !bg->isRated())
1993 return false;
1994 break;
1995 }
1997 return false;
1999 if (referencePlayer->GetReputationMgr().GetReputation(1168) < int32(reqValue))
2000 return false;
2001 break;
2003 {
2004 Battleground const* bg = referencePlayer->GetBattleground();
2005 if (!bg || !bg->isBattleground() || !bg->isRated())
2006 return false;
2007 break;
2008 }
2010 if (referencePlayer->GetRBGPersonalRating() < reqValue)
2011 return false;
2012 break;
2015 return false;
2017 if (WorldStateExpressionEntry const* worldStateExpression = sWorldStateExpressionStore.LookupEntry(reqValue))
2018 return ConditionMgr::IsMeetingWorldStateExpression(referencePlayer->GetMap(), worldStateExpression);
2019 return false;
2021 if (referencePlayer->GetMap()->GetDifficultyID() != reqValue)
2022 return false;
2023 break;
2025 if (referencePlayer->GetLevel() < reqValue)
2026 return false;
2027 break;
2029 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetLevel() < reqValue)
2030 return false;
2031 break;
2033 if (referencePlayer->GetLevel() > reqValue)
2034 return false;
2035 break;
2037 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetLevel() > reqValue)
2038 return false;
2039 break;
2041 if (ModifierTreeNode const* nextModifierTree = sCriteriaMgr->GetModifierTree(reqValue))
2042 return ModifierTreeSatisfied(nextModifierTree, miscValue1, miscValue2, ref, referencePlayer);
2043 return false;
2045 {
2046 Scenario const* scenario = referencePlayer->GetScenario();
2047 if (!scenario || scenario->GetEntry()->ID != reqValue)
2048 return false;
2049 break;
2050 }
2052 if (referencePlayer->GetReputationMgr().GetReputation(1272) < int32(reqValue))
2053 return false;
2054 break;
2056 {
2057 auto getRootAchievementCategory = [](AchievementEntry const* achievement)
2058 {
2059 int16 category = achievement->Category;
2060 do
2061 {
2062 Achievement_CategoryEntry const* categoryEntry = sAchievementCategoryStore.LookupEntry(category);
2063 if (!categoryEntry || categoryEntry->Parent == -1)
2064 break;
2065
2066 category = categoryEntry->Parent;
2067 } while (true);
2068
2069 return category;
2070 };
2071
2072 uint32 petAchievementPoints = 0;
2073 for (uint32 achievementId : referencePlayer->GetCompletedAchievementIds())
2074 {
2075 AchievementEntry const* achievement = sAchievementStore.AssertEntry(achievementId);
2076 if (getRootAchievementCategory(achievement) == ACHIVEMENT_CATEGORY_PET_BATTLES)
2077 petAchievementPoints += uint32(achievement->Points);
2078 }
2079
2080 if (petAchievementPoints < reqValue)
2081 return false;
2082 break;
2083 }
2085 if (referencePlayer->GetSession()->GetBattlePetMgr()->GetPetUniqueSpeciesCount() < reqValue)
2086 return false;
2087 break;
2089 {
2090 BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(miscValue1);
2091 if (!speciesEntry || speciesEntry->PetTypeEnum != int32(reqValue))
2092 return false;
2093 break;
2094 }
2095 case ModifierTreeType::BattlePetHealthPercentLessThan: // 79 NYI - use target battle pet here, the one we were just battling
2096 return false;
2098 {
2099 uint32 guildMemberCount = 0;
2100 if (Group const* group = referencePlayer->GetGroup())
2101 for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
2102 if (itr->GetSource()->GetGuildId() == referencePlayer->GetGuildId())
2103 ++guildMemberCount;
2104
2105 if (guildMemberCount < reqValue)
2106 return false;
2107 break;
2108 }
2110 return false;
2112 {
2113 Scenario const* scenario = referencePlayer->GetScenario();
2114 if (!scenario)
2115 return false;
2116 if (scenario->GetStep()->OrderIndex != (reqValue - 1))
2117 return false;
2118 break;
2119 }
2121 return false; // OBSOLETE
2123 if (referencePlayer->FindQuestSlot(reqValue) == MAX_QUEST_LOG_SIZE)
2124 return false;
2125 break;
2127 if (referencePlayer->GetReputationMgr().GetReputation(reqValue) < 42000)
2128 return false;
2129 break;
2132 if (!referencePlayer->HasAchieved(reqValue))
2133 return false;
2134 break;
2136 if (referencePlayer->GetReputationMgr().GetReputation(1271) < int32(reqValue))
2137 return false;
2138 break;
2141 return false;
2143 if (miscValue1 != reqValue)
2144 return false;
2145 break;
2147 if (sWorld->getIntConfig(CONFIG_EXPANSION) < reqValue)
2148 return false;
2149 break;
2151 if (!referencePlayer->GetSession()->GetBattlePetMgr()->HasJournalLock())
2152 return false;
2153 break;
2155 {
2156 FriendshipRepReactionEntry const* friendshipRepReaction = sFriendshipRepReactionStore.LookupEntry(reqValue);
2157 if (!friendshipRepReaction)
2158 return false;
2159 FriendshipReputationEntry const* friendshipReputation = sFriendshipReputationStore.LookupEntry(friendshipRepReaction->FriendshipRepID);
2160 if (!friendshipReputation)
2161 return false;
2162 if (referencePlayer->GetReputation(friendshipReputation->FactionID) < int32(friendshipRepReaction->ReactionThreshold))
2163 return false;
2164 break;
2165 }
2167 if (referencePlayer->GetReputationMgr().GetReputation(reqValue) < int32(secondaryAsset))
2168 return false;
2169 break;
2171 {
2172 ItemTemplate const* item = sObjectMgr->GetItemTemplate(miscValue1);
2173 if (!item || item->GetClass() != reqValue || item->GetSubClass() != secondaryAsset)
2174 return false;
2175 break;
2176 }
2178 if (referencePlayer->GetGender() != uint8(reqValue))
2179 return false;
2180 break;
2182 if (referencePlayer->GetNativeGender() != uint8(reqValue))
2183 return false;
2184 break;
2186 if (referencePlayer->GetPureSkillValue(reqValue) < uint16(secondaryAsset))
2187 return false;
2188 break;
2190 {
2191 auto languageDescs = sLanguageMgr->GetLanguageDescById(Language(reqValue));
2192 bool hasLanguageSkil = std::any_of(languageDescs.begin(), languageDescs.end(), [&](std::pair<uint32 const, LanguageDesc> const& desc)
2193 {
2194 return referencePlayer->GetSkillValue(desc.second.SkillId) >= secondaryAsset;
2195 });
2196 if (!hasLanguageSkil)
2197 return false;
2198 break;
2199 }
2201 if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, 0, 0))
2202 return false;
2203 break;
2205 if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, reqValue, 0))
2206 return false;
2207 break;
2209 if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, 0, reqValue))
2210 return false;
2211 break;
2213 if (!referencePlayer->HasSpell(reqValue))
2214 return false;
2215 break;
2217 if (referencePlayer->GetItemCount(reqValue, false) < secondaryAsset)
2218 return false;
2219 break;
2221 if (referencePlayer->GetSession()->GetExpansion() < reqValue)
2222 return false;
2223 break;
2225 if (!referencePlayer->HasAura([labelId = reqValue](Aura const* aura) { return aura->GetSpellInfo()->HasLabel(labelId); }))
2226 return false;
2227 break;
2229 if (sWorldStateMgr->GetValue(reqValue, referencePlayer->GetMap()) != int32(secondaryAsset))
2230 return false;
2231 break;
2233 {
2234 WowTime from;
2235 from.SetPackedTime(reqValue);
2236 WowTime to;
2237 to.SetPackedTime(secondaryAsset);
2238
2239 if (!GameTime::GetWowTime()->IsInRange(from, to))
2240 return false;
2241 break;
2242 }
2244 if (uint32 questBit = sDB2Manager.GetQuestUniqueBitFlag(reqValue))
2245 if (!(referencePlayer->m_activePlayerData->QuestCompleted[((questBit - 1) >> 6)] & (UI64LIT(1) << ((questBit - 1) & 63))))
2246 return false;
2247 break;
2249 if (referencePlayer->GetQuestStatus(reqValue) != QUEST_STATUS_COMPLETE)
2250 return false;
2251 break;
2253 {
2254 QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
2255 if (!objective)
2256 return false;
2257 Quest const* quest = sObjectMgr->GetQuestTemplate(objective->QuestID);
2258 if (!quest)
2259 return false;
2260 uint16 slot = referencePlayer->FindQuestSlot(objective->QuestID);
2261 if (slot >= MAX_QUEST_LOG_SIZE || referencePlayer->GetQuestRewardStatus(objective->QuestID) || !referencePlayer->IsQuestObjectiveComplete(slot, quest, *objective))
2262 return false;
2263 break;
2264 }
2266 {
2267 if (!referencePlayer->HasExploredZone(reqValue))
2268 return false;
2269 break;
2270 }
2272 if (referencePlayer->GetItemCount(reqValue, true) < secondaryAsset)
2273 return false;
2274 break;
2275 case ModifierTreeType::Weather: // 115
2276 if (referencePlayer->GetMap()->GetZoneWeather(referencePlayer->GetZoneId()) != WeatherState(reqValue))
2277 return false;
2278 break;
2280 {
2281 ChrRacesEntry const* race = sChrRacesStore.LookupEntry(referencePlayer->GetRace());
2282 if (!race)
2283 return false;
2284 FactionTemplateEntry const* faction = sFactionTemplateStore.LookupEntry(race->FactionID);
2285 if (!faction)
2286 return false;
2287 int32 factionIndex = -1;
2288 if (faction->FactionGroup & FACTION_MASK_HORDE)
2289 factionIndex = 0;
2290 else if (faction->FactionGroup & FACTION_MASK_ALLIANCE)
2291 factionIndex = 1;
2292 else if (faction->FactionGroup & FACTION_MASK_PLAYER)
2293 factionIndex = 0;
2294 if (factionIndex != int32(reqValue))
2295 return false;
2296 break;
2297 }
2299 if (ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus(reqValue)) != secondaryAsset)
2300 return false;
2301 break;
2303 if (ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus(reqValue)) < secondaryAsset)
2304 return false;
2305 break;
2307 if (!referencePlayer->HasCurrency(reqValue, secondaryAsset))
2308 return false;
2309 break;
2311 {
2312 if (!ref)
2313 return false;
2314 Unit const* unitRef = ref->ToUnit();
2315 if (!unitRef || !unitRef->CanHaveThreatList())
2316 return false;
2317 if (unitRef->GetThreatManager().GetThreatListSize() >= reqValue)
2318 return false;
2319 break;
2320 }
2322 if (referencePlayer->GetCurrencyTrackedQuantity(reqValue) < secondaryAsset)
2323 return false;
2324 break;
2326 if (referencePlayer->GetMap()->GetEntry()->InstanceType != int8(reqValue))
2327 return false;
2328 break;
2330 if (!referencePlayer->HasPlayerFlag(PLAYER_FLAGS_TIMEWALKING))
2331 return false;
2332 break;
2334 if (!sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS))
2335 return false;
2336 break;
2337 case ModifierTreeType::PvpSeason: // 125
2338 if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) != reqValue)
2339 return false;
2340 break;
2342 {
2343 Garrison const* garrison = referencePlayer->GetGarrison();
2344 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel < reqValue)
2345 return false;
2346 break;
2347 }
2349 {
2350 Garrison const* garrison = referencePlayer->GetGarrison();
2351 if (!garrison)
2352 return false;
2353 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2354 {
2355 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2356 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= secondaryAsset;
2357 });
2358 if (followerCount < reqValue)
2359 return false;
2360 break;
2361 }
2363 {
2364 Garrison const* garrison = referencePlayer->GetGarrison();
2365 if (!garrison)
2366 return false;
2367 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2368 {
2369 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2370 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.Quality >= secondaryAsset;
2371 });
2372 if (followerCount < reqValue)
2373 return false;
2374 break;
2375 }
2377 {
2378 Garrison const* garrison = referencePlayer->GetGarrison();
2379 if (!garrison)
2380 return false;
2381 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2382 {
2383 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2384 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
2385 });
2386 if (followerCount < 1)
2387 return false;
2388 break;
2389 }
2391 {
2392 Garrison const* garrison = referencePlayer->GetGarrison();
2393 if (!garrison)
2394 return false;
2395 GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(secondaryAsset);
2396 if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
2397 return false;
2398 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2399 {
2400 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2401 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
2402 });
2403 if (followerCount < 1)
2404 return false;
2405 break;
2406 }
2408 {
2409 Garrison const* garrison = referencePlayer->GetGarrison();
2410 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2411 return false;
2412 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2413 {
2414 GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
2415 if (!followerBuilding)
2416 return false;
2417 return followerBuilding->BuildingType == int32(secondaryAsset) && follower.HasAbility(reqValue);;
2418 });
2419 if (followerCount < 1)
2420 return false;
2421 break;
2422 }
2424 {
2425 Garrison const* garrison = referencePlayer->GetGarrison();
2426 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2427 return false;
2428 GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(reqValue);
2429 if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
2430 return false;
2431 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2432 {
2433 GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
2434 if (!followerBuilding)
2435 return false;
2436 return followerBuilding->BuildingType == int32(secondaryAsset) && follower.HasAbility(reqValue);;
2437 });
2438 if (followerCount < 1)
2439 return false;
2440 break;
2441 }
2443 {
2444 Garrison const* garrison = referencePlayer->GetGarrison();
2445 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2446 return false;
2447 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2448 {
2449 if (follower.PacketInfo.FollowerLevel < reqValue)
2450 return false;
2451 GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
2452 if (!followerBuilding)
2453 return false;
2454 return followerBuilding->BuildingType == int32(secondaryAsset);
2455 });
2456 if (followerCount < 1)
2457 return false;
2458 break;
2459 }
2461 {
2462 Garrison* garrison = referencePlayer->GetGarrison();
2463 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2464 return false;
2465 for (Garrison::Plot const* plot : garrison->GetPlots())
2466 {
2467 if (!plot->BuildingInfo.PacketInfo)
2468 continue;
2469
2470 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2471 if (!building || building->UpgradeLevel < reqValue || building->BuildingType != int32(secondaryAsset))
2472 continue;
2473
2474 return true;
2475 }
2476 return false;
2477 }
2479 {
2480 Garrison const* garrison = referencePlayer->GetGarrison();
2481 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2482 return false;
2483 if (!garrison->HasBlueprint(reqValue))
2484 return false;
2485 break;
2486 }
2488 return false; // OBSOLETE
2490 {
2491 Garrison* garrison = referencePlayer->GetGarrison();
2492 if (!garrison || garrison->GetType() != GarrisonType(reqValue))
2493 return false;
2494 for (Garrison::Plot const* plot : garrison->GetPlots())
2495 if (!plot->BuildingInfo.PacketInfo)
2496 return false;
2497 break;
2498 }
2500 if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() != referencePlayer->GetGUID().GetCounter())
2501 return false;
2502 break;
2504 return false;
2506 {
2507 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(reqValue);
2508 if (!building)
2509 return false;
2510 Garrison* garrison = referencePlayer->GetGarrison();
2511 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2512 return false;
2513 for (Garrison::Plot const* plot : garrison->GetPlots())
2514 {
2515 if (!plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->GarrBuildingID != reqValue)
2516 continue;
2517
2518 return !plot->BuildingInfo.PacketInfo->Active;
2519 }
2520 return false;
2521 }
2523 return false;
2525 {
2526 Garrison* garrison = referencePlayer->GetGarrison();
2527 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2528 return false;
2529 for (Garrison::Plot const* plot : garrison->GetPlots())
2530 {
2531 if (!plot->BuildingInfo.PacketInfo)
2532 continue;
2533
2534 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2535 if (!building || building->UpgradeLevel != secondaryAsset || building->BuildingType != int32(reqValue))
2536 continue;
2537
2538 return true;
2539 }
2540 return false;
2541 }
2543 {
2544 Garrison const* garrison = referencePlayer->GetGarrison();
2545 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2546 return false;
2547 if (miscValue1)
2548 {
2549 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2550 if (!follower)
2551 return false;
2552 if (!follower->HasAbility(reqValue))
2553 return false;
2554 }
2555 else
2556 {
2557 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2558 {
2559 return follower.HasAbility(reqValue);
2560 });
2561 if (followerCount < 1)
2562 return false;
2563 }
2564 break;
2565 }
2567 {
2568 GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(reqValue);
2569 if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
2570 return false;
2571 Garrison const* garrison = referencePlayer->GetGarrison();
2572 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2573 return false;
2574 if (miscValue1)
2575 {
2576 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2577 if (!follower || !follower->HasAbility(reqValue))
2578 return false;
2579 }
2580 else
2581 {
2582 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2583 {
2584 return follower.HasAbility(reqValue);
2585 });
2586 if (followerCount < 1)
2587 return false;
2588 }
2589 break;
2590 }
2592 {
2593 Garrison const* garrison = referencePlayer->GetGarrison();
2594 if (!garrison || garrison->GetType() != GARRISON_TYPE_GARRISON)
2595 return false;
2596 if (miscValue1)
2597 {
2598 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2599 if (!follower || follower->PacketInfo.Quality < reqValue)
2600 return false;
2601 }
2602 else
2603 {
2604 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2605 {
2606 return follower.PacketInfo.Quality >= reqValue;
2607 });
2608 if (followerCount < 1)
2609 return false;
2610 }
2611 break;
2612 }
2614 {
2615 Garrison const* garrison = referencePlayer->GetGarrison();
2616 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2617 return false;
2618 if (miscValue1)
2619 {
2620 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2621 if (!follower || follower->PacketInfo.FollowerLevel != reqValue)
2622 return false;
2623 }
2624 else
2625 {
2626 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2627 {
2628 return follower.PacketInfo.FollowerLevel == reqValue;
2629 });
2630 if (followerCount < 1)
2631 return false;
2632 }
2633 break;
2634 }
2637 return false;
2639 {
2640 if (!miscValue1)
2641 return false;
2642 Garrison* garrison = referencePlayer->GetGarrison();
2643 if (!garrison)
2644 return false;
2645 for (Garrison::Plot const* plot : garrison->GetPlots())
2646 {
2647 if (!plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->GarrBuildingID != miscValue1)
2648 continue;
2649
2650 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2651 if (!building || building->UpgradeLevel != reqValue)
2652 continue;
2653
2654 return true;
2655 }
2656 break;
2657 }
2659 {
2660 Garrison* garrison = referencePlayer->GetGarrison();
2661 if (!garrison)
2662 return false;
2663 Garrison::Plot const* plot = garrison->GetPlot(reqValue);
2664 if (!plot)
2665 return false;
2666 if (!plot->BuildingInfo.CanActivate() || !plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->Active)
2667 return false;
2668 break;
2669 }
2671 {
2672 uint32 count = 0;
2673 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
2674 if (slot.Pet.Species == secondaryAsset)
2675 ++count;
2676 if (count < reqValue)
2677 return false;
2678 break;
2679 }
2681 {
2682 uint32 count = 0;
2683 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
2684 if (BattlePetSpeciesEntry const* species = sBattlePetSpeciesStore.LookupEntry(slot.Pet.Species))
2685 if (species->PetTypeEnum == int32(secondaryAsset))
2686 ++count;
2687 if (count < reqValue)
2688 return false;
2689 break;
2690 }
2693 return false;
2695 {
2696 uint32 count = 0;
2697 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
2698 if (slot.Pet.Health > 0)
2699 ++count;
2700 if (count < reqValue)
2701 return false;
2702 break;
2703 }
2705 return false; // OBSOLETE
2707 {
2708 Garrison const* garrison = referencePlayer->GetGarrison();
2709 if (!garrison)
2710 return false;
2711 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2712 {
2713 return follower.PacketInfo.GarrFollowerID == reqValue;
2714 });
2715 if (followerCount < 1)
2716 return false;
2717 break;
2718 }
2720 {
2721 QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
2722 if (!objective)
2723 return false;
2724 if (referencePlayer->GetQuestObjectiveData(*objective) != int32(secondaryAsset))
2725 return false;
2726 break;
2727 }
2729 {
2730 QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
2731 if (!objective)
2732 return false;
2733 if (referencePlayer->GetQuestObjectiveData(*objective) < int32(secondaryAsset))
2734 return false;
2735 break;
2736 }
2737 case ModifierTreeType::IsPTRRealm: // 160
2739 case ModifierTreeType::IsQARealm: // 162
2740 return false; // always false
2742 return false;
2744 return true; // Only 1 player is required and referencePlayer->GetMap() will ALWAYS have at least the referencePlayer on it
2746 if (referencePlayer->GetMap()->GetPlayersCountExceptGMs() > reqValue)
2747 return false;
2748 break;
2750 {
2751 Garrison* garrison = referencePlayer->GetGarrison();
2752 if (!garrison || garrison->GetType() != GarrisonType(reqValue))
2753 return false;
2754 for (Garrison::Plot const* plot : garrison->GetPlots())
2755 {
2756 if (!plot->BuildingInfo.PacketInfo)
2757 return false;
2758 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2759 if (!building || building->UpgradeLevel != reqValue)
2760 return false;
2761 }
2762 break;
2763 }
2765 return false;
2767 {
2768 if (!miscValue1)
2769 return false;
2770 Garrison const* garrison = referencePlayer->GetGarrison();
2771 if (!garrison)
2772 return false;
2773 uint32 followerCount = garrison->CountFollowers([miscValue1, reqValue](Garrison::Follower const& follower)
2774 {
2775 return follower.PacketInfo.GarrFollowerID == miscValue1 && follower.GetItemLevel() >= reqValue;
2776 });
2777 if (followerCount < 1)
2778 return false;
2779 break;
2780 }
2782 {
2783 Garrison const* garrison = referencePlayer->GetGarrison();
2784 if (!garrison)
2785 return false;
2786 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2787 {
2788 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2789 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.GetItemLevel() >= secondaryAsset;
2790 });
2791 if (followerCount < reqValue)
2792 return false;
2793 break;
2794 }
2796 {
2797 Garrison const* garrison = referencePlayer->GetGarrison();
2798 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel != reqValue)
2799 return false;
2800 break;
2801 }
2803 if (referencePlayer->GetMap()->GetPlayers().getSize() != reqValue)
2804 return false;
2805 break;
2806 case ModifierTreeType::CurrencyId: // 172
2807 if (miscValue1 != reqValue)
2808 return false;
2809 break;
2811 if (referencePlayer->GetTarget().GetHigh() != HighGuid::Corpse)
2812 return false;
2813 break;
2815 {
2816 Quest const* quest = sObjectMgr->GetQuestTemplate(reqValue);
2817 if (!quest)
2818 return false;
2819 if (!referencePlayer->CanTakeQuest(quest, false))
2820 return false;
2821 break;
2822 }
2824 {
2825 Garrison const* garrison = referencePlayer->GetGarrison();
2826 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2827 return false;
2828 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2829 {
2830 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2831 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel == secondaryAsset;
2832 });
2833 if (followerCount < reqValue)
2834 return false;
2835 break;
2836 }
2838 {
2839 Garrison const* garrison = referencePlayer->GetGarrison();
2840 if (!garrison)
2841 return false;
2842 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2843 {
2844 return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentBuildingID == secondaryAsset;
2845 });
2846 if (followerCount < 1)
2847 return false;
2848 break;
2849 }
2851 return false;
2853 {
2854 Garrison* garrison = referencePlayer->GetGarrison();
2855 if (!garrison || garrison->GetType() != GarrisonType(reqValue))
2856 return false;
2857 uint32 plotCount = 0;
2858 for (Garrison::Plot const* plot : garrison->GetPlots())
2859 {
2860 GarrPlotInstanceEntry const* garrPlotInstance = sGarrPlotInstanceStore.LookupEntry(plot->PacketInfo.GarrPlotInstanceID);
2861 if (!garrPlotInstance || garrPlotInstance->GarrPlotID != secondaryAsset)
2862 continue;
2863 ++plotCount;
2864 }
2865 if (plotCount < reqValue)
2866 return false;
2867 break;
2868 }
2869 case ModifierTreeType::CurrencySource: // 179 NYI
2870 return false;
2872 if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() == referencePlayer->GetGUID().GetCounter())
2873 return false;
2874 break;
2876 {
2877 Garrison const* garrison = referencePlayer->GetGarrison();
2878 if (!garrison)
2879 return false;
2880 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2881 {
2882 return follower.PacketInfo.GarrFollowerID == reqValue && !(follower.PacketInfo.FollowerStatus & FOLLOWER_STATUS_INACTIVE);
2883 });
2884 if (followerCount < 1)
2885 return false;
2886 break;
2887 }
2889 return false;
2891 {
2892 for (auto&& p : referencePlayer->GetSession()->GetCollectionMgr()->GetAccountMounts())
2893 {
2894 MountEntry const* mount = sDB2Manager.GetMount(p.first);
2895 if (!mount)
2896 continue;
2897
2898 if (mount->ID == reqValue)
2899 return true;
2900 }
2901 return false;
2902 }
2904 {
2905 Garrison const* garrison = referencePlayer->GetGarrison();
2906 if (!garrison)
2907 return false;
2908 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2909 {
2910 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.LookupEntry(follower.PacketInfo.GarrFollowerID);
2911 if (!garrFollower)
2912 return false;
2913 return follower.GetItemLevel() >= secondaryAsset && garrFollower->GarrFollowerTypeID == tertiaryAsset;
2914 });
2915 if (followerCount < reqValue)
2916 return false;
2917 break;
2918 }
2920 {
2921 Garrison const* garrison = referencePlayer->GetGarrison();
2922 if (!garrison)
2923 return false;
2924 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2925 {
2926 return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentMissionID != 0;
2927 });
2928 if (followerCount < 1)
2929 return false;
2930 break;
2931 }
2933 return false;
2935 {
2936 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.LookupEntry(miscValue1);
2937 if (!garrFollower || garrFollower->GarrFollowerTypeID != int32(reqValue))
2938 return false;
2939 break;
2940 }
2943 return false;
2945 if (!referencePlayer->HasPlayerFlagEx(PLAYER_FLAGS_EX_MERCENARY_MODE))
2946 return false;
2947 break;
2950 return false;
2952 if (referencePlayer->GetHonorLevel() < reqValue)
2953 return false;
2954 break;
2956 return false; // OBSOLOTE
2959 return false;
2962 return false;
2963 break;
2964 case ModifierTreeType::TeamPoints: // 198 NYI
2965 return false;
2967 if (!referencePlayer->GetSession()->GetCollectionMgr()->HasToy(reqValue))
2968 return false;
2969 break;
2971 {
2972 std::pair<bool, bool> hasAppearance = referencePlayer->GetSession()->GetCollectionMgr()->HasItemAppearance(reqValue);
2973 if (!hasAppearance.first || hasAppearance.second)
2974 return false;
2975 break;
2976 }
2979 return false;
2981 {
2982 int32 restrictionIndex = referencePlayer->m_activePlayerData->CharacterRestrictions.FindIndexIf([reqValue](UF::CharacterRestriction const& restriction)
2983 {
2984 return restriction.Type == reqValue;
2985 });
2986 if (restrictionIndex < 0)
2987 return false;
2988 break;
2989 }
2991 return false;
2993 if (Hours(reqValue) >= Seconds(referencePlayer->GetTotalPlayedTime()))
2994 return false;
2995 break;
2997 {
2998 Quest const* quest = sObjectMgr->GetQuestTemplate(miscValue1);
2999 if (!quest || quest->GetQuestInfoID() != reqValue)
3000 return false;
3001 break;
3002 }
3004 return false;
3006 {
3007 if (Aura const* artifactAura = referencePlayer->GetAura(ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE))
3008 if (Item* artifact = referencePlayer->GetItemByGuid(artifactAura->GetCastItemGUID()))
3009 if (ArtifactAppearanceEntry const* artifactAppearance = sArtifactAppearanceStore.LookupEntry(artifact->GetModifier(ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID)))
3010 if (artifactAppearance->ArtifactAppearanceSetID == reqValue)
3011 break;
3012 return false;
3013 }
3015 if (referencePlayer->GetCurrencyQuantity(reqValue) != secondaryAsset)
3016 return false;
3017 break;
3019 return false;
3021 {
3022 Scenario const* scenario = referencePlayer->GetScenario();
3023 if (!scenario)
3024 return false;
3025 if (scenario->GetEntry()->Type != reqValue)
3026 return false;
3027 break;
3028 }
3030 if (referencePlayer->GetSession()->GetAccountExpansion() < reqValue)
3031 return false;
3032 break;
3036 return false;
3038 {
3039 uint32 memberCount = 0;
3040 if (Group const* group = referencePlayer->GetGroup())
3041 for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
3042 if (itr->GetSource() != referencePlayer && *referencePlayer->m_playerData->VirtualPlayerRealm == *itr->GetSource()->m_playerData->VirtualPlayerRealm)
3043 ++memberCount;
3044 if (memberCount < reqValue)
3045 return false;
3046 break;
3047 }
3049 {
3050 Item const* artifact = referencePlayer->GetItemByEntry(secondaryAsset, ItemSearchLocation::Everywhere);
3051 if (!artifact)
3052 return false;
3053 if (artifact->GetTotalUnlockedArtifactPowers() < reqValue)
3054 return false;
3055 break;
3056 }
3058 if (referencePlayer->GetReputationMgr().GetParagonLevel(miscValue1) < int32(reqValue))
3059 return false;
3060 return false;
3062 return false;
3064 {
3065 BattlemasterListEntry const* bg = sBattlemasterListStore.LookupEntry(referencePlayer->GetBattlegroundTypeId());
3066 if (!bg || !(bg->GetFlags().HasFlag(BattlemasterListFlags::IsBrawl)))
3067 return false;
3068 break;
3069 }
3071 {
3072 FactionEntry const* faction = sFactionStore.LookupEntry(secondaryAsset);
3073 if (!faction)
3074 return false;
3075 if (referencePlayer->GetReputationMgr().GetParagonLevel(faction->ParagonFactionID) < int32(reqValue))
3076 return false;
3077 break;
3078 }
3080 {
3081 std::vector<int32> bonusListIDs = ItemBonusMgr::GetAllBonusListsForTree(reqValue);
3082 if (bonusListIDs.empty())
3083 return false;
3084
3085 bool bagScanReachedEnd = referencePlayer->ForEachItem(ItemSearchLocation::Everywhere, [&bonusListIDs](Item const* item)
3086 {
3087 bool hasBonus = std::any_of(item->GetBonusListIDs().begin(), item->GetBonusListIDs().end(), [&bonusListIDs](int32 bonusListID)
3088 {
3089 return std::find(bonusListIDs.begin(), bonusListIDs.end(), bonusListID) != bonusListIDs.end();
3090 });
3092 });
3093 if (bagScanReachedEnd)
3094 return false;
3095 break;
3096 }
3098 if (referencePlayer->GetFreeInventorySlotCount(ItemSearchLocation::Inventory) < reqValue)
3099 return false;
3100 break;
3102 return false;
3104 {
3105 Aura const* artifactAura = referencePlayer->GetAura(ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE);
3106 if (!artifactAura)
3107 return false;
3108 Item const* artifact = referencePlayer->GetItemByGuid(artifactAura->GetCastItemGUID());
3109 if (!artifact)
3110 return false;
3111 UF::ArtifactPower const* artifactPower = artifact->GetArtifactPower(secondaryAsset);
3112 if (!artifactPower)
3113 return false;
3114 if (artifactPower->PurchasedRank < reqValue)
3115 return false;
3116 break;
3117 }
3119 if (referencePlayer->HasLevelBoosted())
3120 return false;
3121 break;
3123 if (referencePlayer->HasRaceChanged())
3124 return false;
3125 break;
3127 if (referencePlayer->HasBeenGrantedLevelsFromRaF())
3128 return false;
3129 break;
3131 return false;
3133 if (!referencePlayer->GetSession()->CanAccessAlliedRaces())
3134 return false;
3135 break;
3137 {
3138 if (Group const* group = referencePlayer->GetGroup())
3139 {
3140 uint32 membersWithAchievement = 0;
3141 for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
3142 if (itr->GetSource()->HasAchieved(secondaryAsset))
3143 ++membersWithAchievement;
3144
3145 if (membersWithAchievement > reqValue)
3146 return false;
3147 }
3148 // true if no group
3149 break;
3150 }
3152 {
3153 UF::VisibleItem const& visibleItem = referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_MAINHAND];
3155 if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(visibleItem.ItemID))
3156 {
3157 if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
3158 {
3159 itemSubclass = itemTemplate->GetSubClass();
3160
3161 if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sDB2Manager.GetItemModifiedAppearance(visibleItem.ItemID, visibleItem.ItemAppearanceModID))
3162 if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(itemModifiedAppearance->ID))
3163 if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
3164 itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
3165 }
3166 }
3167 if (itemSubclass != reqValue)
3168 return false;
3169 break;
3170 }
3172 {
3173 UF::VisibleItem const& visibleItem = referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_OFFHAND];
3175 if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(visibleItem.ItemID))
3176 {
3177 if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
3178 {
3179 itemSubclass = itemTemplate->GetSubClass();
3180
3181 if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sDB2Manager.GetItemModifiedAppearance(visibleItem.ItemID, visibleItem.ItemAppearanceModID))
3182 if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(itemModifiedAppearance->ID))
3183 if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
3184 itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
3185 }
3186 }
3187 if (itemSubclass != reqValue)
3188 return false;
3189 break;
3190 }
3192 {
3193 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(reqValue);
3194 if (!pvpTier)
3195 return false;
3196 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(pvpTier->BracketID);
3197 if (!pvpInfo)
3198 return false;
3199 if (pvpTier->ID != pvpInfo->PvpTierID)
3200 return false;
3201 break;
3202 }
3204 {
3205 Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
3206 if (!heartOfAzeroth || heartOfAzeroth->ToAzeriteItem()->GetLevel() < reqValue)
3207 return false;
3208 break;
3209 }
3211 {
3212 bool isOnQuest = false;
3213 if (std::vector<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue))
3214 {
3215 isOnQuest = std::any_of(questLineQuests->begin(), questLineQuests->end(), [referencePlayer](QuestLineXQuestEntry const* questLineQuest)
3216 {
3217 return referencePlayer->FindQuestSlot(questLineQuest->QuestID) < MAX_QUEST_LOG_SIZE;
3218 });
3219 }
3220 if (!isOnQuest)
3221 return false;
3222 break;
3223 }
3225 return false; // OBSOLETE (db2 removed)
3227 {
3228 Group const* group = referencePlayer->GetGroup();
3229 if (!group || !group->isRaidGroup())
3230 return false;
3231 break;
3232 }
3234 {
3235 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(secondaryAsset);
3236 if (!pvpInfo)
3237 return false;
3238 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(pvpInfo->PvpTierID);
3239 if (!pvpTier)
3240 return false;
3241 if (pvpTier->Rank < int32(reqValue))
3242 return false;
3243 break;
3244 }
3246 {
3247 std::vector<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
3248 if (!questLineQuests)
3249 return false;
3250 bool canTakeQuest = std::any_of(questLineQuests->begin(), questLineQuests->end(), [referencePlayer](QuestLineXQuestEntry const* questLineQuest)
3251 {
3252 if (Quest const* quest = sObjectMgr->GetQuestTemplate(questLineQuest->QuestID))
3253 return referencePlayer->CanTakeQuest(quest, false);
3254 return false;
3255 });
3256 if (!canTakeQuest)
3257 return false;
3258 break;
3259 }
3261 {
3262 std::vector<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
3263 if (!questLineQuests)
3264 return false;
3265 for (QuestLineXQuestEntry const* questLineQuest : *questLineQuests)
3266 if (!referencePlayer->GetQuestRewardStatus(questLineQuest->QuestID))
3267 return false;
3268 break;
3269 }
3271 {
3272 std::vector<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
3273 if (!questLineQuests)
3274 return false;
3275 uint32 completedQuests = 0;
3276 for (QuestLineXQuestEntry const* questLineQuest : *questLineQuests)
3277 if (referencePlayer->GetQuestRewardStatus(questLineQuest->QuestID))
3278 ++completedQuests;
3279 if (completedQuests < reqValue)
3280 return false;
3281 break;
3282 }
3284 {
3285 std::vector<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
3286 if (!questLineQuests || questLineQuests->empty())
3287 return false;
3288 std::size_t completedQuests = 0;
3289 for (QuestLineXQuestEntry const* questLineQuest : *questLineQuests)
3290 if (referencePlayer->GetQuestRewardStatus(questLineQuest->QuestID))
3291 ++completedQuests;
3292 if (GetPctOf(completedQuests, questLineQuests->size()) < reqValue)
3293 return false;
3294 break;
3295 }
3297 if (!referencePlayer->HasPlayerLocalFlag(PLAYER_LOCAL_FLAG_WAR_MODE))
3298 return false;
3299 break;
3301 if (!referencePlayer->HasPlayerFlag(PLAYER_FLAGS_WAR_MODE_ACTIVE))
3302 return false;
3303 break;
3305 if (!referencePlayer->CanEnableWarModeInArea())
3306 return false;
3307 break;
3313 return false;
3315 {
3316 CreatureDisplayInfoEntry const* creatureDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(referencePlayer->GetDisplayId());
3317 if (!creatureDisplayInfo)
3318 return false;
3319 CreatureDisplayInfoExtraEntry const* creatureDisplayInfoExtra = sCreatureDisplayInfoExtraStore.LookupEntry(creatureDisplayInfo->ExtendedDisplayInfoID);
3320 if (!creatureDisplayInfoExtra)
3321 return false;
3322 if (uint32(creatureDisplayInfoExtra->DisplayRaceID) != reqValue)
3323 return false;
3324 break;
3325 }
3327 {
3328 if (!ref || !ref->IsUnit())
3329 return false;
3330 CreatureDisplayInfoEntry const* creatureDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(ref->ToUnit()->GetDisplayId());
3331 if (!creatureDisplayInfo)
3332 return false;
3333 CreatureDisplayInfoExtraEntry const* creatureDisplayInfoExtra = sCreatureDisplayInfoExtraStore.LookupEntry(creatureDisplayInfo->ExtendedDisplayInfoID);
3334 if (!creatureDisplayInfoExtra)
3335 return false;
3336 if (uint32(creatureDisplayInfoExtra->DisplayRaceID) != reqValue)
3337 return false;
3338 break;
3339 }
3341 {
3342 FriendshipRepReactionEntry const* friendshipRepReaction = sFriendshipRepReactionStore.LookupEntry(reqValue);
3343 if (!friendshipRepReaction)
3344 return false;
3345 FriendshipReputationEntry const* friendshipReputation = sFriendshipReputationStore.LookupEntry(friendshipRepReaction->FriendshipRepID);
3346 if (!friendshipReputation)
3347 return false;
3348 DB2Manager::FriendshipRepReactionSet const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(reqValue);
3349 if (!friendshipReactions)
3350 return false;
3351 uint32 rank = referencePlayer->GetReputationRank(friendshipReputation->FactionID);
3352 if (rank >= friendshipReactions->size())
3353 return false;
3354 auto itr = friendshipReactions->begin();
3355 std::advance(itr, rank);
3356 if ((*itr)->ID != reqValue)
3357 return false;
3358 break;
3359 }
3361 if (referencePlayer->GetAuraCount(secondaryAsset) != reqValue)
3362 return false;
3363 break;
3365 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetAuraCount(secondaryAsset) != reqValue)
3366 return false;
3367 break;
3369 if (referencePlayer->GetAuraCount(secondaryAsset) < reqValue)
3370 return false;
3371 break;
3373 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetAuraCount(secondaryAsset) < reqValue)
3374 return false;
3375 break;
3377 {
3378 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3379 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3380 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3381 if (essence.AzeriteEssenceID == reqValue && essence.Rank < secondaryAsset)
3382 return true;
3383 return false;
3384 }
3386 {
3387 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3388 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3389 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3390 if (essence.AzeriteEssenceID == reqValue && essence.Rank == secondaryAsset)
3391 return true;
3392 return false;
3393 }
3395 {
3396 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3397 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3398 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3399 if (essence.AzeriteEssenceID == reqValue && essence.Rank > secondaryAsset)
3400 return true;
3401 return false;
3402 }
3404 if (!referencePlayer->GetAuraEffect(reqValue, secondaryAsset))
3405 return false;
3406 break;
3408 {
3409 ChrSpecializationEntry const* spec = referencePlayer->GetPrimarySpecializationEntry();
3410 if (!spec || spec->Role != int32(reqValue))
3411 return false;
3412 break;
3413 }
3415 if (!referencePlayer->IsMaxLevel())
3416 return false;
3417 break;
3419 {
3420 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(miscValue2);
3421 if (!itemModifiedAppearance)
3422 return false;
3423 if (itemModifiedAppearance->TransmogSourceTypeEnum != int32(reqValue))
3424 return false;
3425 break;
3426 }
3428 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3429 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3430 if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
3431 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3432 if (essence.AzeriteEssenceID == selectedEssences->AzeriteEssenceID[reqValue] && essence.Rank < secondaryAsset)
3433 return true;
3434 return false;
3436 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3437 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3438 if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
3439 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3440 if (essence.AzeriteEssenceID == selectedEssences->AzeriteEssenceID[reqValue] && essence.Rank > secondaryAsset)
3441 return true;
3442 return false;
3444 {
3445 uint8 level = referencePlayer->GetLevel();
3446 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0))
3447 {
3448 if (secondaryAsset)
3449 return level >= levels->MinLevelWithDelta && level <= levels->MaxLevelWithDelta;
3450 return level >= levels->MinLevel && level <= levels->MaxLevel;
3451 }
3452 return false;
3453 }
3455 {
3456 if (!ref || !ref->IsUnit())
3457 return false;
3458 uint8 level = ref->ToUnit()->GetLevel();
3459 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0))
3460 {
3461 if (secondaryAsset)
3462 return level >= levels->MinLevelWithDelta && level <= levels->MaxLevelWithDelta;
3463 return level >= levels->MinLevel && level <= levels->MaxLevel;
3464 }
3465 return false;
3466 }
3468 return false;
3470 {
3471 QuestStatus status = referencePlayer->GetQuestStatus(reqValue);
3472 if (status == QUEST_STATUS_NONE || status == QUEST_STATUS_FAILED)
3473 return false;
3474 break;
3475 }
3477 {
3478 uint8 level = referencePlayer->GetLevel();
3479 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0))
3480 return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel;
3481 return false;
3482 }
3484 {
3485 if (!ref || !ref->IsUnit())
3486 return false;
3487 uint8 level = ref->ToUnit()->GetLevel();
3488 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0))
3489 return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel;
3490 return false;
3491 }
3494 return false;
3496 if (referencePlayer->m_activePlayerData->JailersTowerLevelMax < int32(reqValue))
3497 return false;
3498 break;
3500 {
3501 Group const* group = referencePlayer->GetGroup();
3502 if (!group)
3503 return false;
3504 for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
3505 if (itr->GetSource()->GetSession()->GetRecruiterId() == referencePlayer->GetSession()->GetAccountId())
3506 return true;
3507 return false;
3508 }
3510 {
3511 Group const* group = referencePlayer->GetGroup();
3512 if (!group)
3513 return false;
3514 for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
3515 if (itr->GetSource()->GetSession()->GetAccountId() == referencePlayer->GetSession()->GetRecruiterId())
3516 return true;
3517 return false;
3518 }
3520 if (referencePlayer->GetPrimarySpecialization() != ChrSpecialization(reqValue))
3521 return false;
3522 break;
3524 {
3525 MapEntry const* map = referencePlayer->GetMap()->GetEntry();
3526 if (map->ID != reqValue && map->CosmeticParentMapID != int32(reqValue))
3527 return false;
3528 break;
3529 }
3531 if (referencePlayer->GetSession()->GetAccountExpansion() < EXPANSION_SHADOWLANDS)
3532 return false;
3533 break;
3537 case ModifierTreeType::HonorGainSource: // 285 NYI
3540 return false;
3542 if (referencePlayer->m_playerData->CovenantID != int32(reqValue))
3543 return false;
3544 break;
3546 {
3547 time_t eventTimestamp = GameTime::GetGameTime();
3548 switch (reqValue)
3549 {
3550 case 111: // Battle for Azeroth Season 4 Start
3551 eventTimestamp = time_t(1579618800); // January 21, 2020 8:00
3552 break;
3553 case 120: // Patch 9.0.1
3554 eventTimestamp = time_t(1602601200); // October 13, 2020 8:00
3555 break;
3556 case 121: // Shadowlands Season 1 Start
3557 eventTimestamp = time_t(1607439600); // December 8, 2020 8:00
3558 break;
3559 case 123: // Shadowlands Season 1 End
3560 // timestamp = unknown
3561 break;
3562 case 149: // Shadowlands Season 2 End
3563 // timestamp = unknown
3564 break;
3565 case 349: // Dragonflight Season 3 Start (pre-season)
3566 eventTimestamp = time_t(1699340400); // November 7, 2023 8:00
3567 break;
3568 case 350: // Dragonflight Season 3 Start
3569 eventTimestamp = time_t(1699945200); // November 14, 2023 8:00
3570 break;
3571 case 352: // Dragonflight Season 3 End
3572 // eventTimestamp = time_t(); unknown
3573 break;
3574 default:
3575 break;
3576 }
3577 if (GameTime::GetGameTime() < eventTimestamp)
3578 return false;
3579 break;
3580 }
3582 return false;
3584 if (referencePlayer->m_playerData->SoulbindID != int32(reqValue))
3585 return false;
3586 break;
3588 return false;
3594 return false;
3596 {
3597 std::vector<uint32> areas = sDB2Manager.GetAreasForGroup(reqValue);
3598 for (uint32 areaInGroup : areas)
3599 if (DB2Manager::IsInArea(referencePlayer->GetAreaId(), areaInGroup))
3600 return true;
3601 return false;
3602 }
3604 {
3605 if (!ref)
3606 return false;
3607 std::vector<uint32> areas = sDB2Manager.GetAreasForGroup(reqValue);
3608 for (uint32 areaInGroup : areas)
3609 if (DB2Manager::IsInArea(ref->GetAreaId(), areaInGroup))
3610 return true;
3611 return false;
3612 }
3614 if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID != int32(reqValue))
3615 return false;
3616 break;
3618 if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID == 0)
3619 return false;
3620 break;
3622 if (!sDB2Manager.GetAzeriteEmpoweredItem(miscValue1))
3623 return false;
3624 break;
3626 {
3627 uint32 block = reqValue / 32;
3628 if (block >= referencePlayer->m_activePlayerData->RuneforgePowers.size())
3629 return false;
3630
3631 uint32 bit = reqValue % 32;
3632 return referencePlayer->m_activePlayerData->RuneforgePowers[block] & (1 << bit);
3633 }
3635 if (!(referencePlayer->m_playerData->CtrOptions->ContentTuningConditionMask & 1))
3636 return false;
3637 break;
3639 if (!referencePlayer->GetSession()->GetRecruiterId())
3640 return false;
3641 break;
3643 {
3644 if (Group const* group = referencePlayer->GetGroup())
3645 {
3646 for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
3647 if (!itr->GetSource()->HasAchieved(reqValue))
3648 return false;
3649 }
3650 else if (!referencePlayer->HasAchieved(reqValue))
3651 return false;
3652 break;
3653 }
3655 return false;
3657 {
3658 ShapeshiftFormModelData const* formModelData = sDB2Manager.GetShapeshiftFormModelData(referencePlayer->GetRace(), referencePlayer->GetNativeGender(), secondaryAsset);
3659 if (!formModelData)
3660 return false;
3661 uint32 formChoice = referencePlayer->GetCustomizationChoice(formModelData->OptionID);
3662 auto choiceItr = std::find_if(formModelData->Choices->begin(), formModelData->Choices->end(), [formChoice](ChrCustomizationChoiceEntry const* choice)
3663 {
3664 return choice->ID == formChoice;
3665 });
3666 if (choiceItr == formModelData->Choices->end())
3667 return false;
3668 if (int32(reqValue) != formModelData->Displays[std::distance(formModelData->Choices->begin(), choiceItr)]->DisplayID)
3669 return false;
3670 break;
3671 }
3673 return false;
3675 return false;
3677 if (!referencePlayer->IsFlying())
3678 return false;
3679 break;
3681 {
3682 Scenario const* scenario = referencePlayer->GetScenario();
3683 if (!scenario)
3684 return false;
3685 if (scenario->GetStep() != scenario->GetLastStep())
3686 return false;
3687 break;
3688 }
3690 if (!*referencePlayer->m_activePlayerData->WeeklyRewardsPeriodSinceOrigin)
3691 return false;
3692 break;
3694 if (!ref || !ref->IsPlayer())
3695 return false;
3696 if (ref->ToPlayer()->m_playerData->CovenantID != int32(reqValue))
3697 return false;
3698 break;
3701 return false;
3708 return false;
3710 {
3711 int32 customizationChoiceIndex = referencePlayer->m_playerData->Customizations.FindIndexIf([reqValue](UF::ChrCustomizationChoice const& choice)
3712 {
3713 return choice.ChrCustomizationChoiceID == reqValue;
3714 });
3715 if (customizationChoiceIndex < 0)
3716 return false;
3717 break;
3718 }
3720 {
3721 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(reqValue);
3722 if (!pvpTier)
3723 return false;
3724 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(pvpTier->BracketID);
3725 if (!pvpInfo)
3726 return false;
3727 if (pvpTier->ID != pvpInfo->WeeklyBestWinPvpTierID)
3728 return false;
3729 break;
3730 }
3732 {
3733 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(secondaryAsset);
3734 if (!pvpInfo)
3735 return false;
3736 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(pvpInfo->WeeklyBestWinPvpTierID);
3737 if (!pvpTier)
3738 return false;
3739 if (pvpTier->Rank < int32(reqValue))
3740 return false;
3741 break;
3742 }
3744 return false;
3746 {
3747 bool bagScanReachedEnd = referencePlayer->ForEachItem(ItemSearchLocation::Inventory, [reqValue, secondaryAsset](Item const* item)
3748 {
3749 if (item->GetEntry() != reqValue)
3751
3752 if (item->GetModifier(ITEM_MODIFIER_CHALLENGE_KEYSTONE_LEVEL) < secondaryAsset)
3754
3756 });
3757 if (bagScanReachedEnd)
3758 return false;
3759 break;
3760 }
3762 {
3763 uint32 count = 0;
3764 referencePlayer->HasAura([secondaryAsset, &count](Aura const* aura)
3765 {
3766 if (aura->GetSpellInfo()->HasLabel(secondaryAsset))
3767 count += aura->GetStackAmount();
3768 return false;
3769 });
3770 if (count < reqValue)
3771 return false;
3772 break;
3773 }
3775 {
3776 uint32 count = 0;
3777 referencePlayer->HasAura([secondaryAsset, &count](Aura const* aura)
3778 {
3779 if (aura->GetSpellInfo()->HasLabel(secondaryAsset))
3780 count += aura->GetStackAmount();
3781 return false;
3782 });
3783 if (count != reqValue)
3784 return false;
3785 break;
3786 }
3788 {
3789 uint32 count = 0;
3790 referencePlayer->HasAura([secondaryAsset, &count](Aura const* aura)
3791 {
3792 if (aura->GetSpellInfo()->HasLabel(secondaryAsset))
3793 count += aura->GetStackAmount();
3794 return false;
3795 });
3796 if (count > reqValue)
3797 return false;
3798 break;
3799 }
3801 {
3802 Group const* group = referencePlayer->GetGroup();
3803 if (!(group->GetGroupFlags() & GROUP_FLAG_CROSS_FACTION))
3804 return false;
3805 break;
3806 }
3808 {
3809 auto hasTraitNodeEntry = [referencePlayer, reqValue]()
3810 {
3811 for (UF::TraitConfig const& traitConfig : referencePlayer->m_activePlayerData->TraitConfigs)
3812 {
3813 if (TraitConfigType(*traitConfig.Type) == TraitConfigType::Combat)
3814 {
3815 if (int32(*referencePlayer->m_activePlayerData->ActiveCombatTraitConfigID) != traitConfig.ID
3817 continue;
3818 }
3819
3820 for (UF::TraitEntry const& traitEntry : traitConfig.Entries)
3821 if (traitEntry.TraitNodeEntryID == int32(reqValue))
3822 return true;
3823 }
3824 return false;
3825 }();
3826 if (!hasTraitNodeEntry)
3827 return false;
3828 break;
3829 }
3831 {
3832 auto traitNodeEntryRank = [referencePlayer, secondaryAsset]() -> Optional<uint16>
3833 {
3834 for (UF::TraitConfig const& traitConfig : referencePlayer->m_activePlayerData->TraitConfigs)
3835 {
3836 if (TraitConfigType(*traitConfig.Type) == TraitConfigType::Combat)
3837 {
3838 if (int32(*referencePlayer->m_activePlayerData->ActiveCombatTraitConfigID) != traitConfig.ID
3840 continue;
3841 }
3842
3843 for (UF::TraitEntry const& traitEntry : traitConfig.Entries)
3844 if (traitEntry.TraitNodeEntryID == int32(secondaryAsset))
3845 return traitEntry.Rank;
3846 }
3847 return {};
3848 }();
3849 if (!traitNodeEntryRank || traitNodeEntryRank < int32(reqValue))
3850 return false;
3851 break;
3852 }
3854 if (GameTime::GetGameTime() - referencePlayer->m_playerData->LogoutTime < int64(reqValue) * DAY)
3855 return false;
3856 break;
3858 if (!referencePlayer->m_activePlayerData->HasPerksProgramPendingReward)
3859 return false;
3860 break;
3862 {
3863 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(reqValue);
3864 if (!itemTemplate || !referencePlayer->CanUseItem(itemTemplate))
3865 return false;
3866 break;
3867 }
3869 if (referencePlayer->m_playerData->CurrentBattlePetSpeciesID != int32(reqValue))
3870 return false;
3871 break;
3873 if (referencePlayer->m_unitData->WildBattlePetLevel != BattlePets::MAX_BATTLE_PET_LEVEL)
3874 return false;
3875 break;
3877 {
3878 auto traitNodeEntryRankCount = [referencePlayer, secondaryAsset]()
3879 {
3880 uint32 ranks = 0;
3881 for (UF::TraitConfig const& traitConfig : referencePlayer->m_activePlayerData->TraitConfigs)
3882 {
3884 continue;
3885
3886 if (*traitConfig.SkillLineID != int32(secondaryAsset))
3887 continue;
3888
3889 for (UF::TraitEntry const& traitEntry : traitConfig.Entries)
3890 if (sTraitNodeEntryStore.AssertEntry(traitEntry.TraitNodeEntryID)->GetNodeEntryType() == TraitNodeEntryType::ProfPath)
3891 ranks += traitEntry.Rank + traitEntry.GrantedRanks;
3892 }
3893 return ranks;
3894 }();
3895 if (traitNodeEntryRankCount < reqValue)
3896 return false;
3897 break;
3898 }
3900 {
3901 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(reqValue);
3902
3903 bool bagScanReachedEnd = referencePlayer->ForEachItem(ItemSearchLocation::Inventory, [referencePlayer, itemModifiedAppearance](Item const* item)
3904 {
3905 if (item->GetVisibleAppearanceModId(referencePlayer) == itemModifiedAppearance->ID)
3907
3908 if (int32(item->GetEntry()) == itemModifiedAppearance->ItemID)
3910
3912 });
3913 if (bagScanReachedEnd)
3914 return false;
3915 break;
3916 }
3918 if (!referencePlayer->IsLockedToDungeonEncounter(reqValue, Difficulty(secondaryAsset)))
3919 return false;
3920 break;
3922 {
3923 QuestStatus status = referencePlayer->GetQuestStatus(reqValue);
3924 if (status == QUEST_STATUS_NONE || status == QUEST_STATUS_FAILED)
3925 return false;
3926 if (referencePlayer->IsQuestRewarded(secondaryAsset))
3927 return false;
3928 break;
3929 }
3931 {
3932 Scenario const* scenario = referencePlayer->GetScenario();
3933 if (!scenario)
3934 return false;
3935 if (scenario->GetStep()->ID != reqValue)
3936 return false;
3937 break;
3938 }
3940 if (referencePlayer->GetPositionZ() >= reqValue)
3941 return false;
3942 break;
3944 {
3945 MapEntry const* mapEntry = referencePlayer->GetMap()->GetEntry();
3946 if (mapEntry->ExpansionID != reqValue)
3947 return false;
3948 break;
3949 }
3950 default:
3951 return false;
3952 }
3953 return true;
3954}
3955
3957
3959{
3960 return GetCriteriaTypeString(CriteriaType(type));
3961}
3962
3964{
3965 switch (type)
3966 {
3968 return "KillCreature";
3970 return "WinBattleground";
3972 return "CompleteResearchProject";
3974 return "CompleteAnyResearchProject";
3976 return "FindResearchObject";
3978 return "ReachLevel";
3980 return "ExhaustAnyResearchSite";
3982 return "SkillRaised";
3984 return "EarnAchievement";
3986 return "CompleteQuestsCount";
3988 return "CompleteAnyDailyQuestPerDay";
3990 return "CompleteQuestsInZone";
3992 return "CurrencyGained";
3994 return "DamageDealt";
3996 return "CompleteDailyQuest";
3998 return "ParticipateInBattleground";
4000 return "DieOnMap";
4002 return "DieAnywhere";
4004 return "DieInInstance";
4006 return "RunInstance";
4008 return "KilledByCreature";
4010 return "CompleteInternalCriteria";
4012 return "CompleteAnyChallengeMode";
4014 return "KilledByPlayer";
4016 return "MaxDistFallenWithoutDying";
4018 return "EarnChallengeModeMedal";
4020 return "DieFromEnviromentalDamage";
4022 return "CompleteQuest";
4024 return "BeSpellTarget";
4026 return "CastSpell";
4028 return "TrackedWorldStateUIModified";
4030 return "PVPKillInArea";
4032 return "WinArena";
4034 return "ParticipateInArena";
4036 return "LearnOrKnowSpell";
4038 return "EarnHonorableKill";
4040 return "AcquireItem";
4042 return "WinAnyRankedArena";
4044 return "EarnTeamArenaRating";
4046 return "EarnPersonalArenaRating";
4048 return "AchieveSkillStep";
4050 return "UseItem";
4052 return "LootItem";
4054 return "RevealWorldMapOverlay";
4056 return "EarnTitle";
4058 return "BankSlotsPurchased";
4060 return "ReputationGained";
4062 return "TotalExaltedFactions";
4064 return "GotHaircut";
4066 return "EquipItemInSlot";
4068 return "RollNeed";
4070 return "RollGreed";
4072 return "DeliverKillingBlowToClass";
4074 return "DeliverKillingBlowToRace";
4076 return "DoEmote";
4078 return "HealingDone";
4080 return "DeliveredKillingBlow";
4082 return "EquipItem";
4084 return "CompleteQuestsInSort";
4086 return "MoneyEarnedFromSales";
4088 return "MoneySpentOnRespecs";
4090 return "TotalRespecs";
4092 return "MoneyEarnedFromQuesting";
4094 return "MoneySpentOnTaxis";
4096 return "KilledAllUnitsInSpawnRegion";
4098 return "MoneySpentAtBarberShop";
4100 return "MoneySpentOnPostage";
4102 return "MoneyLootedFromCreatures";
4104 return "UseGameobject";
4106 return "GainAura";
4108 return "KillPlayer";
4110 return "CompleteChallengeMode";
4112 return "CatchFishInFishingHole";
4114 return "PlayerTriggerGameEvent";
4116 return "Login";
4118 return "LearnSpellFromSkillLine";
4120 return "WinDuel";
4122 return "LoseDuel";
4124 return "KillAnyCreature";
4126 return "CreatedItemsByCastingSpellWithLimit";
4128 return "MoneyEarnedFromAuctions";
4130 return "BattlePetAchievementPointsEarned";
4132 return "ItemsPostedAtAuction";
4134 return "HighestAuctionBid";
4136 return "AuctionsWon";
4138 return "HighestAuctionSale";
4140 return "MostMoneyOwned";
4142 return "TotalReveredFactions";
4144 return "TotalHonoredFactions";
4146 return "TotalFactionsEncountered";
4148 return "LootAnyItem";
4150 return "ObtainAnyItem";
4152 return "AnyoneTriggerGameEventScenario";
4154 return "RollAnyNeed";
4156 return "RollAnyGreed";
4158 return "ReleasedSpirit";
4160 return "AccountKnownPet";
4162 return "DefeatDungeonEncounterWhileElegibleForLoot";
4164 return "HighestDamageDone";
4166 return "HighestDamageTaken";
4168 return "TotalDamageTaken";
4170 return "HighestHealCast";
4172 return "TotalHealReceived";
4174 return "HighestHealReceived";
4176 return "AbandonAnyQuest";
4178 return "BuyTaxi";
4180 return "GetLootByType";
4182 return "LandTargetedSpellOnTarget";
4184 return "LearnTradeskillSkillLine";
4186 return "HonorableKills";
4188 return "AcceptSummon";
4190 return "EarnAchievementPoints";
4192 return "RollDisenchant";
4194 return "RollAnyDisenchant";
4196 return "CompletedLFGDungeon";
4198 return "CompletedLFGDungeonWithStrangers";
4200 return "KickInitiatorInLFGDungeon";
4202 return "KickVoterInLFGDungeon";
4204 return "KickTargetInLFGDungeon";
4206 return "AbandonedLFGDungeon";
4208 return "MoneySpentOnGuildRepair";
4210 return "GuildAttainedLevel";
4212 return "CreatedItemsByCastingSpell";
4214 return "FishInAnyPool";
4216 return "GuildBankTabsPurchased";
4218 return "EarnGuildAchievementPoints";
4220 return "WinAnyBattleground";
4222 return "ParticipateInAnyBattleground";
4224 return "EarnBattlegroundRating";
4226 return "GuildTabardCreated";
4228 return "CompleteQuestsCountForGuild";
4230 return "HonorableKillsForGuild";
4232 return "KillAnyCreatureForGuild";
4234 return "GroupedTankLeftEarlyInLFGDungeon";
4236 return "CompleteGuildChallenge";
4238 return "CompleteAnyGuildChallenge";
4240 return "MarkedAFKInBattleground";
4242 return "RemovedAFKInBattleground";
4244 return "StartAnyBattleground";
4246 return "CompleteAnyBattleground";
4248 return "MarkedSomeoneAFKInBattleground";
4250 return "CompletedLFRDungeon";
4252 return "AbandonedLFRDungeon";
4254 return "KickInitiatorInLFRDungeon";
4256 return "KickVoterInLFRDungeon";
4258 return "KickTargetInLFRDungeon";
4260 return "GroupedTankLeftEarlyInLFRDungeon";
4262 return "CompleteAnyScenario";
4264 return "CompleteScenario";
4266 return "EnterAreaTriggerWithActionSet";
4268 return "LeaveAreaTriggerWithActionSet";
4270 return "LearnedNewPet";
4272 return "UniquePetsOwned";
4274 return "AccountObtainPetThroughBattle";
4276 return "WinPetBattle";
4278 return "LosePetBattle";
4280 return "BattlePetReachLevel";
4282 return "PlayerObtainPetThroughBattle";
4284 return "ActivelyEarnPetLevel";
4286 return "EnterArea";
4288 return "LeaveArea";
4290 return "DefeatDungeonEncounter";
4292 return "PlaceAnyGarrisonBuilding";
4294 return "PlaceGarrisonBuilding";
4296 return "ActivateAnyGarrisonBuilding";
4298 return "ActivateGarrisonBuilding";
4300 return "UpgradeGarrison";
4302 return "StartAnyGarrisonMissionWithFollowerType";
4304 return "StartGarrisonMission";
4306 return "SucceedAnyGarrisonMissionWithFollowerType";
4308 return "SucceedGarrisonMission";
4310 return "RecruitAnyGarrisonFollower";
4312 return "RecruitGarrisonFollower";
4314 return "AcquireGarrison";
4316 return "LearnAnyGarrisonBlueprint";
4318 return "LearnGarrisonBlueprint";
4320 return "LearnAnyGarrisonSpecialization";
4322 return "LearnGarrisonSpecialization";
4324 return "CollectGarrisonShipment";
4326 return "ItemLevelChangedForGarrisonFollower";
4328 return "LevelChangedForGarrisonFollower";
4330 return "LearnToy";
4332 return "LearnAnyToy";
4334 return "QualityUpgradedForGarrisonFollower";
4336 return "LearnHeirloom";
4338 return "LearnAnyHeirloom";
4340 return "EarnArtifactXP";
4342 return "AnyArtifactPowerRankPurchased";
4344 return "LearnTransmog";
4346 return "LearnAnyTransmog";
4348 return "HonorLevelIncrease";
4350 return "PrestigeLevelIncrease";
4352 return "ActivelyReachLevel";
4354 return "CompleteResearchAnyGarrisonTalent";
4356 return "CompleteResearchGarrisonTalent";
4358 return "LearnAnyTransmogInSlot";
4360 return "RecruitAnyGarrisonTroop";
4362 return "StartResearchAnyGarrisonTalent";
4364 return "StartResearchGarrisonTalent";
4366 return "CompleteAnyWorldQuest";
4368 return "EarnLicense";
4370 return "CollectTransmogSetFromGroup";
4372 return "ParagonLevelIncreaseWithFaction";
4374 return "PlayerHasEarnedHonor";
4376 return "KillCreatureScenario";
4378 return "ArtifactPowerRankPurchased";
4380 return "ChooseAnyRelicTalent";
4382 return "ChooseRelicTalent";
4384 return "EarnExpansionLevel";
4386 return "AccountHonorLevelReached";
4388 return "EarnArtifactXPForAzeriteItem";
4390 return "AzeriteLevelReached";
4392 return "MythicPlusCompleted";
4394 return "ScenarioGroupCompleted";
4396 return "CompleteAnyReplayQuest";
4398 return "BuyItemsFromVendors";
4400 return "SellItemsToVendors";
4402 return "ReachMaxLevel";
4404 return "MemorizeSpell";
4406 return "LearnTransmogIllusion";
4408 return "LearnAnyTransmogIllusion";
4410 return "EnterTopLevelArea";
4412 return "LeaveTopLevelArea";
4414 return "SocketGarrisonTalent";
4416 return "SocketAnySoulbindConduit";
4418 return "ObtainAnyItemWithCurrencyValue";
4420 return "MythicPlusRatingAttained";
4422 return "SpentTalentPoint";
4424 return "MythicPlusDisplaySeasonEnded";
4426 return "WinRatedSoloShuffleRound";
4428 return "ParticipateInRatedSoloShuffleRound";
4430 return "ReputationAmountGained";
4432 return "FulfillAnyCraftingOrder";
4434 return "FulfillCraftingOrderType";
4436 return "PerksProgramMonthComplete";
4438 return "CompleteTrackingQuest";
4440 return "GainLevels";
4441 default:
4442 return "MissingType";
4443 }
4444}
4445
4447{
4448 static CriteriaMgr instance;
4449 return &instance;
4450}
4451
4452namespace
4453{
4454inline bool IsCriteriaTypeStoredByAsset(CriteriaType type)
4455{
4456 switch (type)
4457 {
4491 return true;
4492 default:
4493 break;
4494 }
4495 return false;
4496}
4497}
4498
4500{
4501 if (asset && IsCriteriaTypeStoredByAsset(type))
4502 {
4503 auto itr = _criteriasByAsset[size_t(type)].find(asset);
4504 if (itr != _criteriasByAsset[size_t(type)].end())
4505 return itr->second;
4506
4507 return EmptyCriteriaList;
4508 }
4509
4510 return _criteriasByType[size_t(type)];
4511}
4512
4514{
4515 if (CriteriaList const* criteriaList = Trinity::Containers::MapGetValuePtr(_scenarioCriteriasByTypeAndScenarioId[size_t(type)], scenarioId))
4516 return *criteriaList;
4517
4518 return EmptyCriteriaList;
4519}
4520
4521std::unordered_map<int32, CriteriaList> const& CriteriaMgr::GetCriteriaByStartEvent(CriteriaStartEvent startEvent) const
4522{
4523 return _criteriasByStartEvent[size_t(startEvent)];
4524}
4525
4527{
4528 return Trinity::Containers::MapGetValuePtr(_criteriasByStartEvent[size_t(startEvent)], asset);
4529}
4530
4531std::unordered_map<int32, CriteriaList> const& CriteriaMgr::GetCriteriaByFailEvent(CriteriaFailEvent failEvent) const
4532{
4533 return _criteriasByFailEvent[size_t(failEvent)];
4534}
4535
4537{
4538 return Trinity::Containers::MapGetValuePtr(_criteriasByFailEvent[size_t(failEvent)], asset);
4539}
4540
4541CriteriaMgr::CriteriaMgr() = default;
4542
4543//==========================================================
4545{
4546 for (std::pair<uint32 const, CriteriaTree*>& criteriaTree : _criteriaTrees)
4547 delete criteriaTree.second;
4548
4549 for (std::pair<uint32 const, Criteria*>& criteria : _criteria)
4550 delete criteria.second;
4551
4552 for (std::pair<uint32 const, ModifierTreeNode*>& criteriaModifier : _criteriaModifiers)
4553 delete criteriaModifier.second;
4554}
4555
4557{
4558 uint32 oldMSTime = getMSTime();
4559
4560 if (sModifierTreeStore.GetNumRows() == 0)
4561 {
4562 TC_LOG_ERROR("server.loading", ">> Loaded 0 criteria modifiers.");
4563 return;
4564 }
4565
4566 // Load modifier tree nodes
4567 for (uint32 i = 0; i < sModifierTreeStore.GetNumRows(); ++i)
4568 {
4569 ModifierTreeEntry const* tree = sModifierTreeStore.LookupEntry(i);
4570 if (!tree)
4571 continue;
4572
4573 ModifierTreeNode* node = new ModifierTreeNode();
4574 node->Entry = tree;
4575 _criteriaModifiers[node->Entry->ID] = node;
4576 }
4577
4578 // Build tree
4579 for (std::pair<uint32 const, ModifierTreeNode*>& criteriaModifier : _criteriaModifiers)
4580 if (ModifierTreeNode* parentNode = Trinity::Containers::MapGetValuePtr(_criteriaModifiers, criteriaModifier.second->Entry->Parent))
4581 parentNode->Children.push_back(criteriaModifier.second);
4582
4583 TC_LOG_INFO("server.loading", ">> Loaded {} criteria modifiers in {} ms", uint32(_criteriaModifiers.size()), GetMSTimeDiffToNow(oldMSTime));
4584}
4585
4586template<typename T>
4587T GetEntry(std::unordered_map<uint32, T> const& map, CriteriaTreeEntry const* tree)
4588{
4589 CriteriaTreeEntry const* cur = tree;
4590 auto itr = map.find(tree->ID);
4591 while (itr == map.end())
4592 {
4593 if (!cur->Parent)
4594 break;
4595
4596 cur = sCriteriaTreeStore.LookupEntry(cur->Parent);
4597 if (!cur)
4598 break;
4599
4600 itr = map.find(cur->ID);
4601 }
4602
4603 if (itr == map.end())
4604 return nullptr;
4605
4606 return itr->second;
4607};
4608
4610{
4611 uint32 oldMSTime = getMSTime();
4612
4613 std::unordered_map<uint32 /*criteriaTreeID*/, AchievementEntry const*> achievementCriteriaTreeIds;
4614 for (AchievementEntry const* achievement : sAchievementStore)
4615 if (achievement->CriteriaTree)
4616 achievementCriteriaTreeIds[achievement->CriteriaTree] = achievement;
4617
4618 std::unordered_map<uint32 /*criteriaTreeID*/, ScenarioStepEntry const*> scenarioCriteriaTreeIds;
4619 for (ScenarioStepEntry const* scenarioStep : sScenarioStepStore)
4620 if (scenarioStep->Criteriatreeid)
4621 scenarioCriteriaTreeIds[scenarioStep->Criteriatreeid] = scenarioStep;
4622
4623 std::unordered_map<uint32 /*criteriaTreeID*/, QuestObjective const*> questObjectiveCriteriaTreeIds;
4624 for (auto const& [questId, quest] : sObjectMgr->GetQuestTemplates())
4625 {
4626 for (QuestObjective const& objective : quest->Objectives)
4627 {
4628 if (objective.Type != QUEST_OBJECTIVE_CRITERIA_TREE)
4629 continue;
4630
4631 if (objective.ObjectID)
4632 questObjectiveCriteriaTreeIds[objective.ObjectID] = &objective;
4633 }
4634 }
4635
4636 // Load criteria tree nodes
4637 for (CriteriaTreeEntry const* tree : sCriteriaTreeStore)
4638 {
4639 // Find linked achievement
4640 AchievementEntry const* achievement = GetEntry(achievementCriteriaTreeIds, tree);
4641 ScenarioStepEntry const* scenarioStep = GetEntry(scenarioCriteriaTreeIds, tree);
4642 QuestObjective const* questObjective = GetEntry(questObjectiveCriteriaTreeIds, tree);
4643 if (!achievement && !scenarioStep && !questObjective)
4644 continue;
4645
4646 CriteriaTree* criteriaTree = new CriteriaTree();
4647 criteriaTree->ID = tree->ID;
4648 criteriaTree->Achievement = achievement;
4649 criteriaTree->ScenarioStep = scenarioStep;
4650 criteriaTree->QuestObjective = questObjective;
4651 criteriaTree->Entry = tree;
4652
4653 _criteriaTrees[criteriaTree->Entry->ID] = criteriaTree;
4654 }
4655
4656 // Build tree
4657 for (std::pair<uint32 const, CriteriaTree*> const& criteriaTree : _criteriaTrees)
4658 {
4659 if (CriteriaTree* parent = Trinity::Containers::MapGetValuePtr(_criteriaTrees, criteriaTree.second->Entry->Parent))
4660 parent->Children.push_back(criteriaTree.second);
4661
4662 if (sCriteriaStore.HasRecord(criteriaTree.second->Entry->CriteriaID))
4663 _criteriaTreeByCriteria[criteriaTree.second->Entry->CriteriaID].push_back(criteriaTree.second);
4664 }
4665
4666 // Load criteria
4667 uint32 criterias = 0;
4668 uint32 guildCriterias = 0;
4669 uint32 scenarioCriterias = 0;
4670 uint32 questObjectiveCriterias = 0;
4671 for (CriteriaEntry const* criteriaEntry : sCriteriaStore)
4672 {
4673 ASSERT(criteriaEntry->Type < AsUnderlyingType(CriteriaType::Count), "CriteriaType::Count must be greater than or equal to %u but is currently equal to %u",
4674 criteriaEntry->Type + 1, uint32(CriteriaType::Count));
4675 ASSERT(criteriaEntry->StartEvent < AsUnderlyingType(CriteriaStartEvent::Count), "CriteriaStartEvent::Count must be greater than or equal to %u but is currently equal to %u",
4676 criteriaEntry->StartEvent + 1, uint32(CriteriaStartEvent::Count));
4677 ASSERT(criteriaEntry->FailEvent < AsUnderlyingType(CriteriaFailEvent::Count), "CriteriaFailEvent::Count must be greater than or equal to %u but is currently equal to %u",
4678 criteriaEntry->FailEvent + 1, uint32(CriteriaFailEvent::Count));
4679
4680 auto treeItr = _criteriaTreeByCriteria.find(criteriaEntry->ID);
4681 if (treeItr == _criteriaTreeByCriteria.end())
4682 continue;
4683
4684 Criteria* criteria = new Criteria();
4685 criteria->ID = criteriaEntry->ID;
4686 criteria->Entry = criteriaEntry;
4687 criteria->Modifier = Trinity::Containers::MapGetValuePtr(_criteriaModifiers, criteriaEntry->ModifierTreeId);
4688
4689 _criteria[criteria->ID] = criteria;
4690
4691 std::vector<uint32> scenarioIds;
4692
4693 for (CriteriaTree const* tree : treeItr->second)
4694 {
4695 const_cast<CriteriaTree*>(tree)->Criteria = criteria;
4696
4697 if (AchievementEntry const* achievement = tree->Achievement)
4698 {
4699 if (achievement->Flags & ACHIEVEMENT_FLAG_GUILD)
4700 criteria->FlagsCu |= CRITERIA_FLAG_CU_GUILD;
4701 else if (achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT)
4702 criteria->FlagsCu |= CRITERIA_FLAG_CU_ACCOUNT;
4703 else
4704 criteria->FlagsCu |= CRITERIA_FLAG_CU_PLAYER;
4705 }
4706 else if (tree->ScenarioStep)
4707 {
4709 scenarioIds.push_back(tree->ScenarioStep->ScenarioID);
4710 }
4711 else if (tree->QuestObjective)
4713 }
4714
4716 {
4717 ++criterias;
4718 _criteriasByType[criteriaEntry->Type].push_back(criteria);
4719 if (IsCriteriaTypeStoredByAsset(CriteriaType(criteriaEntry->Type)))
4720 {
4721 if (CriteriaType(criteriaEntry->Type) != CriteriaType::RevealWorldMapOverlay)
4722 _criteriasByAsset[criteriaEntry->Type][criteriaEntry->Asset.ID].push_back(criteria);
4723 else
4724 {
4725 WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(criteriaEntry->Asset.WorldMapOverlayID);
4726 if (!worldOverlayEntry)
4727 break;
4728
4729 for (uint8 j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
4730 {
4731 if (worldOverlayEntry->AreaID[j])
4732 {
4733 bool valid = true;
4734 for (uint8 i = 0; i < j; ++i)
4735 if (worldOverlayEntry->AreaID[j] == worldOverlayEntry->AreaID[i])
4736 valid = false;
4737 if (valid)
4738 _criteriasByAsset[criteriaEntry->Type][worldOverlayEntry->AreaID[j]].push_back(criteria);
4739 }
4740 }
4741 }
4742 }
4743 }
4744
4745 if (criteria->FlagsCu & CRITERIA_FLAG_CU_GUILD)
4746 {
4747 ++guildCriterias;
4748 _guildCriteriasByType[criteriaEntry->Type].push_back(criteria);
4749 }
4750
4751 if (criteria->FlagsCu & CRITERIA_FLAG_CU_SCENARIO)
4752 {
4753 ++scenarioCriterias;
4754 for (uint32 scenarioId : scenarioIds)
4755 _scenarioCriteriasByTypeAndScenarioId[criteriaEntry->Type][scenarioId].push_back(criteria);
4756 }
4757
4759 {
4760 ++questObjectiveCriterias;
4761 _questObjectiveCriteriasByType[criteriaEntry->Type].push_back(criteria);
4762 }
4763
4764 if (criteriaEntry->StartEvent)
4765 _criteriasByStartEvent[criteriaEntry->StartEvent][criteriaEntry->StartAsset].push_back(criteria);
4766
4767 if (criteriaEntry->FailEvent)
4768 _criteriasByFailEvent[criteriaEntry->FailEvent][criteriaEntry->FailAsset].push_back(criteria);
4769 }
4770
4771 TC_LOG_INFO("server.loading", ">> Loaded {} criteria, {} guild criteria, {} scenario criteria and {} quest objective criteria in {} ms.", criterias, guildCriterias, scenarioCriterias, questObjectiveCriterias, GetMSTimeDiffToNow(oldMSTime));
4772}
4773
4775{
4776 uint32 oldMSTime = getMSTime();
4777
4778 _criteriaDataMap.clear(); // need for reload case
4779
4780 QueryResult result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM criteria_data");
4781
4782 if (!result)
4783 {
4784 TC_LOG_INFO("server.loading", ">> Loaded 0 additional criteria data. DB table `criteria_data` is empty.");
4785 return;
4786 }
4787
4788 uint32 count = 0;
4789
4790 do
4791 {
4792 Field* fields = result->Fetch();
4793 uint32 criteria_id = fields[0].GetUInt32();
4794
4795 Criteria const* criteria = GetCriteria(criteria_id);
4796
4797 if (!criteria)
4798 {
4799 TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains data for non-existing criteria (Entry: {}). Ignored.", criteria_id);
4800 continue;
4801 }
4802
4803 uint32 dataType = fields[1].GetUInt8();
4804 std::string scriptName = fields[4].GetString();
4805 uint32 scriptId = 0;
4806 if (!scriptName.empty())
4807 {
4808 if (dataType != CRITERIA_DATA_TYPE_SCRIPT)
4809 TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains a ScriptName for non-scripted data type (Entry: {}, type {}), useless data.", criteria_id, dataType);
4810 else
4811 scriptId = sObjectMgr->GetScriptId(scriptName);
4812 }
4813
4814 CriteriaData data(dataType, fields[2].GetUInt32(), fields[3].GetUInt32(), scriptId);
4815
4816 if (!data.IsValid(criteria))
4817 continue;
4818
4819 // this will allocate empty data set storage
4820 CriteriaDataSet& dataSet = _criteriaDataMap[criteria_id];
4821 dataSet.SetCriteriaId(criteria_id);
4822
4823 // add real data only for not NONE data types
4825 dataSet.Add(data);
4826
4827 // counting data by and data types
4828 ++count;
4829 }
4830 while (result->NextRow());
4831
4832 TC_LOG_INFO("server.loading", ">> Loaded {} additional criteria data in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
4833}
4834
4836{
4837 auto itr = _criteriaTrees.find(criteriaTreeId);
4838 if (itr == _criteriaTrees.end())
4839 return nullptr;
4840
4841 return itr->second;
4842}
4843
4845{
4846 auto itr = _criteria.find(criteriaId);
4847 if (itr == _criteria.end())
4848 return nullptr;
4849
4850 return itr->second;
4851}
4852
4854{
4855 auto itr = _criteriaModifiers.find(modifierTreeId);
4856 if (itr != _criteriaModifiers.end())
4857 return itr->second;
4858
4859 return nullptr;
4860}
#define sArenaTeamMgr
Definition: ArenaTeamMgr.h:53
#define MAX_ARENA_SLOT
Definition: ArenaTeam.h:109
constexpr uint32 ITEM_ID_HEART_OF_AZEROTH
Definition: AzeriteItem.h:23
@ DAY
Definition: Common.h:31
T GetEntry(std::unordered_map< uint32, T > const &map, CriteriaTreeEntry const *tree)
@ CRITERIA_FLAG_CU_ACCOUNT
@ CRITERIA_FLAG_CU_PLAYER
@ CRITERIA_FLAG_CU_QUEST_OBJECTIVE
@ CRITERIA_FLAG_CU_SCENARIO
@ CRITERIA_FLAG_CU_GUILD
ProgressType
@ PROGRESS_SET
@ PROGRESS_ACCUMULATE
@ PROGRESS_HIGHEST
#define sCriteriaMgr
std::vector< Criteria const * > CriteriaList
std::vector< CriteriaTree const * > CriteriaTreeList
@ CRITERIA_DATA_TYPE_INSTANCE_SCRIPT
@ CRITERIA_DATA_TYPE_T_LEVEL
@ CRITERIA_DATA_TYPE_VALUE
@ CRITERIA_DATA_TYPE_T_CREATURE
@ CRITERIA_DATA_TYPE_SCRIPT
@ CRITERIA_DATA_TYPE_S_AURA
@ CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE
@ CRITERIA_DATA_TYPE_GAME_EVENT
@ CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH
@ CRITERIA_DATA_TYPE_MAP_ID
@ CRITERIA_DATA_TYPE_S_EQUIPPED_ITEM
@ CRITERIA_DATA_TYPE_S_DRUNK
@ CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE
@ CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT
@ CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE
@ CRITERIA_DATA_TYPE_T_TEAM
@ CRITERIA_DATA_TYPE_HOLIDAY
@ CRITERIA_DATA_TYPE_T_GENDER
@ CRITERIA_DATA_TYPE_T_AURA
@ CRITERIA_DATA_TYPE_S_ITEM_QUALITY
@ CRITERIA_DATA_TYPE_NONE
@ CRITERIA_DATA_TYPE_S_KNOWN_TITLE
@ MAX_CRITERIA_DATA_TYPE
DB2Storage< ArtifactAppearanceEntry > sArtifactAppearanceStore("ArtifactAppearance.db2", &ArtifactAppearanceLoadInfo::Instance)
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< WorldMapOverlayEntry > sWorldMapOverlayStore("WorldMapOverlay.db2", &WorldMapOverlayLoadInfo::Instance)
DB2Storage< ItemModifiedAppearanceExtraEntry > sItemModifiedAppearanceExtraStore("ItemModifiedAppearanceExtra.db2", &ItemModifiedAppearanceExtraLoadInfo::Instance)
DB2Storage< Achievement_CategoryEntry > sAchievementCategoryStore("Achievement_Category.db2", &AchievementCategoryLoadInfo::Instance)
DB2Storage< BattlemasterListEntry > sBattlemasterListStore("BattlemasterList.db2", &BattlemasterListLoadInfo::Instance)
DB2Storage< FriendshipReputationEntry > sFriendshipReputationStore("FriendshipReputation.db2", &FriendshipReputationLoadInfo::Instance)
DB2Storage< AchievementEntry > sAchievementStore("Achievement.db2", &AchievementLoadInfo::Instance)
DB2Storage< FriendshipRepReactionEntry > sFriendshipRepReactionStore("FriendshipRepReaction.db2", &FriendshipRepReactionLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< CriteriaEntry > sCriteriaStore("Criteria.db2", &CriteriaLoadInfo::Instance)
DB2Storage< GarrBuildingEntry > sGarrBuildingStore("GarrBuilding.db2", &GarrBuildingLoadInfo::Instance)
DB2Storage< ModifierTreeEntry > sModifierTreeStore("ModifierTree.db2", &ModifierTreeLoadInfo::Instance)
DB2Storage< WorldStateExpressionEntry > sWorldStateExpressionStore("WorldStateExpression.db2", &WorldStateExpressionLoadInfo::Instance)
DB2Storage< GarrPlotInstanceEntry > sGarrPlotInstanceStore("GarrPlotInstance.db2", &GarrPlotInstanceLoadInfo::Instance)
DB2Storage< CharTitlesEntry > sCharTitlesStore("CharTitles.db2", &CharTitlesLoadInfo::Instance)
DB2Storage< TraitNodeEntryEntry > sTraitNodeEntryStore("TraitNodeEntry.db2", &TraitNodeEntryLoadInfo::Instance)
DB2Storage< CreatureDisplayInfoExtraEntry > sCreatureDisplayInfoExtraStore("CreatureDisplayInfoExtra.db2", &CreatureDisplayInfoExtraLoadInfo::Instance)
DB2Storage< ScenarioStepEntry > sScenarioStepStore("ScenarioStep.db2", &ScenarioStepLoadInfo::Instance)
DB2Storage< CriteriaTreeEntry > sCriteriaTreeStore("CriteriaTree.db2", &CriteriaTreeLoadInfo::Instance)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore("BattlePetSpecies.db2", &BattlePetSpeciesLoadInfo::Instance)
DB2Storage< ItemModifiedAppearanceEntry > sItemModifiedAppearanceStore("ItemModifiedAppearance.db2", &ItemModifiedAppearanceLoadInfo::Instance)
DB2Storage< PvpTierEntry > sPvpTierStore("PvpTier.db2", &PvpTierLoadInfo::Instance)
DB2Storage< ChrRacesEntry > sChrRacesStore("ChrRaces.db2", &ChrRacesLoadInfo::Instance)
DB2Storage< PlayerConditionEntry > sPlayerConditionStore("PlayerCondition.db2", &PlayerConditionLoadInfo::Instance)
DB2Storage< CreatureDisplayInfoEntry > sCreatureDisplayInfoStore("CreatureDisplayInfo.db2", &CreatureDisplayInfoLoadInfo::Instance)
DB2Storage< HolidaysEntry > sHolidaysStore("Holidays.db2", &HolidaysLoadInfo::Instance)
DB2Storage< FactionTemplateEntry > sFactionTemplateStore("FactionTemplate.db2", &FactionTemplateLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
DB2Storage< GarrFollowerEntry > sGarrFollowerStore("GarrFollower.db2", &GarrFollowerLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
DB2Storage< GarrAbilityEntry > sGarrAbilityStore("GarrAbility.db2", &GarrAbilityLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
#define MAX_WORLD_MAP_OVERLAY_AREA_IDX
TraitConfigType
Definition: DBCEnums.h:2185
@ STRONG_MAX_LEVEL
Definition: DBCEnums.h:55
PlayerConditionLfgStatus
Definition: DBCEnums.h:1753
Difficulty
Definition: DBCEnums.h:873
@ DIFFICULTY_NONE
Definition: DBCEnums.h:874
TraitCombatConfigFlags
Definition: DBCEnums.h:2157
ModifierTreeOperator
Definition: DBCEnums.h:1701
@ FACTION_MASK_ALLIANCE
Definition: DBCEnums.h:950
@ FACTION_MASK_HORDE
Definition: DBCEnums.h:951
@ FACTION_MASK_PLAYER
Definition: DBCEnums.h:949
@ ACHIEVEMENT_FLAG_ACCOUNT
Definition: DBCEnums.h:101
@ ACHIEVEMENT_FLAG_GUILD
Definition: DBCEnums.h:98
ModifierTreeType
Definition: DBCEnums.h:1320
@ GroupMemberCountFromConnectedRealmEqualOrGreaterThan
@ GarrisonShipmentContainerIsFull
@ PlayerExpansionLevelEqualOrGreaterThan
@ PlayerHasTrackedCurrencyEqualOrGreaterThan
@ PlayerToTargetLevelDeltaGreaterThan
@ PlayerHasItemQuantityIncludingBank
@ PlayerBattlegroundRatingEqualOrGreaterThan
@ PlayerHasTraitNodeEntryInActiveConfig
@ GarrisonFollowersWithQualityEqualOrGreaterThan
@ PlayerHasCurrencyEqualOrGreaterThan
@ ReputationWithFactionIsEqualOrGreaterThan
@ PlayerMythicPlusRunCountInCurrentExpansionEqualOrGreaterThan
@ PlayerIsQnQuestLinkedToScheduledWorldStateGroup
@ BattlePetTeamWithTypeEqualOrGreaterThan
@ GarrisonBuildingIsUnderConstruction
@ UniqueBattlePetsEqualOrGreaterThan
@ PlayerSummonedBattlePetSpecies
@ PlayerLanguageSkillEqualOrGreaterThan
@ ParagonReputationLevelWithFactionEqualOrGreaterThan
@ PlayerHasAzeriteEssenceRankEqual
@ PlayerHasImpInABallToySubscriptionReward
@ AllPlayersInGroupHaveAchievement
@ PlayerHasWrathCollectorsEdition
@ GarrisonFollowerCountWithInactiveWithItemLevelEqualOrGreaterThan
@ TargetLevelWithinOrAboveLevelRange
@ PlayerHasAPACSubscriptionReward_2020
@ PlayerHasCompletedQuestObjective
@ GarrisonBuildingWithLevelEqualOrGreaterThan
@ GarrisonFollowerWithAbilityAssignedToBuilding
@ PlayerHasTBCCDEPathOfIllidan_Toy
@ PlayerHasCompletedDungeonEncounterInDifficulty
@ PlayerUsedBoostLessThanHoursAgoRealTime
@ PlayerCreatedCharacterLessThanHoursAgoRealTime
@ PlayerHasTBCCDEWarpStalker_Mount
@ GarrisonFollowerWithTraitAssignedToBuilding
@ CurrencySpentOnGarrisonTalentResearchEqualOrGreaterThan
@ PlayerHasSoulbindConduitRankEqualOrGreaterThan
@ PlayerLevelWithinContentTuning
@ HasGarrisonBuildingActiveSpecialization
@ PlayerHasCompletedPercentageOfQuestline
@ PrestigeLevelEqualOrGreaterThan
@ PlayerHasItemWithKeystoneLevelModifierEqualOrGreaterThan
@ PlayerHasEmptyInventorySlotCountEqualOrGreaterThan
@ JailersTowerActiveFloorIndexEqualOrGreaterThan
@ PlayerLootSpecializationMatchesRole
@ PlayerHasItemWithBonusListFromTreeAndQuality
@ InstancePlayerCountEqualOrLessThan
@ PlayerAuraStackCountEqualOrGreaterThan
@ GarrisonFollowerCountWithItemLevelEqualOrGreaterThan
@ PlayerSpellShapeshiftFormCreatureDisplayInfoSelection
@ MaxJailersTowerLevelEqualOrGreaterThan
@ PlayerSoulbindConduitCountAtRankEqualOrGreaterThan
@ TargetLevelWithinContentTuning
@ GarrisonFollowersWithLevelEqualOrGreaterThan
@ PlayerIsAllowedToToggleWarModeInArea
@ PlayerUsedBoostLessThanHoursAgoGameTime
@ PlayerHasPerksProgramPendingReward
@ GarrisonPlotInstanceHasBuildingThatIsReadyToActivate
@ GarrisonFollowerWithLevelAssignedToBuilding
@ PlayerLevelWithinOrAboveContentTuning
@ BattlePetTeamWithSpeciesEqualOrGreaterThan
@ ServerExpansionEqualOrGreaterThan
@ ParagonReputationLevelEqualOrGreaterThan
@ GuildGroupMemberCountEqualOrGreaterThan
@ JailersTowerActiveFloorDifficultyEqualOrGreaterThan
@ PlayerAuraWithLabelStackCountEqual
@ PlayerAuraWithLabelStackCountEqualOrLessThan
@ GarrisonFollowerWithAbilityAtLevelEqualOrGreaterThan
@ GarrisonMissionIsReadyToCollect
@ TargetAuraStackCountEqualOrGreaterThan
@ ArtifactTraitUnlockedCountEqualOrGreaterThan
@ GarrisonFollowerWithTraitAtLevelEqualOrGreaterThan
@ AllGarrisonPlotsFilledWithBuildingsWithLevelEqualOrGreater
@ HasGarrisonBuildingSpecialization
@ PlayerBestWeeklyWinPvpTierInBracketEqualOrGreaterThan
@ PlayerInebriationLevelEqualOrGreaterThan
@ PlayerEquippedArtifactAppearanceSet
@ PlayerAzeriteLevelEqualOrGreaterThan
@ GarrisonFollowerCountWithLevelEqualOrGreaterThan
@ GroupMemberCountWithAchievementEqualOrLessThan
@ PlayerMythicPlusRatingEqualOrGreaterThan
@ PlayerCanAccessShadowlandsPrepurchaseContent
@ GarrisonMissionHasBeenCompleted
@ PlayerPvpTierInBracketEqualOrGreaterThan
@ MinimumAverageItemHighWaterMarkForSpec
@ GarrisonMissionCountInSetLessThan
@ GarrisonTalentResearchInProgress
@ HasPersonalRatingEqualOrGreaterThan
@ TargetLevelWithinOrAboveContentTuning
@ GarrisonTalentResearchedAndAtRankEqualOrGreaterThan
@ PlayerHasCompletedQuestOrIsOnQuest
@ GarrisonPlotInstanceCountEqualOrGreaterThan
@ PlayerCreatedCharacterLessThanHoursAgoGameTime
@ PlayerCanAcceptQuestInQuestline
@ PlayerHasAzeriteEssenceInSlotAtRankGreaterThan
@ PlayerAuraWithLabelStackCountEqualOrGreaterThan
@ PlayerHasTraitNodeEntryInActiveConfigRankGreaterOrEqualThan
@ PlayerHasAzeriteEssenceRankGreaterThan
@ BattlePetHealthPercentLessThan
@ PlayerCountIsValidToStartGarrisonInvasion
@ HasBlueprintForGarrisonBuilding
@ BattlePetAchievementPointsEqualOrGreaterThan
@ PlayerHasArtifactPowerRankCountPurchasedEqualOrGreaterThan
@ BattlePetTeamWithAliveEqualOrGreaterThan
@ PlayerHasItemInHistoryOfProgressiveEvent
@ PlayerSummonedBattlePetIsMaxLevel
@ PlayerHasWeeklyRewardsAvailable
@ PlayerDailyRandomValueMod_X_Equals
@ PlayerQuestObjectiveProgressEqual
@ PlayerHasItemTransmogrifiedToItemModifiedAppearance
@ PlayerQuestObjectiveProgressEqualOrGreaterThan
@ PlayerLevelWithinOrAboveLevelRange
@ GarrisonTierEqualOrGreaterThan
@ PlayerGuildReputationEqualOrGreaterThan
@ CurrentGarrisonBuildingLevelEqual
@ MythicPlusKeystoneLevelEqualOrGreaterThan
@ PlayerHasCompletedQuestlineQuestCount
@ TargetIsPlayerAndMeetsCondition
@ PlayersAuthExpansionLevelEqualOrGreaterThan
@ TargetToPlayerLevelDeltaGreaterThan
@ GarrisonShipmentOfTypeIsPending
@ GarrisonFollowerItemLevelEqualOrGreaterThan
@ PlayerHasAzeriteEssenceInSlotAtRankLessThan
@ OrderOfTheCloudSerpentReputationGreaterThan
@ PlayerHasMoreThanAchievementPoints
@ PlayerHasAzeriteEssenceRankLessThan
@ PlayerHasVanillaCollectorsEdition
@ PlayerHasBeenGrantedLevelsFromRaF
ChrSpecialization
Definition: DBCEnums.h:357
CriteriaStartEvent
Definition: DBCEnums.h:470
CriteriaTreeOperator
Definition: DBCEnums.h:774
CriteriaFailEvent
Definition: DBCEnums.h:449
uint32 constexpr ACHIVEMENT_CATEGORY_PET_BATTLES
Definition: DBCEnums.h:107
CriteriaType
Definition: DBCEnums.h:503
@ CompleteResearchGarrisonTalent
@ ParticipateInRatedSoloShuffleRound
@ LearnGarrisonSpecialization
@ LevelChangedForGarrisonFollower
@ LearnGarrisonBlueprint
@ MoneyEarnedFromQuesting
@ MythicPlusDisplaySeasonEnded
@ CompleteAnyDailyQuestPerDay
@ MoneySpentOnGuildRepair
@ LearnAnyGarrisonSpecialization
@ ParagonLevelIncreaseWithFaction
@ CatchFishInFishingHole
@ LearnTradeskillSkillLine
@ HonorableKillsForGuild
@ BattlePetAchievementPointsEarned
@ LearnAnyGarrisonBlueprint
@ EarnPersonalArenaRating
@ CompletedLFGDungeonWithStrangers
@ CompleteQuestsCountForGuild
@ SucceedAnyGarrisonMissionWithFollowerType
@ KilledAllUnitsInSpawnRegion
@ MaxDistFallenWithoutDying
@ SucceedGarrisonMission
@ LearnAnyTransmogInSlot
@ MoneyLootedFromCreatures
@ CompleteResearchAnyGarrisonTalent
@ KickInitiatorInLFRDungeon
@ CreatedItemsByCastingSpell
@ GroupedTankLeftEarlyInLFGDungeon
@ EarnBattlegroundRating
@ TotalFactionsEncountered
@ ReputationAmountGained
@ RecruitAnyGarrisonFollower
@ CollectTransmogSetFromGroup
@ EarnChallengeModeMedal
@ DefeatDungeonEncounter
@ CreatedItemsByCastingSpellWithLimit
@ ExhaustAnyResearchSite
@ KickTargetInLFRDungeon
@ PerksProgramMonthComplete
@ QualityUpgradedForGarrisonFollower
@ RecruitAnyGarrisonTroop
@ KickInitiatorInLFGDungeon
@ DeliverKillingBlowToClass
@ MarkedSomeoneAFKInBattleground
@ ItemLevelChangedForGarrisonFollower
@ CompleteGuildChallenge
@ CompleteAnyReplayQuest
@ FulfillCraftingOrderType
@ ParticipateInBattleground
@ DeliverKillingBlowToRace
@ KillAnyCreatureForGuild
@ MoneySpentAtBarberShop
@ MythicPlusRatingAttained
@ FulfillAnyCraftingOrder
@ CollectGarrisonShipment
@ ActivateAnyGarrisonBuilding
@ ScenarioGroupCompleted
@ ArtifactPowerRankPurchased
@ KickTargetInLFGDungeon
@ StartResearchAnyGarrisonTalent
@ StartResearchGarrisonTalent
@ LearnAnyTransmogIllusion
@ LeaveAreaTriggerWithActionSet
@ ObtainAnyItemWithCurrencyValue
@ DieFromEnviromentalDamage
@ StartAnyGarrisonMissionWithFollowerType
@ EnterAreaTriggerWithActionSet
@ LearnSpellFromSkillLine
@ PlayerTriggerGameEvent
@ AnyArtifactPowerRankPurchased
@ AnyoneTriggerGameEventScenario
@ CompleteResearchProject
@ MarkedAFKInBattleground
@ ParticipateInAnyBattleground
@ LandTargetedSpellOnTarget
@ CompleteAnyBattleground
@ GroupedTankLeftEarlyInLFRDungeon
@ PlaceAnyGarrisonBuilding
@ SocketAnySoulbindConduit
@ RecruitGarrisonFollower
@ AccountObtainPetThroughBattle
@ WinRatedSoloShuffleRound
@ CompleteAnyResearchProject
@ ActivateGarrisonBuilding
@ TrackedWorldStateUIModified
@ EarnGuildAchievementPoints
@ MoneyEarnedFromAuctions
@ CompleteAnyChallengeMode
@ CompleteAnyGuildChallenge
@ PlayerObtainPetThroughBattle
@ DefeatDungeonEncounterWhileElegibleForLoot
@ EarnArtifactXPForAzeriteItem
@ AccountHonorLevelReached
@ GuildBankTabsPurchased
@ CompleteInternalCriteria
@ RemovedAFKInBattleground
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
#define UI64FMTD
Definition: Define.h:126
uint8_t uint8
Definition: Define.h:144
int64_t int64
Definition: Define.h:137
int16_t int16
Definition: Define.h:139
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
#define UI64LIT(N)
Definition: Define.h:127
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
@ DISABLE_TYPE_CRITERIA
Definition: DisableMgr.h:31
std::chrono::hours Hours
Hours shorthand typedef.
Definition: Duration.h:38
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:32
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:29
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
#define ASSERT
Definition: Errors.h:68
bool IsHolidayActive(HolidayIds id)
bool IsEventActive(uint16 eventId)
#define sGameEventMgr
Definition: GameEventMgr.h:177
@ GARRISON_ABILITY_FLAG_TRAIT
Definition: Garrison.h:68
GarrisonType
Definition: Garrison.h:34
@ GARRISON_TYPE_GARRISON
Definition: Garrison.h:35
@ FOLLOWER_STATUS_INACTIVE
Definition: Garrison.h:178
@ GROUP_FLAG_CROSS_FACTION
Definition: Group.h:105
@ ITEM_MODIFIER_CHALLENGE_KEYSTONE_LEVEL
Definition: ItemDefines.h:229
@ ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID
Definition: ItemDefines.h:219
@ ITEM_CLASS_WEAPON
Definition: ItemTemplate.h:422
@ ITEM_SUBCLASS_WEAPON_FIST_WEAPON
Definition: ItemTemplate.h:493
#define sLanguageMgr
Definition: LanguageMgr.h:97
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_TRACE(filterType__,...)
Definition: Log.h:153
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
#define sMapMgr
Definition: MapManager.h:184
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ EQUIPMENT_SLOT_MAINHAND
Definition: Player.h:646
@ EQUIPMENT_SLOT_OFFHAND
Definition: Player.h:647
@ PLAYER_FLAGS_WAR_MODE_ACTIVE
Definition: Player.h:438
@ PLAYER_FLAGS_TIMEWALKING
Definition: Player.h:458
@ PLAYER_LOCAL_FLAG_WAR_MODE
Definition: Player.h:489
#define MAX_DRUNKEN
Definition: Player.h:424
@ PLAYER_FLAGS_EX_MERCENARY_MODE
Definition: Player.h:467
DrunkenState
Definition: Player.h:417
std::set< uint32 > RewardedQuestSet
Definition: Player.h:559
@ QUEST_OBJECTIVE_CRITERIA_TREE
Definition: QuestDef.h:346
#define MAX_QUEST_LOG_SIZE
Definition: QuestDef.h:44
QuestStatus
Definition: QuestDef.h:141
@ QUEST_STATUS_FAILED
Definition: QuestDef.h:147
@ QUEST_STATUS_NONE
Definition: QuestDef.h:142
@ QUEST_STATUS_COMPLETE
Definition: QuestDef.h:143
Role Based Access Control related classes definition.
constexpr Trinity::RaceMask< uint64 > RACEMASK_ALL_PLAYABLE
Definition: RaceMask.h:151
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
#define sScriptMgr
Definition: ScriptMgr.h:1418
SpellEffIndex
Definition: SharedDefines.h:29
Language
Gender
@ GENDER_NONE
CreatureFamily
@ MAX_ITEM_QUALITY
@ TEAM_ALLIANCE
@ TEAM_HORDE
Team
@ ALLIANCE
@ HORDE
#define CLASSMASK_ALL_PLAYABLE
AuraStateType
HolidayIds
@ EXPANSION_SHADOWLANDS
Definition: SharedDefines.h:98
AuraType
#define sSpellMgr
Definition: SpellMgr.h:849
std::pair< SkillLineAbilityMap::const_iterator, SkillLineAbilityMap::const_iterator > SkillLineAbilityMapBounds
Definition: SpellMgr.h:621
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition: Timer.h:57
uint32 getMSTime()
Definition: Timer.h:33
#define ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE
Definition: Unit.h:37
float GetPctOf(T value, T max)
Definition: Util.h:78
bool CompareValues(ComparisionType type, T val1, T val2)
Definition: Util.h:469
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
ComparisionType
Definition: Util.h:459
@ COMP_TYPE_MAX
Definition: Util.h:465
#define sWorldStateMgr
Definition: WorldStateMgr.h:50
ArenaTeamMember * GetMember(ObjectGuid guid)
Definition: ArenaTeam.cpp:816
uint32 GetType() const
Definition: ArenaTeam.h:124
uint8 GetStackAmount() const
Definition: SpellAuras.h:189
SpellInfo const * GetSpellInfo() const
Definition: SpellAuras.h:134
ObjectGuid GetCastItemGUID() const
Definition: SpellAuras.h:140
uint32 GetLevel() const
Definition: AzeriteItem.h:41
uint32 GetPetUniqueSpeciesCount() const
bool HasJournalLock() const
Definition: BattlePetMgr.h:201
std::vector< WorldPackets::BattlePet::BattlePetSlot > const & GetSlots() const
Definition: BattlePetMgr.h:183
uint8 GetArenaType() const
Definition: Battleground.h:298
uint32 GetTeamScore(TeamId teamId) const
bool isRated() const
Definition: Battleground.h:331
bool isArena() const
bool isBattleground() const
Team GetPlayerTeam(ObjectGuid guid) const
HeirloomContainer const & GetAccountHeirlooms() const
bool HasToy(uint32 itemId) const
Definition: CollectionMgr.h:99
MountContainer const & GetAccountMounts() const
std::pair< bool, bool > HasItemAppearance(uint32 itemModifiedAppearanceId) const
static bool IsPlayerMeetingCondition(Player const *player, PlayerConditionEntry const *condition)
static bool IsMeetingWorldStateExpression(Map const *map, WorldStateExpressionEntry const *expression)
static uint32 GetPlayerConditionLfgValue(Player const *player, PlayerConditionLfgStatus status)
CreatureTemplate const * GetCreatureTemplate() const
Definition: Creature.h:250
void SetCriteriaProgress(Criteria const *criteria, uint64 changeValue, Player *referencePlayer, ProgressType progressType=PROGRESS_SET)
virtual CriteriaList const & GetCriteriaByType(CriteriaType type, uint32 asset) const =0
virtual void AfterCriteriaTreeUpdate(CriteriaTree const *, Player *)
virtual void SendCriteriaProgressRemoved(uint32 criteriaId)=0
bool ModifierTreeSatisfied(ModifierTreeNode const *parent, uint64 miscValue1, uint64 miscValue2, WorldObject const *ref, Player *referencePlayer) const
virtual ~CriteriaHandler()
virtual void Reset()
virtual bool RequiredAchievementSatisfied(uint32) const
bool RequirementsSatisfied(Criteria const *criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const *ref, Player *referencePlayer) const
std::unordered_map< uint32, Milliseconds > _startedCriteria
CriteriaProgress * GetCriteriaProgress(Criteria const *entry)
virtual void FailCriteria(CriteriaFailEvent failEvent, uint32 asset)
void StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost=Milliseconds::zero())
bool IsCompletedCriteria(Criteria const *criteria, uint64 requiredAmount)
virtual bool CanUpdateCriteriaTree(Criteria const *criteria, CriteriaTree const *tree, Player *referencePlayer) const
bool CanUpdateCriteria(Criteria const *criteria, CriteriaTreeList const *trees, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const *ref, Player *referencePlayer)
CriteriaProgressMap _criteriaProgress
bool ModifierSatisfied(ModifierTreeEntry const *modifier, uint64 miscValue1, uint64 miscValue2, WorldObject const *ref, Player *referencePlayer) const
void RemoveCriteriaProgress(Criteria const *criteria)
virtual void CompletedCriteriaTree(CriteriaTree const *tree, Player *referencePlayer)=0
virtual bool CanCompleteCriteriaTree(CriteriaTree const *tree)
void UpdateTimedCriteria(Milliseconds timeDiff)
bool IsCompletedCriteriaTree(CriteriaTree const *tree)
virtual std::string GetOwnerInfo() const =0
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject const *ref=nullptr, Player *referencePlayer=nullptr)
bool ConditionsSatisfied(Criteria const *criteria, Player *referencePlayer) const
virtual void SendCriteriaUpdate(Criteria const *criteria, CriteriaProgress const *progress, Seconds timeElapsed, bool timedCompleted) const =0
std::unordered_map< int32, CriteriaList > const & GetCriteriaByStartEvent(CriteriaStartEvent startEvent) const
std::unordered_map< uint32, CriteriaTree * > _criteriaTrees
ModifierTreeNode const * GetModifierTree(uint32 modifierTreeId) const
CriteriaList _guildCriteriasByType[size_t(CriteriaType::Count)]
std::unordered_map< uint32, Criteria * > _criteria
static char const * GetCriteriaTypeString(CriteriaType type)
static void WalkCriteriaTree(CriteriaTree const *tree, Func const &func)
std::unordered_map< uint32, CriteriaDataSet > _criteriaDataMap
Criteria const * GetCriteria(uint32 criteriaId) const
CriteriaList const & GetScenarioCriteriaByTypeAndScenario(CriteriaType type, uint32 scenarioId) const
CriteriaList const & GetPlayerCriteriaByType(CriteriaType type, uint32 asset) const
std::unordered_map< uint32, CriteriaTreeList > _criteriaTreeByCriteria
static CriteriaList const EmptyCriteriaList
CriteriaListByAsset _scenarioCriteriasByTypeAndScenarioId[size_t(CriteriaType::Count)]
std::unordered_map< int32, CriteriaList > _criteriasByStartEvent[size_t(CriteriaStartEvent::Count)]
CriteriaTree const * GetCriteriaTree(uint32 criteriaTreeId) const
CriteriaListByAsset _criteriasByAsset[size_t(CriteriaType::Count)]
static CriteriaMgr * Instance()
void LoadCriteriaModifiersTree()
std::unordered_map< int32, CriteriaList > _criteriasByFailEvent[size_t(CriteriaFailEvent::Count)]
std::unordered_map< int32, CriteriaList > const & GetCriteriaByFailEvent(CriteriaFailEvent failEvent) const
CriteriaList _questObjectiveCriteriasByType[size_t(CriteriaType::Count)]
std::unordered_map< uint32, ModifierTreeNode * > _criteriaModifiers
CriteriaList _criteriasByType[size_t(CriteriaType::Count)]
static bool IsInArea(uint32 objectAreaId, uint32 areaId)
Definition: DB2Stores.cpp:1907
std::set< FriendshipRepReactionEntry const *, FriendshipRepReactionEntryComparator > FriendshipRepReactionSet
Definition: DB2Stores.h:406
constexpr bool HasFlag(T flag) const
Definition: EnumFlag.h:106
Class used to access individual fields of database query result.
Definition: Field.h:90
uint8 GetUInt8() const
Definition: Field.cpp:30
std::string GetString() const
Definition: Field.cpp:118
uint32 GetUInt32() const
Definition: Field.cpp:62
std::vector< GameEventData > GameEventDataMap
Definition: GameEventMgr.h:103
Follower const * GetFollower(uint64 dbId) const
Definition: Garrison.cpp:535
uint32 CountFollowers(Predicate &&predicate) const
Definition: Garrison.h:252
GarrisonType GetType() const
Definition: Garrison.h:232
Plot * GetPlot(uint32 garrPlotInstanceId)
Definition: Garrison.cpp:328
bool HasBlueprint(uint32 garrBuildingId) const
Definition: Garrison.h:243
GarrSiteLevelEntry const * GetSiteLevel() const
Definition: Garrison.h:233
std::vector< Plot * > GetPlots()
Definition: Garrison.cpp:318
GroupReference * next()
Definition: Group.h:197
uint32 GetMembersCount() const
Definition: Group.h:327
GroupReference * GetFirstMember()
Definition: Group.h:325
GroupFlags GetGroupFlags() const
Definition: Group.h:329
bool isRaidGroup() const
Definition: Group.cpp:1638
uint32 GetMaxPlayers() const
Definition: Map.cpp:3367
InstanceScript * GetInstanceScript()
Definition: Map.h:870
virtual bool CheckAchievementCriteriaMeet(uint32, Player const *, Unit const *=nullptr, uint32=0)
Definition: Item.h:170
AzeriteItem * ToAzeriteItem()
Definition: Item.h:243
std::vector< int32 > const & GetBonusListIDs() const
Definition: Item.h:229
UF::ArtifactPower const * GetArtifactPower(uint32 artifactPowerId) const
Definition: Item.cpp:2579
uint32 GetTotalUnlockedArtifactPowers() const
Definition: Item.cpp:2632
uint16 GetVisibleAppearanceModId(Player const *owner) const
Definition: Item.cpp:2480
uint32 GetModifier(ItemModifier modifier) const
Definition: Item.cpp:2423
uint32 getSize() const
Definition: LinkedList.h:128
Definition: Map.h:189
bool IsDungeon() const
Definition: Map.cpp:3238
Difficulty GetDifficultyID() const
Definition: Map.h:324
MapEntry const * GetEntry() const
Definition: Map.h:195
uint32 GetPlayersCountExceptGMs() const
Definition: Map.cpp:2681
uint32 GetId() const
Definition: Map.cpp:3228
InstanceMap * ToInstanceMap()
Definition: Map.h:454
WeatherState GetZoneWeather(uint32 zoneId) const
Definition: Map.cpp:3947
uint32 GetInstanceId() const
Definition: Map.h:314
PlayerList const & GetPlayers() const
Definition: Map.h:367
bool IsGarrison() const
Definition: Map.cpp:3350
LowType GetCounter() const
Definition: ObjectGuid.h:293
static ObjectGuid const Empty
Definition: ObjectGuid.h:274
HighGuid GetHigh() const
Definition: ObjectGuid.h:288
static Creature * ToCreature(Object *o)
Definition: Object.h:219
bool IsPlayer() const
Definition: Object.h:212
static Unit * ToUnit(Object *o)
Definition: Object.h:225
bool IsInWorld() const
Definition: Object.h:154
bool IsUnit() const
Definition: Object.h:224
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
bool IsCreature() const
Definition: Object.h:218
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
static bool InDbPhaseShift(WorldObject const *object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId)
ChrSpecialization GetPrimarySpecialization() const
Definition: Player.h:1841
uint32 GetHonorLevel() const
Definition: Player.h:2276
uint32 GetCustomizationChoice(uint32 chrCustomizationOptionId) const
Definition: Player.h:2750
UF::PVPInfo const * GetPvpInfoForBracket(int8 bracket) const
Definition: Player.cpp:22494
uint32 GetCurrencyTrackedQuantity(uint32 id) const
Definition: Player.cpp:7364
int32 GetReputation(uint32 factionentry) const
Definition: Player.cpp:28561
BattlegroundTypeId GetBattlegroundTypeId() const
Definition: Player.h:2397
bool HasPlayerFlagEx(PlayerFlagsEx flags) const
Definition: Player.h:2742
bool CanEnableWarModeInArea() const
Definition: Player.cpp:30060
std::vector< uint32 > GetCompletedAchievementIds() const
Definition: Player.cpp:26746
UF::UpdateField< UF::PlayerData, 0, TYPEID_PLAYER > m_playerData
Definition: Player.h:2863
bool ForEachItem(ItemSearchLocation location, T callback) const
Iterate over each item in the player storage.
Definition: Player.h:1270
uint32 GetTotalPlayedTime() const
Definition: Player.h:1214
RewardedQuestSet const & getRewardedQuests() const
Definition: Player.h:1744
uint8 GetDrunkValue() const
Definition: Player.h:2288
Gender GetNativeGender() const override
Definition: Player.h:1217
bool GetQuestRewardStatus(uint32 quest_id) const
Definition: Player.cpp:16033
bool HasRaceChanged() const
Definition: Player.h:1189
uint16 FindQuestSlot(uint32 quest_id) const
Definition: Player.cpp:16432
bool HasCurrency(uint32 id, uint32 amount) const
Definition: Player.cpp:7413
uint8 GetBankBagSlotCount() const
Definition: Player.h:1378
bool InBattleground() const
Definition: Player.h:2394
Item * GetItemByEntry(uint32 entry, ItemSearchLocation where=ItemSearchLocation::Default) const
Definition: Player.cpp:12589
bool IsMaxLevel() const
Definition: Player.cpp:2365
uint32 GetItemCount(uint32 item, bool inBankAlso=false, Item *skipItem=nullptr) const
Definition: Player.cpp:9511
bool HasTitle(uint32 bitIndex) const
Definition: Player.cpp:26268
uint16 GetPureSkillValue(uint32 skill) const
Definition: Player.cpp:6108
bool HasAchieved(uint32 achievementId) const
Definition: Player.cpp:26751
WorldSession * GetSession() const
Definition: Player.h:2101
int32 GetQuestObjectiveData(uint32 questId, uint32 objectiveId) const
Definition: Player.cpp:16492
uint16 GetBaseSkillValue(uint32 skill) const
Definition: Player.cpp:6094
PlayerSpellMap const & GetSpellMap() const
Definition: Player.h:1901
uint16 GetPureMaxSkillValue(uint32 skill) const
Definition: Player.cpp:6082
bool HasExploredZone(uint32 areaId) const
Definition: Player.cpp:6437
bool HasPlayerLocalFlag(PlayerLocalFlags flags) const
Definition: Player.h:2832
Battleground * GetBattleground() const
Definition: Player.cpp:24976
ObjectGuid::LowType GetGuildId() const
Definition: Player.h:1993
uint32 GetFreeInventorySlotCount(EnumFlag< ItemSearchLocation > location=ItemSearchLocation::Inventory) const
Definition: Player.cpp:9426
bool IsGameMaster() const
Definition: Player.h:1178
uint32 GetRBGPersonalRating() const
Definition: Player.h:2008
uint32 GetAchievementPoints() const
Definition: Player.cpp:26741
bool CanTakeQuest(Quest const *quest, bool msg) const
Definition: Player.cpp:14620
bool IsQuestObjectiveComplete(uint16 slot, Quest const *quest, QuestObjective const &objective) const
Definition: Player.cpp:17090
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:16050
UF::UpdateField< UF::ActivePlayerData, 0, TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition: Player.h:2864
Garrison * GetGarrison() const
Definition: Player.h:2710
bool HasLevelBoosted() const
Definition: Player.h:1193
uint64 GetMoney() const
Definition: Player.h:1738
ReputationRank GetReputationRank(uint32 faction_id) const
Definition: Player.cpp:6497
bool HasSpell(uint32 spell) const override
Definition: Player.cpp:3792
Group * GetGroup(Optional< uint8 > partyIndex)
Definition: Player.h:2606
bool HasPlayerFlag(PlayerFlags flags) const
Definition: Player.h:2737
size_t GetRewardedQuestCount() const
Definition: Player.h:1747
uint32 GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const
Definition: Player.cpp:23264
Item * GetItemByGuid(ObjectGuid guid) const
Definition: Player.cpp:9566
bool HasBeenGrantedLevelsFromRaF() const
Definition: Player.h:1191
ChrSpecializationEntry const * GetPrimarySpecializationEntry() const
Definition: Player.cpp:29827
uint32 GetArenaTeamId(uint8) const
Definition: Player.h:2004
ReputationMgr & GetReputationMgr()
Definition: Player.h:2251
static DrunkenState GetDrunkenstateByValue(uint8 value)
Definition: Player.cpp:876
bool IsLockedToDungeonEncounter(uint32 dungeonEncounterId) const
Definition: Player.cpp:21399
uint32 GetCurrencyQuantity(uint32 id) const
Definition: Player.cpp:7346
bool IsQuestRewarded(uint32 quest_id) const
Definition: Player.cpp:24137
Team GetTeam() const
Definition: Player.h:2235
InventoryResult CanUseItem(Item *pItem, bool not_loading=true) const
Definition: Player.cpp:11381
int32 GetZoneOrSort() const
Definition: QuestDef.h:591
uint32 GetQuestInfoID() const
Definition: QuestDef.h:593
uint8 GetHonoredFactionCount() const
Definition: ReputationMgr.h:85
uint8 GetReveredFactionCount() const
Definition: ReputationMgr.h:86
int32 GetReputation(uint32 faction_id) const
int32 GetParagonLevel(uint32 paragonFactionId) const
uint8 GetExaltedFactionCount() const
Definition: ReputationMgr.h:87
uint8 GetVisibleFactionCount() const
Definition: ReputationMgr.h:84
ScenarioEntry const * GetEntry() const
Definition: Scenario.cpp:138
ScenarioStepEntry const * GetLastStep() const
Definition: Scenario.cpp:291
ScenarioStepEntry const * GetStep() const
Definition: Scenario.h:73
AuraType ApplyAuraName
Definition: SpellInfo.h:219
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition: SpellInfo.h:577
std::vector< SpellEffectInfo > const & GetEffects() const
Definition: SpellInfo.h:576
bool HasLabel(uint32 labelId) const
Definition: SpellInfo.cpp:4937
size_t GetThreatListSize() const
Definition: Unit.h:627
bool HealthAbovePct(int32 pct) const
Definition: Unit.h:782
float GetHealthPct() const
Definition: Unit.h:784
bool CanHaveThreatList() const
====================== THREAT & COMBAT ====================
Definition: Unit.h:1015
ThreatManager & GetThreatManager()
Definition: Unit.h:1063
UF::UpdateField< UF::UnitData, 0, TYPEID_UNIT > m_unitData
Definition: Unit.h:1814
uint8 GetClass() const
Definition: Unit.h:752
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition: Unit.cpp:4464
bool IsAlive() const
Definition: Unit.h:1164
Gender GetGender() const
Definition: Unit.h:755
uint32 GetCreatureType() const
Definition: Unit.cpp:8880
uint32 GetDisplayId() const
Definition: Unit.h:1567
uint32 GetAuraCount(uint32 spellId) const
Definition: Unit.cpp:4648
bool HasAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid caster=ObjectGuid::Empty) const
Definition: Unit.cpp:4634
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4560
uint64 GetHealth() const
Definition: Unit.h:776
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
Definition: Unit.cpp:5961
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4674
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
bool IsFlying() const
Definition: Unit.h:1735
ObjectGuid GetTarget() const
Definition: Unit.h:1759
uint8 GetLevel() const
Definition: Unit.h:746
uint8 GetRace() const
Definition: Unit.h:749
bool isDead() const
Definition: Unit.h:1166
constexpr uint32 GetMapId() const
Definition: Position.h:201
Map * GetMap() const
Definition: Object.h:624
Scenario * GetScenario() const
Definition: Object.cpp:2016
virtual uint8 GetLevelForTarget(WorldObject const *) const
Definition: Object.h:598
bool IsHostileTo(WorldObject const *target) const
Definition: Object.cpp:2860
uint32 GetInstanceId() const
Definition: Object.h:521
std::string const & GetName() const
Definition: Object.h:555
uint32 GetAreaId() const
Definition: Object.h:546
uint32 GetZoneId() const
Definition: Object.h:545
bool CanAccessAlliedRaces() const
uint32 GetRecruiterId() const
bool HasPermission(uint32 permissionId)
uint32 GetAccountId() const
uint8 GetAccountExpansion() const
CollectionMgr * GetCollectionMgr() const
uint8 GetExpansion() const
BattlePets::BattlePetMgr * GetBattlePetMgr() const
void SetPackedTime(uint32 packedTime)
Definition: WowTime.cpp:34
#define sWorld
Definition: World.h:931
WeatherState
Definition: Weather.h:46
Realm realm
Definition: World.cpp:3966
@ CONFIG_ARENA_SEASON_ID
Definition: World.h:347
@ CONFIG_EXPANSION
Definition: World.h:308
@ CONFIG_ARENA_SEASON_IN_PROGRESS
Definition: World.h:142
static constexpr uint16 MAX_BATTLE_PET_LEVEL
Definition: BattlePetMgr.h:41
bool IsDisabledFor(DisableType type, uint32 entry, WorldObject const *ref, uint8 flags)
Definition: DisableMgr.cpp:285
WowTime const * GetWowTime()
Definition: GameTime.cpp:97
time_t GetGameTime()
Definition: GameTime.cpp:44
std::vector< int32 > GetAllBonusListsForTree(uint32 itemBonusTreeId)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition: MapUtils.h:29
TC_PROTO_API ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::FieldOptions, ::google::protobuf::internal::MessageTypeTraits< ::bgs::protocol::FieldRestriction >, 11, false > valid
@ RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS
Definition: RBAC.h:61
EnumFlag< BattlemasterListFlags > GetFlags() const
Definition: DB2Structure.h:519
CreatureFamily family
Definition: CreatureData.h:507
bool Meets(Player const *source, WorldObject const *target, uint32 miscValue1=0, uint32 miscValue2=0) const
std::vector< CriteriaData > _storage
void SetCriteriaId(uint32 id)
void Add(CriteriaData const &data)
struct CriteriaData::@9::@23 EquippedItem
struct CriteriaData::@9::@27 ItemQuality
CriteriaDataType DataType
struct CriteriaData::@9::@12 ClassRace
struct CriteriaData::@9::@21 Holiday
struct CriteriaData::@9::@16 Level
struct CriteriaData::@9::@26 GameEvent
struct CriteriaData::@9::@18 MapPlayers
struct CriteriaData::@9::@13 Health
bool IsValid(Criteria const *criteria)
bool Meets(uint32 criteriaId, Player const *source, WorldObject const *target, uint32 miscValue1=0, uint32 miscValue2=0) const
struct CriteriaData::@9::@20 Drunk
struct CriteriaData::@9::@25 KnownTitle
int16 EligibilityWorldStateID
union CriteriaEntry::AssetNameAlias Asset
int8 EligibilityWorldStateValue
std::time_t Date
ObjectGuid PlayerGUID
EnumFlag< CriteriaTreeFlags > GetFlags() const
ScenarioStepEntry const * ScenarioStep
::Criteria const * Criteria
std::vector< CriteriaTree const * > Children
CriteriaTreeEntry const * Entry
::QuestObjective const * QuestObjective
AchievementEntry const * Achievement
CriteriaEntry const * Entry
uint32 FlagsCu
ModifierTreeNode const * Modifier
uint16 ParagonFactionID
bool CanActivate() const
Definition: Garrison.cpp:835
Optional< WorldPackets::Garrison::GarrisonBuildingInfo > PacketInfo
Definition: Garrison.h:192
WorldPackets::Garrison::GarrisonFollower PacketInfo
Definition: Garrison.h:214
bool HasAbility(uint32 garrAbilityId) const
Definition: Garrison.cpp:852
uint32 GetItemLevel() const
Definition: Garrison.cpp:847
Building BuildingInfo
Definition: Garrison.h:206
uint32 GetBaseItemLevel() const
Definition: ItemTemplate.h:789
uint32 GetQuality() const
Definition: ItemTemplate.h:779
uint32 GetSubClass() const
Definition: ItemTemplate.h:778
uint32 GetClass() const
Definition: ItemTemplate.h:777
int16 CosmeticParentMapID
int8 InstanceType
uint8 ExpansionID
uint32 ID
ModifierTreeEntry const * Entry
std::vector< ModifierTreeNode const * > Children
constexpr float GetPositionZ() const
Definition: Position.h:78
int32 ObjectID
Definition: QuestDef.h:449
uint32 QuestID
Definition: QuestDef.h:446
uint32 Build
Definition: Realm.h:83
std::vector< ChrCustomizationDisplayInfoEntry const * > Displays
Definition: DB2Stores.h:320
std::vector< ChrCustomizationChoiceEntry const * > const * Choices
Definition: DB2Stores.h:319
constexpr bool HasRace(uint8 raceId) const
Definition: RaceMask.h:88
UpdateField< uint32, 0, 11 > PvpTierID
Definition: UpdateFields.h:584
UpdateField< uint32, 0, 12 > WeeklyBestWinPvpTierID
Definition: UpdateFields.h:585
UpdateField< int32, 4, 6 > SkillLineID
Definition: UpdateFields.h:737
UpdateField< int32, 4, 5 > Type
Definition: UpdateFields.h:736
UpdateField< int32, 8, 9 > CombatConfigFlags
Definition: UpdateFields.h:739
DynamicUpdateField< UF::TraitEntry, 0, 1 > Entries
Definition: UpdateFields.h:733
UpdateField< int32, 0, 2 > ID
Definition: UpdateFields.h:734
int32 TraitNodeEntryID
Definition: UpdateFields.h:721
UpdateField< uint16, 0, 4 > ItemAppearanceModID
Definition: UpdateFields.h:241
UpdateField< int32, 0, 1 > ItemID
Definition: UpdateFields.h:238
std::array< uint32, MAX_WORLD_MAP_OVERLAY_AREA_IDX > AreaID