TrinityCore
Loading...
Searching...
No Matches
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 "BattlePetMgr.h"
22#include "Battleground.h"
23#include "CollectionMgr.h"
24#include "Creature.h"
25#include "DB2Stores.h"
26#include "DatabaseEnv.h"
27#include "DisableMgr.h"
28#include "GameEventMgr.h"
29#include "GameTime.h"
30#include "Garrison.h"
31#include "Group.h"
32#include "InstanceScript.h"
33#include "Item.h"
34#include "ItemBonusMgr.h"
35#include "LanguageMgr.h"
36#include "Log.h"
37#include "Map.h"
38#include "MapManager.h"
39#include "MapUtils.h"
40#include "ObjectMgr.h"
41#include "PhasingHandler.h"
42#include "Player.h"
43#include "QuestMgr.h"
44#include "RBAC.h"
45#include "RealmList.h"
46#include "ReputationMgr.h"
47#include "Scenario.h"
48#include "ScriptMgr.h"
49#include "SpellAuras.h"
50#include "SpellInfo.h"
51#include "SpellMgr.h"
52#include "World.h"
53#include "WorldSession.h"
54#include "WorldStateMgr.h"
55#include "WowTime.h"
56
57bool CriteriaData::IsValid(Criteria const* criteria)
58{
60 {
61 TC_LOG_ERROR("sql.sql", "Table `criteria_data` for criteria (Entry: {}) contains a wrong data type ({}), ignored.", criteria->ID, DataType);
62 return false;
63 }
64 switch (CriteriaType(criteria->Entry->Type))
65 {
70 case CriteriaType::CompleteQuest: // only hardcoded list
85 case CriteriaType::CompleteDailyQuest: // only Children's Week achievements
86 case CriteriaType::UseItem: // only Children's Week achievements
92 break;
93 default:
95 {
96 TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains data for a non-supported criteria type (Entry: {} Type: {}), ignored.", criteria->ID, criteria->Entry->Type);
97 return false;
98 }
99 break;
100 }
101
102 switch (DataType)
103 {
106 return true;
109 {
110 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.",
111 criteria->ID, criteria->Entry->Type, DataType, Creature.Id);
112 return false;
113 }
114 return true;
116 if (!ClassRace.Class && !ClassRace.Race)
117 {
118 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.",
119 criteria->ID, criteria->Entry->Type, DataType);
120 return false;
121 }
122 if (ClassRace.Class && ((1 << (ClassRace.Class-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
123 {
124 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.",
125 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Class);
126 return false;
127 }
129 {
130 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.",
131 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Race);
132 return false;
133 }
134 return true;
136 if (Health.Percent < 1 || Health.Percent > 100)
137 {
138 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.",
139 criteria->ID, criteria->Entry->Type, DataType, Health.Percent);
140 return false;
141 }
142 return true;
145 {
146 SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(Aura.SpellId, DIFFICULTY_NONE);
147 if (!spellEntry)
148 {
149 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type {} ({}) contains a wrong spell id in value1 ({}), ignored.",
150 criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId);
151 return false;
152 }
153 if (spellEntry->GetEffects().size() <= Aura.EffectIndex)
154 {
155 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type {} ({}) contains a wrong spell effect index in value2 ({}), ignored.",
156 criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.EffectIndex);
157 return false;
158 }
159 if (!spellEntry->GetEffect(SpellEffIndex(Aura.EffectIndex)).ApplyAuraName)
160 {
161 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type {} ({}) contains a non-aura spell effect (ID: {} Effect: {}), ignored.",
162 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);
163 return false;
164 }
165 return true;
166 }
168 if (Value.ComparisonType >= COMP_TYPE_MAX)
169 {
170 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_VALUE ({}) contains a wrong ComparisionType in value2 ({}), ignored.",
171 criteria->ID, criteria->Entry->Type, DataType, Value.ComparisonType);
172 return false;
173 }
174 return true;
176 if (Level.Min > STRONG_MAX_LEVEL)
177 {
178 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.",
179 criteria->ID, criteria->Entry->Type, DataType, Level.Min);
180 return false;
181 }
182 return true;
184 if (Gender.Gender > GENDER_NONE)
185 {
186 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.",
187 criteria->ID, criteria->Entry->Type, DataType, Gender.Gender);
188 return false;
189 }
190 return true;
192 if (!ScriptId)
193 {
194 TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: {} Type: {}) for data type CRITERIA_DATA_TYPE_SCRIPT ({}) does not have a ScriptName set, ignored.",
195 criteria->ID, criteria->Entry->Type, DataType);
196 return false;
197 }
198 return true;
200 if (MapPlayers.MaxCount <= 0)
201 {
202 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.",
203 criteria->ID, criteria->Entry->Type, DataType, MapPlayers.MaxCount);
204 return false;
205 }
206 return true;
208 if (Team.Team != ALLIANCE && Team.Team != HORDE)
209 {
210 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.",
211 criteria->ID, criteria->Entry->Type, DataType, Team.Team);
212 return false;
213 }
214 return true;
216 if (Drunk.State >= MAX_DRUNKEN)
217 {
218 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.",
219 criteria->ID, criteria->Entry->Type, DataType, Drunk.State);
220 return false;
221 }
222 return true;
224 if (!sHolidaysStore.LookupEntry(Holiday.Id))
225 {
226 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.",
227 criteria->ID, criteria->Entry->Type, DataType, Holiday.Id);
228 return false;
229 }
230 return true;
232 {
233 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
234 if (GameEvent.Id < 1 || GameEvent.Id >= events.size())
235 {
236 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.",
237 criteria->ID, criteria->Entry->Type, DataType, GameEvent.Id);
238 return false;
239 }
240 return true;
241 }
243 return true; // not check correctness node indexes
245 if (EquippedItem.Quality >= MAX_ITEM_QUALITY)
246 {
247 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.",
248 criteria->ID, criteria->Entry->Type, DataType, EquippedItem.Quality);
249 return false;
250 }
251 return true;
253 if (!sMapStore.LookupEntry(Map.Id))
254 {
255 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.",
256 criteria->ID, criteria->Entry->Type, DataType, Map.Id);
257 }
258 return true;
260 if (!ClassRace.Class && !ClassRace.Race)
261 {
262 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.",
263 criteria->ID, criteria->Entry->Type, DataType);
264 return false;
265 }
266 if (ClassRace.Class && ((1 << (ClassRace.Class-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
267 {
268 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.",
269 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Class);
270 return false;
271 }
273 {
274 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.",
275 criteria->ID, criteria->Entry->Type, DataType, ClassRace.Race);
276 return false;
277 }
278 return true;
280 if (!sCharTitlesStore.LookupEntry(KnownTitle.Id))
281 {
282 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.",
283 criteria->ID, criteria->Entry->Type, DataType, KnownTitle.Id);
284 return false;
285 }
286 return true;
288 if (ItemQuality.Quality >= MAX_ITEM_QUALITY)
289 {
290 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.",
291 criteria->ID, criteria->Entry->Type, DataType, ItemQuality.Quality);
292 return false;
293 }
294 return true;
295 default:
296 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);
297 return false;
298 }
299}
300
301bool CriteriaData::Meets(uint32 criteriaId, Player const* source, WorldObject const* target, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/) const
302{
303 switch (DataType)
304 {
306 return true;
308 if (!target || target->GetTypeId() != TYPEID_UNIT)
309 return false;
310 return target->GetEntry() == Creature.Id;
312 if (!target || target->GetTypeId() != TYPEID_PLAYER)
313 return false;
314 if (ClassRace.Class && ClassRace.Class != target->ToPlayer()->GetClass())
315 return false;
316 if (ClassRace.Race && ClassRace.Race != target->ToPlayer()->GetRace())
317 return false;
318 return true;
320 if (source->GetTypeId() != TYPEID_PLAYER)
321 return false;
322 if (ClassRace.Class && ClassRace.Class != source->ToPlayer()->GetClass())
323 return false;
324 if (ClassRace.Race && ClassRace.Race != source->ToPlayer()->GetRace())
325 return false;
326 return true;
328 if (!target || target->GetTypeId() != TYPEID_PLAYER)
329 return false;
330 return !target->ToPlayer()->HealthAbovePct(Health.Percent);
332 return source->HasAuraEffect(Aura.SpellId, uint8(Aura.EffectIndex));
334 {
335 if (!target)
336 return false;
337 Unit const* unitTarget = target->ToUnit();
338 if (!unitTarget)
339 return false;
340 return unitTarget->HasAuraEffect(Aura.SpellId, uint8(Aura.EffectIndex));
341 }
343 return CompareValues(ComparisionType(Value.ComparisonType), miscValue1, Value.Value);
345 if (!target)
346 return false;
347 return target->GetLevelForTarget(source) >= Level.Min;
349 {
350 if (!target)
351 return false;
352 Unit const* unitTarget = target->ToUnit();
353 if (!unitTarget)
354 return false;
355 return unitTarget->GetGender() == static_cast<::Gender>(Gender.Gender);
356 }
358 {
359 Unit const* unitTarget = nullptr;
360 if (target)
361 unitTarget = target->ToUnit();
362 return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(unitTarget));
363 }
365 return source->GetMap()->GetPlayersCountExceptGMs() <= MapPlayers.MaxCount;
367 if (!target || target->GetTypeId() != TYPEID_PLAYER)
368 return false;
369 return target->ToPlayer()->GetTeam() == ::Team(Team.Team);
375 return IsEventActive(uint16(GameEvent.Id));
377 {
378 Battleground* bg = source->GetBattleground();
379 if (!bg)
380 return false;
381
382 uint32 score = bg->GetTeamScore(bg->GetPlayerTeam(source->GetGUID()) == ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE);
383 return score >= BattlegroundScore.Min && score <= BattlegroundScore.Max;
384 }
386 {
387 if (!source->IsInWorld())
388 return false;
389 class Map* map = source->GetMap();
390 if (!map->IsDungeon())
391 {
392 TC_LOG_ERROR("criteria", "Criteria system call CRITERIA_DATA_TYPE_INSTANCE_SCRIPT ({}) for criteria {} in a non-dungeon/non-raid map {}",
393 DataType, criteriaId, map->GetId());
394 return false;
395 }
396 InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript();
397 if (!instance)
398 {
399 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.",
400 DataType, criteriaId, map->GetId());
401 return false;
402 }
403
404 Unit const* unitTarget = nullptr;
405 if (target)
406 unitTarget = target->ToUnit();
407 return instance->CheckAchievementCriteriaMeet(criteriaId, source, unitTarget, miscValue1);
408 }
410 {
411 Criteria const* entry = ASSERT_NOTNULL(sCriteriaMgr->GetCriteria(criteriaId));
412
413 uint32 itemId = (CriteriaType(entry->Entry->Type) == CriteriaType::EquipItemInSlot ? miscValue2 : miscValue1);
414 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId);
415 if (!itemTemplate)
416 return false;
417 return itemTemplate->GetBaseItemLevel() >= EquippedItem.ItemLevel && itemTemplate->GetQuality() >= EquippedItem.Quality;
418 }
420 return source->GetMapId() == Map.Id;
422 {
423 if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(KnownTitle.Id))
424 return source && source->HasTitle(titleInfo->MaskID);
425
426 return false;
427 }
429 {
430 ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
431 if (!pProto)
432 return false;
433 return pProto->GetQuality() == ItemQuality.Quality;
434 }
435 default:
436 break;
437 }
438 return false;
439}
440
441bool CriteriaDataSet::Meets(Player const* source, WorldObject const* target, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/) const
442{
443 for (CriteriaData const& criteriadata : _storage)
444 if (!criteriadata.Meets(_criteriaId, source, target, miscValue1, miscValue2))
445 return false;
446
447 return true;
448}
449
451
453
455{
456 for (std::pair<uint32 const, CriteriaProgress> const& criteriaprogress : _criteriaProgress)
457 SendCriteriaProgressRemoved(criteriaprogress.first);
458
459 _criteriaProgress.clear();
460}
461
465void CriteriaHandler::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, WorldObject const* ref /*= nullptr*/, Player* referencePlayer /*= nullptr*/)
466{
467 if (type >= CriteriaType::Count)
468 {
469 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: Wrong criteria type {}", uint32(type));
470 return;
471 }
472
473 if (!referencePlayer)
474 {
475 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: Player is NULL! Cant update criteria");
476 return;
477 }
478
479 // Disable for GameMasters with GM-mode enabled or for players that don't have the related RBAC permission
480 if (referencePlayer->IsGameMaster() || referencePlayer->GetSession()->HasPermission(rbac::RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS))
481 {
482 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: [Player {} {}] {}, {} ({}), {}, {}, {}",
483 referencePlayer->GetName(), referencePlayer->IsGameMaster() ? "GM mode on" : "disallowed by RBAC",
484 GetOwnerInfo(), CriteriaMgr::GetCriteriaTypeString(type), uint32(type), miscValue1, miscValue2, miscValue3);
485 return;
486 }
487
488 TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria({}, {}, {}, {}, {}) {}",
489 CriteriaMgr::GetCriteriaTypeString(type), uint32(type), miscValue1, miscValue2, miscValue3, GetOwnerInfo());
490
491 CriteriaList const& criteriaList = GetCriteriaByType(type, uint32(miscValue1));
492 for (Criteria const* criteria : criteriaList)
493 UpdateCriteria(criteria, miscValue1, miscValue2, miscValue3, ref, referencePlayer);
494}
495
496void CriteriaHandler::UpdateCriteria(Criteria const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const* ref, Player* referencePlayer)
497{
498 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
499 if (!CanUpdateCriteria(criteria, trees, miscValue1, miscValue2, miscValue3, ref, referencePlayer))
500 return;
501
502 // requirements not found in the dbc
503 if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
504 if (!data->Meets(referencePlayer, ref, uint32(miscValue1), uint32(miscValue2)))
505 return;
506
507 switch (CriteriaType(criteria->Entry->Type))
508 {
509 // std. case: increment at 1
514 case CriteriaType::AuctionsWon: /* FIXME: for online player only currently */
549 case CriteriaType::WinArena: // This also behaves like CriteriaType::WinAnyRankedArena
572 SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
573 break;
574 // std case: increment at miscValue1
582 case CriteriaType::MoneyEarnedFromAuctions:/* FIXME: for online player only currently */
592 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
593 break;
600 SetCriteriaProgress(criteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
601 break;
602 // std case: high value at miscValue1
604 case CriteriaType::HighestAuctionSale: /* FIXME: for online player only currently */
611 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
612 break;
614 SetCriteriaProgress(criteria, miscValue2, referencePlayer, PROGRESS_HIGHEST);
615 break;
617 SetCriteriaProgress(criteria, referencePlayer->GetLevel(), referencePlayer);
618 break;
620 if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(criteria->Entry->Asset.SkillID))
621 SetCriteriaProgress(criteria, skillvalue, referencePlayer);
622 break;
624 if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(criteria->Entry->Asset.SkillID))
625 SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer);
626 break;
628 SetCriteriaProgress(criteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
629 break;
631 {
632 time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
633 CriteriaProgress *progress = GetCriteriaProgress(criteria);
634
635 if (!miscValue1) // Login case.
636 {
637 // reset if player missed one day.
638 if (progress && progress->Date < (nextDailyResetTime - 2 * DAY))
639 SetCriteriaProgress(criteria, 0, referencePlayer, PROGRESS_SET);
640 return;
641 }
642
643 ProgressType progressType;
644 if (!progress)
645 // 1st time. Start count.
646 progressType = PROGRESS_SET;
647 else if (progress->Date < (nextDailyResetTime - 2 * DAY))
648 // last progress is older than 2 days. Player missed 1 day => Restart count.
649 progressType = PROGRESS_SET;
650 else if (progress->Date < (nextDailyResetTime - DAY))
651 // last progress is between 1 and 2 days. => 1st time of the day.
652 progressType = PROGRESS_ACCUMULATE;
653 else
654 // last progress is within the day before the reset => Already counted today.
655 return;
656
657 SetCriteriaProgress(criteria, 1, referencePlayer, progressType);
658 break;
659 }
661 {
662 if (miscValue1)
663 {
664 SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
665 }
666 else // login case
667 {
668 uint32 counter = 0;
669
670 RewardedQuestSet const& rewQuests = referencePlayer->getRewardedQuests();
671 for (uint32 rewQuest : rewQuests)
672 {
673 Quest const* quest = sObjectMgr->GetQuestTemplate(rewQuest);
674 if (quest && quest->GetZoneOrSort() >= 0 && quest->GetZoneOrSort() == criteria->Entry->Asset.ZoneID)
675 ++counter;
676 }
677 SetCriteriaProgress(criteria, counter, referencePlayer, PROGRESS_HIGHEST);
678 }
679 break;
680 }
682 // miscValue1 is the ingame fallheight*100 as stored in dbc
683 SetCriteriaProgress(criteria, miscValue1, referencePlayer);
684 break;
703 SetCriteriaProgress(criteria, 1, referencePlayer);
704 break;
706 SetCriteriaProgress(criteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
707 break;
709 {
710 int32 reputation = referencePlayer->GetReputationMgr().GetReputation(criteria->Entry->Asset.FactionID);
711 if (reputation > 0)
712 SetCriteriaProgress(criteria, reputation, referencePlayer);
713 break;
714 }
716 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
717 break;
720 {
721 uint32 spellCount = 0;
722 for (auto& [spellId, _] : referencePlayer->GetSpellMap())
723 {
724 SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
725 for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter)
726 {
727 if (skillIter->second->SkillLine == uint32(criteria->Entry->Asset.SkillID))
728 {
729 // do not add couter twice if by any chance skill is listed twice in dbc (eg. skill 777 and spell 22717)
730 ++spellCount;
731 break;
732 }
733 }
734 }
735 SetCriteriaProgress(criteria, spellCount, referencePlayer);
736 break;
737 }
739 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
740 break;
742 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
743 break;
745 SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
746 break;
748 SetCriteriaProgress(criteria, referencePlayer->m_activePlayerData->LifetimeHonorableKills, referencePlayer);
749 break;
751 SetCriteriaProgress(criteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
752 break;
754 if (!miscValue1)
755 return;
756 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
757 break;
759 {
760 uint32 reqTeamType = criteria->Entry->Asset.TeamType;
761
762 if (miscValue1)
763 {
764 if (miscValue2 != reqTeamType)
765 return;
766
767 SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
768 }
769 else // login case
770 {
771 for (uint8 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
772 {
773 uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
774 if (!teamId)
775 continue;
776
777 ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
778 if (!team || team->GetType() != reqTeamType)
779 continue;
780
781 if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
782 {
783 SetCriteriaProgress(criteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
784 break;
785 }
786 }
787 }
788 break;
789 }
791 SetCriteriaProgress(criteria, referencePlayer->GetSession()->GetBattlePetMgr()->GetPetUniqueSpeciesCount(), referencePlayer);
792 break;
794 SetCriteriaProgress(criteria, miscValue1, referencePlayer);
795 break;
797 switch (BankType(criteria->Entry->Asset.BankType))
798 {
800 SetCriteriaProgress(criteria, referencePlayer->GetCharacterBankTabCount(), referencePlayer);
801 break;
803 SetCriteriaProgress(criteria, referencePlayer->GetAccountBankTabCount(), referencePlayer);
804 break;
805 default:
806 break;
807 }
808 break;
809 // FIXME: not triggered in code as result, need to implement
877 default:
878 break; // Not implemented yet :(
879 }
880
881 for (CriteriaTree const* tree : *trees)
882 {
883 if (IsCompletedCriteriaTree(tree))
884 CompletedCriteriaTree(tree, referencePlayer);
885
886 AfterCriteriaTreeUpdate(tree, referencePlayer);
887 }
888}
889
891{
892 for (auto itr = _startedCriteria.begin(); itr != _startedCriteria.end();)
893 {
894 // Time is up, remove timer and reset progress
895 if (itr->second <= timeDiff)
896 {
897 RemoveCriteriaProgress(sCriteriaMgr->GetCriteria(itr->first));
898
899 itr = _startedCriteria.erase(itr);
900 }
901 else
902 {
903 itr->second -= timeDiff;
904 ++itr;
905 }
906 }
907}
908
909void CriteriaHandler::StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost /*= Milliseconds::zero()*/)
910{
911 CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByStartEvent(startEvent, entry);
912 if (!criteriaList)
913 return;
914
915 for (Criteria const* criteria : *criteriaList)
916 {
917 Milliseconds timeLimit = Milliseconds::max(); // this value is for criteria that have a start event requirement but no time limit
918 if (criteria->Entry->StartTimer)
919 timeLimit = Seconds(criteria->Entry->StartTimer);
920
921 timeLimit -= timeLost;
922
923 if (timeLimit <= Milliseconds::zero())
924 continue;
925
926 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
927 bool canStart = std::any_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
928 {
929 return !IsCompletedCriteriaTree(tree);
930 });
931
932 if (!canStart)
933 continue;
934
935 auto [itr, isNew] = _startedCriteria.try_emplace(criteria->ID, timeLimit);
936 if (!isNew)
937 {
938 if (!criteria->Entry->GetFlags().HasFlag(CriteriaFlags::ResetOnStart))
939 continue;
940
941 itr->second = timeLimit;
942 }
943
944 // and at client too
945 SetCriteriaProgress(criteria, 0, nullptr, PROGRESS_SET);
946 }
947}
948
950{
951 CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByFailEvent(failEvent, asset);
952 if (!criteriaList)
953 return;
954
955 for (Criteria const* criteria : *criteriaList)
956 {
957 _startedCriteria.erase(criteria->ID);
958
959 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
960 bool allTreesFullyComplete = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
961 {
962 CriteriaTree const* root = tree;
963 if (CriteriaTree const* parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent))
964 {
965 do
966 {
967 root = parent;
968 parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent);
969 } while (parent);
970 }
971
972 return IsCompletedCriteriaTree(root);
973 });
974
975 if (allTreesFullyComplete)
976 continue;
977
978 RemoveCriteriaProgress(criteria);
979 }
980}
981
983{
984 auto iter = _criteriaProgress.find(entry->ID);
985 if (iter == _criteriaProgress.end())
986 return nullptr;
987
988 return &iter->second;
989}
990
991void CriteriaHandler::SetCriteriaProgress(Criteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType progressType)
992{
993 TC_LOG_DEBUG("criteria", "CriteriaHandler::SetCriteriaProgress({}, {}) for {}", criteria->ID, changeValue, GetOwnerInfo());
994
995 CriteriaProgress* progress = GetCriteriaProgress(criteria);
996 if (!progress)
997 {
998 // not create record for 0 counter but allow it for timed criteria
999 // we will need to send 0 progress to client to start the timer
1000 if (changeValue == 0 && !criteria->Entry->StartTimer)
1001 return;
1002
1003 progress = &_criteriaProgress[criteria->ID];
1004 progress->Counter = changeValue;
1005 }
1006 else
1007 {
1008 uint64 newValue = 0;
1009 switch (progressType)
1010 {
1011 case PROGRESS_SET:
1012 newValue = changeValue;
1013 break;
1015 {
1016 // avoid overflow
1017 uint64 max_value = std::numeric_limits<uint64>::max();
1018 newValue = max_value - progress->Counter > changeValue ? progress->Counter + changeValue : max_value;
1019 break;
1020 }
1021 case PROGRESS_HIGHEST:
1022 newValue = progress->Counter < changeValue ? changeValue : progress->Counter;
1023 break;
1024 }
1025
1026 // not update (not mark as changed) if counter will have same value
1027 if (progress->Counter == newValue && !criteria->Entry->StartTimer)
1028 return;
1029
1030 progress->Counter = newValue;
1031 }
1032
1033 progress->Changed = true;
1034 progress->Date = GameTime::GetGameTime(); // set the date to the latest update.
1035 progress->PlayerGUID = referencePlayer ? referencePlayer->GetGUID() : ObjectGuid::Empty;
1036
1037 Seconds timeElapsed = Seconds::zero();
1038
1039 if (criteria->Entry->StartTimer)
1040 {
1041 auto startedItr = _startedCriteria.find(criteria->ID);
1042 if (startedItr != _startedCriteria.end())
1043 {
1044 // Client expects this in packet
1045 timeElapsed = duration_cast<Seconds>(Seconds(criteria->Entry->StartTimer) - startedItr->second);
1046
1047 // Remove the timer, we wont need it anymore
1048 CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
1049
1050 bool allTreesCompleted = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
1051 {
1052 return IsCompletedCriteriaTree(tree);
1053 });
1054
1055 if (allTreesCompleted)
1056 _startedCriteria.erase(startedItr);
1057 }
1058 }
1059
1060 SendCriteriaUpdate(criteria, progress, timeElapsed, true);
1061}
1062
1064{
1065 if (!criteria)
1066 return;
1067
1068 auto criteriaProgress = _criteriaProgress.find(criteria->ID);
1069 if (criteriaProgress == _criteriaProgress.end())
1070 return;
1071
1073
1074 criteriaProgress->second.Counter = 0;
1075 criteriaProgress->second.Changed = true;
1076}
1077
1079{
1080 if (!CanCompleteCriteriaTree(tree))
1081 return false;
1082
1083 uint64 requiredCount = tree->Entry->Amount;
1084 switch (CriteriaTreeOperator(tree->Entry->Operator))
1085 {
1087 return tree->Criteria && IsCompletedCriteria(tree->Criteria, requiredCount);
1089 return !tree->Criteria || !IsCompletedCriteria(tree->Criteria, requiredCount);
1091 for (CriteriaTree const* node : tree->Children)
1092 if (!IsCompletedCriteriaTree(node))
1093 return false;
1094 return true;
1096 {
1097 uint64 progress = 0;
1098 CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree)
1099 {
1100 if (criteriaTree->Criteria)
1101 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria))
1102 progress += criteriaProgress->Counter;
1103 });
1104 return progress >= requiredCount;
1105 }
1107 {
1108 uint64 progress = 0;
1109 CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree)
1110 {
1111 if (criteriaTree->Criteria)
1112 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria))
1113 if (criteriaProgress->Counter > progress)
1114 progress = criteriaProgress->Counter;
1115 });
1116 return progress >= requiredCount;
1117 }
1119 {
1120 uint64 progress = 0;
1121 for (CriteriaTree const* node : tree->Children)
1122 if (node->Criteria)
1123 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(node->Criteria))
1124 if (criteriaProgress->Counter >= 1)
1125 if (++progress >= requiredCount)
1126 return true;
1127
1128 return false;
1129 }
1131 {
1132 uint64 progress = 0;
1133 for (CriteriaTree const* node : tree->Children)
1134 if (IsCompletedCriteriaTree(node))
1135 if (++progress >= requiredCount)
1136 return true;
1137
1138 return false;
1139 }
1141 {
1142 uint64 progress = 0;
1143 CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree)
1144 {
1145 if (criteriaTree->Criteria)
1146 if (CriteriaProgress const* criteriaProgress = GetCriteriaProgress(criteriaTree->Criteria))
1147 progress += criteriaProgress->Counter * criteriaTree->Entry->Amount;
1148 });
1149 return progress >= requiredCount;
1150 }
1151 default:
1152 break;
1153 }
1154
1155 return false;
1156}
1157
1158bool CriteriaHandler::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
1159{
1160 if ((tree->Entry->GetFlags().HasFlag(CriteriaTreeFlags::HordeOnly) && referencePlayer->GetTeam() != HORDE) ||
1161 (tree->Entry->GetFlags().HasFlag(CriteriaTreeFlags::AllianceOnly) && referencePlayer->GetTeam() != ALLIANCE))
1162 {
1163 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteriaTree: (Id: {} Type {} CriteriaTree {}) Wrong faction",
1164 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Entry->ID);
1165 return false;
1166 }
1167
1168 return true;
1169}
1170
1172{
1173 return true;
1174}
1175
1176bool CriteriaHandler::IsCompletedCriteria(Criteria const* criteria, uint64 requiredAmount)
1177{
1178 CriteriaProgress const* progress = GetCriteriaProgress(criteria);
1179 if (!progress)
1180 return false;
1181
1182 switch (CriteriaType(criteria->Entry->Type))
1183 {
1256 return progress->Counter >= requiredAmount;
1277 return progress->Counter >= 1;
1279 return progress->Counter >= (requiredAmount * 75);
1281 return progress->Counter >= 9000;
1283 return requiredAmount && progress->Counter >= requiredAmount;
1285 return true;
1286 // handle all statistic-only criteria here
1320 default:
1321 break;
1322 }
1323
1324 return false;
1325}
1326
1327bool CriteriaHandler::CanUpdateCriteria(Criteria const* criteria, CriteriaTreeList const* trees, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const* ref, Player* referencePlayer)
1328{
1329 if (DisableMgr::IsDisabledFor(DISABLE_TYPE_CRITERIA, criteria->ID, nullptr))
1330 {
1331 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Disabled", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1332 return false;
1333 }
1334
1335 bool treeRequirementPassed = false;
1336 for (CriteriaTree const* tree : *trees)
1337 {
1338 if (!CanUpdateCriteriaTree(criteria, tree, referencePlayer))
1339 continue;
1340
1341 treeRequirementPassed = true;
1342 break;
1343 }
1344
1345 if (!treeRequirementPassed)
1346 return false;
1347
1348 if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, miscValue3, ref, referencePlayer))
1349 {
1350 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Requirements not satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1351 return false;
1352 }
1353
1354 if (criteria->Modifier && !ModifierTreeSatisfied(criteria->Modifier, miscValue1, miscValue2, ref, referencePlayer))
1355 {
1356 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Requirements have not been satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1357 return false;
1358 }
1359
1360 if (!ConditionsSatisfied(criteria, referencePlayer))
1361 {
1362 TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: {} Type {}) Conditions have not been satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
1363 return false;
1364 }
1365
1366 if (criteria->Entry->EligibilityWorldStateID != 0)
1367 if (WorldStateMgr::GetValue(criteria->Entry->EligibilityWorldStateID, referencePlayer->GetMap()) != criteria->Entry->EligibilityWorldStateValue)
1368 return false;
1369
1370 return true;
1371}
1372
1373bool CriteriaHandler::ConditionsSatisfied(Criteria const* criteria, Player* /*referencePlayer*/) const
1374{
1375 if (criteria->Entry->StartEvent && !_startedCriteria.contains(criteria->ID))
1376 return false;
1377
1378 return true;
1379}
1380
1381bool CriteriaHandler::RequirementsSatisfied(Criteria const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const* ref, Player* referencePlayer) const
1382{
1383 switch (CriteriaType(criteria->Entry->Type))
1384 {
1429 if (!miscValue1)
1430 return false;
1431 break;
1445 break;
1448 return false;
1449 break;
1453 if (!miscValue1 || uint32(criteria->Entry->Asset.MapID) != referencePlayer->GetMapId())
1454 return false;
1455 break;
1458 if (!miscValue1 || uint32(criteria->Entry->Asset.CreatureID) != miscValue1)
1459 return false;
1460 break;
1463 // update at loading or specific skill update
1464 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.SkillID))
1465 return false;
1466 break;
1468 if (miscValue1)
1469 {
1470 Quest const* quest = sObjectMgr->GetQuestTemplate(miscValue1);
1471 if (!quest || quest->GetZoneOrSort() != criteria->Entry->Asset.ZoneID)
1472 return false;
1473 }
1474 break;
1476 {
1477 if (!miscValue1)
1478 return false;
1479 break;
1480 }
1482 {
1483 if (!miscValue1)
1484 return false;
1485
1486 Map const* map = referencePlayer->IsInWorld() ? referencePlayer->GetMap() : sMapMgr->FindMap(referencePlayer->GetMapId(), referencePlayer->GetInstanceId());
1487 if (!map || !map->IsDungeon())
1488 return false;
1489
1490 //FIXME: work only for instances where max == min for players
1491 if (map->ToInstanceMap()->GetMaxPlayers() != uint32(criteria->Entry->Asset.GroupSize))
1492 return false;
1493 break;
1494 }
1496 if (!miscValue1 || !ref || ref->GetTypeId() != TYPEID_PLAYER)
1497 return false;
1498 break;
1500 if (!miscValue1 || miscValue2 != uint32(criteria->Entry->Asset.EnviromentalDamageType))
1501 return false;
1502 break;
1504 {
1505 // if miscValues != 0, it contains the questID.
1506 if (miscValue1)
1507 {
1508 if (miscValue1 != uint32(criteria->Entry->Asset.QuestID))
1509 return false;
1510 }
1511 else
1512 {
1513 // login case.
1514 if (!referencePlayer->GetQuestRewardStatus(criteria->Entry->Asset.QuestID))
1515 return false;
1516 }
1517
1518 if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
1519 if (!data->Meets(referencePlayer, ref))
1520 return false;
1521 break;
1522 }
1527 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.SpellID))
1528 return false;
1529 break;
1531 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.SpellID))
1532 return false;
1533
1534 if (!referencePlayer->HasSpell(criteria->Entry->Asset.SpellID))
1535 return false;
1536 break;
1538 // miscValue1 = itemId - miscValue2 = count of item loot
1539 // miscValue3 = loot_type (note: 0 = LOOT_CORPSE and then it ignored)
1540 if (!miscValue1 || !miscValue2 || !miscValue3 || miscValue3 != uint32(criteria->Entry->Asset.LootType))
1541 return false;
1542 break;
1544 if (miscValue1 && uint32(criteria->Entry->Asset.ItemID) != miscValue1)
1545 return false;
1546 break;
1551 if (!miscValue1 || uint32(criteria->Entry->Asset.ItemID )!= miscValue1)
1552 return false;
1553 break;
1555 {
1556 WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(criteria->Entry->Asset.WorldMapOverlayID);
1557 if (!worldOverlayEntry)
1558 break;
1559
1560 bool matchFound = false;
1561 for (uint32 j : worldOverlayEntry->AreaID)
1562 {
1563 if (referencePlayer->HasExploredZone(j))
1564 {
1565 matchFound = true;
1566 break;
1567 }
1568 }
1569
1570 if (!matchFound)
1571 return false;
1572 break;
1573 }
1575 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.FactionID))
1576 return false;
1577 break;
1580 // miscValue1 = EquipmentSlot miscValue2 = itemid | itemModifiedAppearanceId
1581 if (!miscValue2 || miscValue1 != uint32(criteria->Entry->Asset.EquipmentSlot))
1582 return false;
1583 break;
1586 {
1587 // miscValue1 = itemid miscValue2 = diced value
1588 if (!miscValue1 || miscValue2 != uint32(criteria->Entry->Asset.RollValue))
1589 return false;
1590
1591 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1592 if (!proto)
1593 return false;
1594 break;
1595 }
1597 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.EmoteID))
1598 return false;
1599 break;
1602 if (!miscValue1)
1603 return false;
1604
1606 {
1607 if (!referencePlayer->InBattleground())
1608 return false;
1609
1610 // map specific case (BG in fact) expected player targeted damage/heal
1611 if (!ref || ref->GetTypeId() != TYPEID_PLAYER)
1612 return false;
1613 }
1614 break;
1617 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.GameObjectID))
1618 return false;
1619 break;
1622 if (miscValue1 && miscValue1 != uint32(criteria->Entry->Asset.SkillID))
1623 return false;
1624 break;
1626 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.ClassID))
1627 return false;
1628 break;
1630 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.RaceID))
1631 return false;
1632 break;
1634 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.WorldStateUIID))
1635 return false;
1636 break;
1639 if (!miscValue1 || !DB2Manager::IsInArea(uint32(miscValue1), uint32(criteria->Entry->Asset.AreaID)))
1640 return false;
1641 break;
1643 if (!miscValue1 || DB2Manager::IsInArea(uint32(miscValue1), uint32(criteria->Entry->Asset.AreaID)))
1644 return false;
1645 break;
1648 if (!miscValue1 || !miscValue2 || int64(miscValue2) < 0
1649 || miscValue1 != uint32(criteria->Entry->Asset.CurrencyID))
1650 return false;
1651 break;
1654 if (miscValue1 != uint32(criteria->Entry->Asset.MapID))
1655 return false;
1656 break;
1658 return false;
1661 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.DungeonEncounterID))
1662 return false;
1663 break;
1666 if (miscValue1 != uint32(criteria->Entry->Asset.GarrBuildingID))
1667 return false;
1668 break;
1670 if (miscValue1 != uint32(criteria->Entry->Asset.GarrFollowerID))
1671 return false;
1672 break;
1674 if (miscValue1 != uint32(criteria->Entry->Asset.TransmogSetGroupID))
1675 return false;
1676 break;
1679 if (!miscValue1 || !miscValue2 || miscValue2 != uint32(criteria->Entry->Asset.PetLevel))
1680 return false;
1681 break;
1683 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.PlayerLevel))
1684 return false;
1685 break;
1688 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.ZoneID))
1689 return false;
1690 break;
1693 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.EventID))
1694 return false;
1695 break;
1697 if (miscValue1 != uint32(criteria->Entry->Asset.ScenarioID))
1698 return false;
1699 break;
1702 if (!miscValue1 || miscValue1 != uint32(criteria->Entry->Asset.AreaTriggerActionSetID))
1703 return false;
1704 break;
1706 if (!referencePlayer->IsMaxLevel())
1707 return false;
1708 break;
1710 if (miscValue1 /*allow any at login*/ && miscValue1 != uint32(criteria->Entry->Asset.BankType))
1711 return false;
1712 break;
1714 if (miscValue1 != uint32(criteria->Entry->Asset.TaxiNodesID))
1715 return false;
1716 break;
1717 default:
1718 break;
1719 }
1720 return true;
1721}
1722
1723bool CriteriaHandler::ModifierTreeSatisfied(ModifierTreeNode const* tree, uint64 miscValue1, uint64 miscValue2, WorldObject const* ref, Player* referencePlayer) const
1724{
1725 switch (ModifierTreeOperator(tree->Entry->Operator))
1726 {
1728 return tree->Entry->Type && ModifierSatisfied(tree->Entry, miscValue1, miscValue2, ref, referencePlayer);
1730 return tree->Entry->Type && !ModifierSatisfied(tree->Entry, miscValue1, miscValue2, ref, referencePlayer);
1732 for (ModifierTreeNode const* node : tree->Children)
1733 if (!ModifierTreeSatisfied(node, miscValue1, miscValue2, ref, referencePlayer))
1734 return false;
1735 return true;
1737 {
1738 int8 requiredAmount = std::max<int8>(tree->Entry->Amount, 1);
1739 for (ModifierTreeNode const* node : tree->Children)
1740 if (ModifierTreeSatisfied(node, miscValue1, miscValue2, ref, referencePlayer))
1741 if (!--requiredAmount)
1742 return true;
1743
1744 return false;
1745 }
1746 default:
1747 break;
1748 }
1749
1750 return false;
1751}
1752
1753bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint64 miscValue1, uint64 miscValue2, WorldObject const* ref, Player* referencePlayer) const
1754{
1755 uint32 reqValue = modifier->Asset;
1756 uint32 secondaryAsset = modifier->SecondaryAsset;
1757 int32 tertiaryAsset = modifier->TertiaryAsset;
1758
1759 switch (ModifierTreeType(modifier->Type))
1760 {
1762 {
1763 uint32 inebriation = std::min(std::max<uint32>(referencePlayer->GetDrunkValue(), *referencePlayer->m_playerData->FakeInebriation), 100u);
1764 if (inebriation < reqValue)
1765 return false;
1766 break;
1767 }
1769 {
1770 if (!ConditionMgr::IsPlayerMeetingCondition(referencePlayer, reqValue))
1771 return false;
1772 break;
1773 }
1775 {
1776 // miscValue1 is itemid
1777 ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1778 if (!item || item->GetBaseItemLevel() < reqValue)
1779 return false;
1780 break;
1781 }
1783 if (!ref || ref->GetEntry() != reqValue)
1784 return false;
1785 break;
1787 if (!ref || ref->GetTypeId() != TYPEID_PLAYER)
1788 return false;
1789 break;
1791 if (!ref || !ref->IsUnit() || ref->ToUnit()->IsAlive())
1792 return false;
1793 break;
1795 if (!ref || !referencePlayer->IsHostileTo(ref))
1796 return false;
1797 break;
1799 if (!referencePlayer->HasAura(reqValue))
1800 return false;
1801 break;
1803 if (!referencePlayer->HasAuraType(AuraType(reqValue)))
1804 return false;
1805 break;
1807 if (!ref || !ref->IsUnit() || !ref->ToUnit()->HasAura(reqValue))
1808 return false;
1809 break;
1811 if (!ref || !ref->IsUnit() || !ref->ToUnit()->HasAuraType(AuraType(reqValue)))
1812 return false;
1813 break;
1815 if (!ref || !ref->IsUnit() || !ref->ToUnit()->HasAuraState(AuraStateType(reqValue)))
1816 return false;
1817 break;
1819 if (!referencePlayer->HasAuraState(AuraStateType(reqValue)))
1820 return false;
1821 break;
1823 {
1824 // miscValue1 is itemid
1825 ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1826 if (!item || item->GetQuality() < reqValue)
1827 return false;
1828 break;
1829 }
1831 {
1832 // miscValue1 is itemid
1833 ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
1834 if (!item || item->GetQuality() != reqValue)
1835 return false;
1836 break;
1837 }
1839 if (referencePlayer->isDead())
1840 return false;
1841 break;
1843 {
1844 if (!DB2Manager::IsInArea(referencePlayer->GetAreaId(), reqValue))
1845 return false;
1846 break;
1847 }
1849 {
1850 if (!ref)
1851 return false;
1852 if (!DB2Manager::IsInArea(ref->GetAreaId(), reqValue))
1853 return false;
1854 break;
1855 }
1856 case ModifierTreeType::ItemId: // 19
1857 if (miscValue1 != reqValue)
1858 return false;
1859 break;
1861 {
1862 DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(referencePlayer->GetMap()->GetDifficultyID());
1863 if (!difficulty || difficulty->OldEnumValue == -1 || uint32(difficulty->OldEnumValue) != reqValue)
1864 return false;
1865 break;
1866 }
1868 if (!ref || !ref->IsUnit() || referencePlayer->GetLevel() < ref->ToUnit()->GetLevel() + reqValue)
1869 return false;
1870 break;
1872 if (!ref || !ref->IsUnit() || referencePlayer->GetLevel() + reqValue < ref->ToUnit()->GetLevel())
1873 return false;
1874 break;
1876 if (!ref || !ref->IsUnit() || referencePlayer->GetLevel() != ref->ToUnit()->GetLevel())
1877 return false;
1878 break;
1880 {
1881 Battleground* bg = referencePlayer->GetBattleground();
1882 if (!bg || !bg->isArena() || bg->GetArenaType() != reqValue)
1883 return false;
1884 break;
1885 }
1887 if (referencePlayer->GetRace() != reqValue)
1888 return false;
1889 break;
1891 if (referencePlayer->GetClass() != reqValue)
1892 return false;
1893 break;
1895 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetRace() != reqValue)
1896 return false;
1897 break;
1899 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetClass() != reqValue)
1900 return false;
1901 break;
1903 if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= reqValue)
1904 return false;
1905 break;
1907 {
1908 if (!ref)
1909 return false;
1910 if (!ref->IsUnit() || ref->ToUnit()->GetCreatureType() != reqValue)
1911 return false;
1912 break;
1913 }
1915 {
1916 if (!ref)
1917 return false;
1918 if (!ref->IsCreature() || ref->ToCreature()->GetCreatureTemplate()->family != CreatureFamily(reqValue))
1919 return false;
1920 break;
1921 }
1922 case ModifierTreeType::PlayerMap: // 32
1923 if (referencePlayer->GetMapId() != reqValue)
1924 return false;
1925 break;
1927 {
1928 std::shared_ptr<Realm const> currentRealm = sRealmList->GetCurrentRealm();
1929 if (!currentRealm)
1930 return false;
1931 if (reqValue < ClientBuild::GetMinorMajorBugfixVersionForBuild(currentRealm->Build))
1932 return false;
1933 break;
1934 }
1936 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
1937 if (slot.Pet.Level < reqValue)
1938 return false;
1939 break;
1941 if (referencePlayer->GetGroup())
1942 return false;
1943 break;
1945 if (!referencePlayer->GetGroup())
1946 return false;
1947 break;
1949 if (referencePlayer->GetMaxPersonalArenaRatingRequirement(0) < reqValue)
1950 return false;
1951 break;
1952 case ModifierTreeType::HasTitle: // 38
1953 if (!referencePlayer->HasTitle(reqValue))
1954 return false;
1955 break;
1957 if (referencePlayer->GetLevel() != reqValue)
1958 return false;
1959 break;
1961 if (!ref || ref->GetLevelForTarget(referencePlayer) != reqValue)
1962 return false;
1963 break;
1965 {
1966 uint32 zoneId = referencePlayer->GetAreaId();
1967 if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId))
1968 if (areaEntry->GetFlags().HasFlag(AreaFlags::IsSubzone))
1969 zoneId = areaEntry->ParentAreaID;
1970 if (zoneId != reqValue)
1971 return false;
1972 break;
1973 }
1975 {
1976 if (!ref)
1977 return false;
1978 uint32 zoneId = ref->GetAreaId();
1979 if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId))
1980 if (areaEntry->GetFlags().HasFlag(AreaFlags::IsSubzone))
1981 zoneId = areaEntry->ParentAreaID;
1982 if (zoneId != reqValue)
1983 return false;
1984 break;
1985 }
1987 if (referencePlayer->GetHealthPct() > float(reqValue))
1988 return false;
1989 break;
1991 if (referencePlayer->GetHealthPct() < float(reqValue))
1992 return false;
1993 break;
1995 if (referencePlayer->GetHealthPct() != float(reqValue))
1996 return false;
1997 break;
1999 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealthPct() > float(reqValue))
2000 return false;
2001 break;
2003 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealthPct() < float(reqValue))
2004 return false;
2005 break;
2007 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealthPct() != float(reqValue))
2008 return false;
2009 break;
2011 if (referencePlayer->GetHealth() > reqValue)
2012 return false;
2013 break;
2015 if (referencePlayer->GetHealth() < reqValue)
2016 return false;
2017 break;
2019 if (referencePlayer->GetHealth() != reqValue)
2020 return false;
2021 break;
2023 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealth() > reqValue)
2024 return false;
2025 break;
2027 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealth() < reqValue)
2028 return false;
2029 break;
2031 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetHealth() != reqValue)
2032 return false;
2033 break;
2035 {
2036 if (!ref || !ref->IsPlayer())
2037 return false;
2038
2039 if (!ConditionMgr::IsPlayerMeetingCondition(ref->ToPlayer(), reqValue))
2040 return false;
2041 break;
2042 }
2044 if (referencePlayer->GetAchievementPoints() <= reqValue)
2045 return false;
2046 break;
2049 return false;
2050 break;
2053 return false;
2054 break;
2057 return false;
2058 break;
2060 {
2061 Battleground const* bg = referencePlayer->GetBattleground();
2062 if (!bg || !bg->isArena() || !bg->isRated())
2063 return false;
2064 break;
2065 }
2067 return false;
2069 if (referencePlayer->GetReputationMgr().GetReputation(1168) < int32(reqValue))
2070 return false;
2071 break;
2073 {
2074 Battleground const* bg = referencePlayer->GetBattleground();
2075 if (!bg || !bg->isBattleground() || !bg->isRated())
2076 return false;
2077 break;
2078 }
2080 if (referencePlayer->GetRBGPersonalRating() < reqValue)
2081 return false;
2082 break;
2085 return false;
2087 if (WorldStateExpressionEntry const* worldStateExpression = sWorldStateExpressionStore.LookupEntry(reqValue))
2088 return ConditionMgr::IsMeetingWorldStateExpression(referencePlayer->GetMap(), worldStateExpression);
2089 return false;
2091 if (referencePlayer->GetMap()->GetDifficultyID() != int32(reqValue))
2092 return false;
2093 break;
2095 if (referencePlayer->GetLevel() < reqValue)
2096 return false;
2097 break;
2099 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetLevel() < reqValue)
2100 return false;
2101 break;
2103 if (referencePlayer->GetLevel() > reqValue)
2104 return false;
2105 break;
2107 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetLevel() > reqValue)
2108 return false;
2109 break;
2111 if (ModifierTreeNode const* nextModifierTree = sCriteriaMgr->GetModifierTree(reqValue))
2112 return ModifierTreeSatisfied(nextModifierTree, miscValue1, miscValue2, ref, referencePlayer);
2113 return false;
2115 {
2116 Scenario const* scenario = referencePlayer->GetScenario();
2117 if (!scenario || scenario->GetEntry()->ID != reqValue)
2118 return false;
2119 break;
2120 }
2122 if (referencePlayer->GetReputationMgr().GetReputation(1272) < int32(reqValue))
2123 return false;
2124 break;
2126 {
2127 auto getRootAchievementCategory = [](AchievementEntry const* achievement)
2128 {
2129 int16 category = achievement->Category;
2130 do
2131 {
2132 Achievement_CategoryEntry const* categoryEntry = sAchievementCategoryStore.LookupEntry(category);
2133 if (!categoryEntry || categoryEntry->Parent == -1)
2134 break;
2135
2136 category = categoryEntry->Parent;
2137 } while (true);
2138
2139 return category;
2140 };
2141
2142 uint32 petAchievementPoints = 0;
2143 for (uint32 achievementId : referencePlayer->GetCompletedAchievementIds())
2144 {
2145 AchievementEntry const* achievement = sAchievementStore.AssertEntry(achievementId);
2146 if (getRootAchievementCategory(achievement) == ACHIVEMENT_CATEGORY_PET_BATTLES)
2147 petAchievementPoints += uint32(achievement->Points);
2148 }
2149
2150 if (petAchievementPoints < reqValue)
2151 return false;
2152 break;
2153 }
2155 if (referencePlayer->GetSession()->GetBattlePetMgr()->GetPetUniqueSpeciesCount() < reqValue)
2156 return false;
2157 break;
2159 {
2160 BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(miscValue1);
2161 if (!speciesEntry || speciesEntry->PetTypeEnum != int32(reqValue))
2162 return false;
2163 break;
2164 }
2165 case ModifierTreeType::BattlePetHealthPercentLessThan: // 79 NYI - use target battle pet here, the one we were just battling
2166 return false;
2168 {
2169 uint32 guildMemberCount = 0;
2170 if (Group const* group = referencePlayer->GetGroup())
2171 for (GroupReference const& itr : group->GetMembers())
2172 if (itr.GetSource()->GetGuildId() == referencePlayer->GetGuildId())
2173 ++guildMemberCount;
2174
2175 if (guildMemberCount < reqValue)
2176 return false;
2177 break;
2178 }
2180 return false;
2182 {
2183 Scenario const* scenario = referencePlayer->GetScenario();
2184 if (!scenario)
2185 return false;
2186 if (scenario->GetStep()->OrderIndex != (reqValue - 1))
2187 return false;
2188 break;
2189 }
2191 return false; // OBSOLETE
2193 if (referencePlayer->FindQuestSlot(reqValue) == MAX_QUEST_LOG_SIZE)
2194 return false;
2195 break;
2197 if (referencePlayer->GetReputationMgr().GetReputation(reqValue) < 42000)
2198 return false;
2199 break;
2202 if (!referencePlayer->HasAchieved(reqValue))
2203 return false;
2204 break;
2206 if (referencePlayer->GetReputationMgr().GetReputation(1271) < int32(reqValue))
2207 return false;
2208 break;
2211 return false;
2213 if (miscValue1 != reqValue)
2214 return false;
2215 break;
2217 if (sWorld->getIntConfig(CONFIG_EXPANSION) < reqValue)
2218 return false;
2219 break;
2221 if (!referencePlayer->GetSession()->GetBattlePetMgr()->HasJournalLock())
2222 return false;
2223 break;
2225 {
2226 FriendshipRepReactionEntry const* friendshipRepReaction = sFriendshipRepReactionStore.LookupEntry(reqValue);
2227 if (!friendshipRepReaction)
2228 return false;
2229 FriendshipReputationEntry const* friendshipReputation = sFriendshipReputationStore.LookupEntry(friendshipRepReaction->FriendshipRepID);
2230 if (!friendshipReputation)
2231 return false;
2232 if (referencePlayer->GetReputation(friendshipReputation->FactionID) < int32(friendshipRepReaction->ReactionThreshold))
2233 return false;
2234 break;
2235 }
2237 if (referencePlayer->GetReputationMgr().GetReputation(reqValue) < int32(secondaryAsset))
2238 return false;
2239 break;
2241 {
2242 ItemTemplate const* item = sObjectMgr->GetItemTemplate(miscValue1);
2243 if (!item || item->GetClass() != reqValue || item->GetSubClass() != secondaryAsset)
2244 return false;
2245 break;
2246 }
2248 if (referencePlayer->GetGender() != uint8(reqValue))
2249 return false;
2250 break;
2252 if (referencePlayer->GetNativeGender() != uint8(reqValue))
2253 return false;
2254 break;
2256 if (referencePlayer->GetPureSkillValue(reqValue) < uint16(secondaryAsset))
2257 return false;
2258 break;
2260 {
2261 auto languageDescs = sLanguageMgr->GetLanguageDescById(Language(reqValue));
2262 bool hasLanguageSkil = std::any_of(languageDescs.begin(), languageDescs.end(), [&](std::pair<uint32 const, LanguageDesc> const& desc)
2263 {
2264 return referencePlayer->GetSkillValue(desc.second.SkillId) >= secondaryAsset;
2265 });
2266 if (!hasLanguageSkil)
2267 return false;
2268 break;
2269 }
2271 if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, 0, 0))
2272 return false;
2273 break;
2275 if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, reqValue, 0))
2276 return false;
2277 break;
2279 if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, 0, reqValue))
2280 return false;
2281 break;
2283 if (!referencePlayer->HasSpell(reqValue))
2284 return false;
2285 break;
2287 if (referencePlayer->GetItemCount(reqValue, false) < secondaryAsset)
2288 return false;
2289 break;
2291 if (referencePlayer->GetSession()->GetExpansion() < reqValue)
2292 return false;
2293 break;
2295 if (!referencePlayer->HasAura([labelId = reqValue](Aura const* aura) { return aura->GetSpellInfo()->HasLabel(labelId); }))
2296 return false;
2297 break;
2299 if (WorldStateMgr::GetValue(reqValue, referencePlayer->GetMap()) != int32(secondaryAsset))
2300 return false;
2301 break;
2303 {
2304 WowTime from;
2305 from.SetPackedTime(reqValue);
2306 WowTime to;
2307 to.SetPackedTime(secondaryAsset);
2308
2309 if (!GameTime::GetWowTime()->IsInRange(from, to))
2310 return false;
2311 break;
2312 }
2314 if (!referencePlayer->IsQuestCompletedBitSet(reqValue))
2315 return false;
2316 break;
2318 if (referencePlayer->GetQuestStatus(reqValue) != QUEST_STATUS_COMPLETE)
2319 return false;
2320 break;
2322 {
2323 QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
2324 if (!objective)
2325 return false;
2326 Quest const* quest = sObjectMgr->GetQuestTemplate(objective->QuestID);
2327 if (!quest)
2328 return false;
2329 uint16 slot = referencePlayer->FindQuestSlot(objective->QuestID);
2330 if (slot >= MAX_QUEST_LOG_SIZE || referencePlayer->GetQuestRewardStatus(objective->QuestID) || !referencePlayer->IsQuestObjectiveComplete(slot, quest, *objective))
2331 return false;
2332 break;
2333 }
2335 {
2336 if (!referencePlayer->HasExploredZone(reqValue))
2337 return false;
2338 break;
2339 }
2341 if (referencePlayer->GetItemCount(reqValue, true) < secondaryAsset)
2342 return false;
2343 break;
2344 case ModifierTreeType::Weather: // 115
2345 if (referencePlayer->GetMap()->GetZoneWeather(referencePlayer->GetZoneId()) != WeatherState(reqValue))
2346 return false;
2347 break;
2349 {
2350 ChrRacesEntry const* race = sChrRacesStore.LookupEntry(referencePlayer->GetRace());
2351 if (!race)
2352 return false;
2353 FactionTemplateEntry const* faction = sFactionTemplateStore.LookupEntry(race->FactionID);
2354 if (!faction)
2355 return false;
2356 int32 factionIndex = -1;
2357 if (faction->FactionGroup & FACTION_MASK_HORDE)
2358 factionIndex = 0;
2359 else if (faction->FactionGroup & FACTION_MASK_ALLIANCE)
2360 factionIndex = 1;
2361 else if (faction->FactionGroup & FACTION_MASK_PLAYER)
2362 factionIndex = 0;
2363 if (factionIndex != int32(reqValue))
2364 return false;
2365 break;
2366 }
2368 if (ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus(reqValue)) != secondaryAsset)
2369 return false;
2370 break;
2372 if (ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus(reqValue)) < secondaryAsset)
2373 return false;
2374 break;
2376 if (!referencePlayer->HasCurrency(reqValue, secondaryAsset))
2377 return false;
2378 break;
2380 {
2381 if (!ref)
2382 return false;
2383 Unit const* unitRef = ref->ToUnit();
2384 if (!unitRef || !unitRef->CanHaveThreatList())
2385 return false;
2386 if (unitRef->GetThreatManager().GetThreatListSize() >= reqValue)
2387 return false;
2388 break;
2389 }
2391 if (referencePlayer->GetCurrencyTrackedQuantity(reqValue) < secondaryAsset)
2392 return false;
2393 break;
2395 if (referencePlayer->GetMap()->GetEntry()->InstanceType != int8(reqValue))
2396 return false;
2397 break;
2399 if (!referencePlayer->HasPlayerFlag(PLAYER_FLAGS_TIMEWALKING))
2400 return false;
2401 break;
2403 if (!sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS))
2404 return false;
2405 break;
2406 case ModifierTreeType::PvpSeason: // 125
2407 if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) != reqValue)
2408 return false;
2409 break;
2411 {
2412 Garrison const* garrison = referencePlayer->GetGarrison();
2413 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel < reqValue)
2414 return false;
2415 break;
2416 }
2418 {
2419 Garrison const* garrison = referencePlayer->GetGarrison();
2420 if (!garrison)
2421 return false;
2422 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2423 {
2424 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2425 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= secondaryAsset;
2426 });
2427 if (followerCount < reqValue)
2428 return false;
2429 break;
2430 }
2432 {
2433 Garrison const* garrison = referencePlayer->GetGarrison();
2434 if (!garrison)
2435 return false;
2436 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2437 {
2438 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2439 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.Quality >= secondaryAsset;
2440 });
2441 if (followerCount < reqValue)
2442 return false;
2443 break;
2444 }
2446 {
2447 Garrison const* garrison = referencePlayer->GetGarrison();
2448 if (!garrison)
2449 return false;
2450 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2451 {
2452 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2453 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
2454 });
2455 if (followerCount < 1)
2456 return false;
2457 break;
2458 }
2460 {
2461 Garrison const* garrison = referencePlayer->GetGarrison();
2462 if (!garrison)
2463 return false;
2464 GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(secondaryAsset);
2465 if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
2466 return false;
2467 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2468 {
2469 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2470 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
2471 });
2472 if (followerCount < 1)
2473 return false;
2474 break;
2475 }
2477 {
2478 Garrison const* garrison = referencePlayer->GetGarrison();
2479 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2480 return false;
2481 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2482 {
2483 GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
2484 if (!followerBuilding)
2485 return false;
2486 return followerBuilding->BuildingType == secondaryAsset && follower.HasAbility(reqValue);;
2487 });
2488 if (followerCount < 1)
2489 return false;
2490 break;
2491 }
2493 {
2494 Garrison const* garrison = referencePlayer->GetGarrison();
2495 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2496 return false;
2497 GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(reqValue);
2498 if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
2499 return false;
2500 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2501 {
2502 GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
2503 if (!followerBuilding)
2504 return false;
2505 return followerBuilding->BuildingType == secondaryAsset && follower.HasAbility(reqValue);;
2506 });
2507 if (followerCount < 1)
2508 return false;
2509 break;
2510 }
2512 {
2513 Garrison const* garrison = referencePlayer->GetGarrison();
2514 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2515 return false;
2516 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2517 {
2518 if (follower.PacketInfo.FollowerLevel < reqValue)
2519 return false;
2520 GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
2521 if (!followerBuilding)
2522 return false;
2523 return followerBuilding->BuildingType == secondaryAsset;
2524 });
2525 if (followerCount < 1)
2526 return false;
2527 break;
2528 }
2530 {
2531 Garrison* garrison = referencePlayer->GetGarrison();
2532 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2533 return false;
2534 for (Garrison::Plot const* plot : garrison->GetPlots())
2535 {
2536 if (!plot->BuildingInfo.PacketInfo)
2537 continue;
2538
2539 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2540 if (!building || building->UpgradeLevel < reqValue || building->BuildingType != secondaryAsset)
2541 continue;
2542
2543 return true;
2544 }
2545 return false;
2546 }
2548 {
2549 Garrison const* garrison = referencePlayer->GetGarrison();
2550 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2551 return false;
2552 if (!garrison->HasBlueprint(reqValue))
2553 return false;
2554 break;
2555 }
2557 return false; // OBSOLETE
2559 {
2560 Garrison* garrison = referencePlayer->GetGarrison();
2561 if (!garrison || garrison->GetType() != GarrisonType(reqValue))
2562 return false;
2563 for (Garrison::Plot const* plot : garrison->GetPlots())
2564 if (!plot->BuildingInfo.PacketInfo)
2565 return false;
2566 break;
2567 }
2569 if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() != referencePlayer->GetGUID().GetCounter())
2570 return false;
2571 break;
2573 return false;
2575 {
2576 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(reqValue);
2577 if (!building)
2578 return false;
2579 Garrison* garrison = referencePlayer->GetGarrison();
2580 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2581 return false;
2582 for (Garrison::Plot const* plot : garrison->GetPlots())
2583 {
2584 if (!plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->GarrBuildingID != reqValue)
2585 continue;
2586
2587 return !plot->BuildingInfo.PacketInfo->Active;
2588 }
2589 return false;
2590 }
2592 return false;
2594 {
2595 Garrison* garrison = referencePlayer->GetGarrison();
2596 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2597 return false;
2598 for (Garrison::Plot const* plot : garrison->GetPlots())
2599 {
2600 if (!plot->BuildingInfo.PacketInfo)
2601 continue;
2602
2603 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2604 if (!building || building->UpgradeLevel != secondaryAsset || building->BuildingType != reqValue)
2605 continue;
2606
2607 return true;
2608 }
2609 return false;
2610 }
2612 {
2613 Garrison const* garrison = referencePlayer->GetGarrison();
2614 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2615 return false;
2616 if (miscValue1)
2617 {
2618 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2619 if (!follower)
2620 return false;
2621 if (!follower->HasAbility(reqValue))
2622 return false;
2623 }
2624 else
2625 {
2626 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2627 {
2628 return follower.HasAbility(reqValue);
2629 });
2630 if (followerCount < 1)
2631 return false;
2632 }
2633 break;
2634 }
2636 {
2637 GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(reqValue);
2638 if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
2639 return false;
2640 Garrison const* garrison = referencePlayer->GetGarrison();
2641 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2642 return false;
2643 if (miscValue1)
2644 {
2645 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2646 if (!follower || !follower->HasAbility(reqValue))
2647 return false;
2648 }
2649 else
2650 {
2651 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2652 {
2653 return follower.HasAbility(reqValue);
2654 });
2655 if (followerCount < 1)
2656 return false;
2657 }
2658 break;
2659 }
2661 {
2662 Garrison const* garrison = referencePlayer->GetGarrison();
2663 if (!garrison || garrison->GetType() != GARRISON_TYPE_GARRISON)
2664 return false;
2665 if (miscValue1)
2666 {
2667 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2668 if (!follower || follower->PacketInfo.Quality < reqValue)
2669 return false;
2670 }
2671 else
2672 {
2673 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2674 {
2675 return follower.PacketInfo.Quality >= reqValue;
2676 });
2677 if (followerCount < 1)
2678 return false;
2679 }
2680 break;
2681 }
2683 {
2684 Garrison const* garrison = referencePlayer->GetGarrison();
2685 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
2686 return false;
2687 if (miscValue1)
2688 {
2689 Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
2690 if (!follower || follower->PacketInfo.FollowerLevel != reqValue)
2691 return false;
2692 }
2693 else
2694 {
2695 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2696 {
2697 return follower.PacketInfo.FollowerLevel == reqValue;
2698 });
2699 if (followerCount < 1)
2700 return false;
2701 }
2702 break;
2703 }
2706 return false;
2708 {
2709 if (!miscValue1)
2710 return false;
2711 Garrison* garrison = referencePlayer->GetGarrison();
2712 if (!garrison)
2713 return false;
2714 for (Garrison::Plot const* plot : garrison->GetPlots())
2715 {
2716 if (!plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->GarrBuildingID != miscValue1)
2717 continue;
2718
2719 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2720 if (!building || building->UpgradeLevel != reqValue)
2721 continue;
2722
2723 return true;
2724 }
2725 break;
2726 }
2728 {
2729 Garrison* garrison = referencePlayer->GetGarrison();
2730 if (!garrison)
2731 return false;
2732 Garrison::Plot const* plot = garrison->GetPlot(reqValue);
2733 if (!plot)
2734 return false;
2735 if (!plot->BuildingInfo.CanActivate() || !plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->Active)
2736 return false;
2737 break;
2738 }
2740 {
2741 uint32 count = 0;
2742 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
2743 if (slot.Pet.Species == secondaryAsset)
2744 ++count;
2745 if (count < reqValue)
2746 return false;
2747 break;
2748 }
2750 {
2751 uint32 count = 0;
2752 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
2753 if (BattlePetSpeciesEntry const* species = sBattlePetSpeciesStore.LookupEntry(slot.Pet.Species))
2754 if (species->PetTypeEnum == int32(secondaryAsset))
2755 ++count;
2756 if (count < reqValue)
2757 return false;
2758 break;
2759 }
2762 return false;
2764 {
2765 uint32 count = 0;
2766 for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
2767 if (slot.Pet.Health > 0)
2768 ++count;
2769 if (count < reqValue)
2770 return false;
2771 break;
2772 }
2774 return false; // OBSOLETE
2776 {
2777 Garrison const* garrison = referencePlayer->GetGarrison();
2778 if (!garrison)
2779 return false;
2780 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2781 {
2782 return follower.PacketInfo.GarrFollowerID == reqValue;
2783 });
2784 if (followerCount < 1)
2785 return false;
2786 break;
2787 }
2789 {
2790 QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
2791 if (!objective)
2792 return false;
2793 if (referencePlayer->GetQuestObjectiveData(*objective) != int32(secondaryAsset))
2794 return false;
2795 break;
2796 }
2798 {
2799 QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
2800 if (!objective)
2801 return false;
2802 if (referencePlayer->GetQuestObjectiveData(*objective) < int32(secondaryAsset))
2803 return false;
2804 break;
2805 }
2806 case ModifierTreeType::IsPTRRealm: // 160
2808 case ModifierTreeType::IsQARealm: // 162
2809 return false; // always false
2811 return false;
2813 return true; // Only 1 player is required and referencePlayer->GetMap() will ALWAYS have at least the referencePlayer on it
2815 if (referencePlayer->GetMap()->GetPlayersCountExceptGMs() > reqValue)
2816 return false;
2817 break;
2819 {
2820 Garrison* garrison = referencePlayer->GetGarrison();
2821 if (!garrison || garrison->GetType() != GarrisonType(reqValue))
2822 return false;
2823 for (Garrison::Plot const* plot : garrison->GetPlots())
2824 {
2825 if (!plot->BuildingInfo.PacketInfo)
2826 return false;
2827 GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
2828 if (!building || building->UpgradeLevel != reqValue)
2829 return false;
2830 }
2831 break;
2832 }
2834 return false;
2836 {
2837 if (!miscValue1)
2838 return false;
2839 Garrison const* garrison = referencePlayer->GetGarrison();
2840 if (!garrison)
2841 return false;
2842 uint32 followerCount = garrison->CountFollowers([miscValue1, reqValue](Garrison::Follower const& follower)
2843 {
2844 return follower.PacketInfo.GarrFollowerID == miscValue1 && follower.GetItemLevel() >= reqValue;
2845 });
2846 if (followerCount < 1)
2847 return false;
2848 break;
2849 }
2851 {
2852 Garrison const* garrison = referencePlayer->GetGarrison();
2853 if (!garrison)
2854 return false;
2855 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2856 {
2857 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2858 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.GetItemLevel() >= secondaryAsset;
2859 });
2860 if (followerCount < reqValue)
2861 return false;
2862 break;
2863 }
2865 {
2866 Garrison const* garrison = referencePlayer->GetGarrison();
2867 if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel != reqValue)
2868 return false;
2869 break;
2870 }
2872 if (referencePlayer->GetMap()->GetPlayers().size() != reqValue)
2873 return false;
2874 break;
2875 case ModifierTreeType::CurrencyId: // 172
2876 if (miscValue1 != reqValue)
2877 return false;
2878 break;
2880 if (referencePlayer->GetTarget().GetHigh() != HighGuid::Corpse)
2881 return false;
2882 break;
2884 {
2885 Quest const* quest = sObjectMgr->GetQuestTemplate(reqValue);
2886 if (!quest)
2887 return false;
2888 if (!referencePlayer->CanTakeQuest(quest, false))
2889 return false;
2890 break;
2891 }
2893 {
2894 Garrison const* garrison = referencePlayer->GetGarrison();
2895 if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
2896 return false;
2897 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2898 {
2899 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
2900 return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel == secondaryAsset;
2901 });
2902 if (followerCount < reqValue)
2903 return false;
2904 break;
2905 }
2907 {
2908 Garrison const* garrison = referencePlayer->GetGarrison();
2909 if (!garrison)
2910 return false;
2911 uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
2912 {
2913 return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentBuildingID == secondaryAsset;
2914 });
2915 if (followerCount < 1)
2916 return false;
2917 break;
2918 }
2920 return false;
2922 {
2923 Garrison* garrison = referencePlayer->GetGarrison();
2924 if (!garrison || garrison->GetType() != GarrisonType(reqValue))
2925 return false;
2926 uint32 plotCount = 0;
2927 for (Garrison::Plot const* plot : garrison->GetPlots())
2928 {
2929 GarrPlotInstanceEntry const* garrPlotInstance = sGarrPlotInstanceStore.LookupEntry(plot->PacketInfo.GarrPlotInstanceID);
2930 if (!garrPlotInstance || garrPlotInstance->GarrPlotID != secondaryAsset)
2931 continue;
2932 ++plotCount;
2933 }
2934 if (plotCount < reqValue)
2935 return false;
2936 break;
2937 }
2938 case ModifierTreeType::CurrencySource: // 179 NYI
2939 return false;
2941 if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() == referencePlayer->GetGUID().GetCounter())
2942 return false;
2943 break;
2945 {
2946 Garrison const* garrison = referencePlayer->GetGarrison();
2947 if (!garrison)
2948 return false;
2949 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2950 {
2951 return follower.PacketInfo.GarrFollowerID == reqValue && !(follower.PacketInfo.FollowerStatus & FOLLOWER_STATUS_INACTIVE);
2952 });
2953 if (followerCount < 1)
2954 return false;
2955 break;
2956 }
2958 return false;
2960 {
2961 for (auto&& p : referencePlayer->GetSession()->GetCollectionMgr()->GetAccountMounts())
2962 {
2963 MountEntry const* mount = sDB2Manager.GetMount(p.first);
2964 if (!mount)
2965 continue;
2966
2967 if (mount->ID == reqValue)
2968 return true;
2969 }
2970 return false;
2971 }
2973 {
2974 Garrison const* garrison = referencePlayer->GetGarrison();
2975 if (!garrison)
2976 return false;
2977 uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
2978 {
2979 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.LookupEntry(follower.PacketInfo.GarrFollowerID);
2980 if (!garrFollower)
2981 return false;
2982 return follower.GetItemLevel() >= secondaryAsset && garrFollower->GarrFollowerTypeID == tertiaryAsset;
2983 });
2984 if (followerCount < reqValue)
2985 return false;
2986 break;
2987 }
2989 {
2990 Garrison const* garrison = referencePlayer->GetGarrison();
2991 if (!garrison)
2992 return false;
2993 uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
2994 {
2995 return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentMissionID != 0;
2996 });
2997 if (followerCount < 1)
2998 return false;
2999 break;
3000 }
3002 return false;
3004 {
3005 GarrFollowerEntry const* garrFollower = sGarrFollowerStore.LookupEntry(miscValue1);
3006 if (!garrFollower || garrFollower->GarrFollowerTypeID != int32(reqValue))
3007 return false;
3008 break;
3009 }
3012 return false;
3014 if (!referencePlayer->HasPlayerFlagEx(PLAYER_FLAGS_EX_MERCENARY_MODE))
3015 return false;
3016 break;
3019 return false;
3021 if (referencePlayer->GetHonorLevel() < reqValue)
3022 return false;
3023 break;
3025 return false; // OBSOLOTE
3028 return false;
3031 return false;
3032 break;
3033 case ModifierTreeType::TeamPoints: // 198 NYI
3034 return false;
3036 if (!referencePlayer->GetSession()->GetCollectionMgr()->HasToy(reqValue))
3037 return false;
3038 break;
3040 {
3041 std::pair<bool, bool> hasAppearance = referencePlayer->GetSession()->GetCollectionMgr()->HasItemAppearance(reqValue);
3042 if (!hasAppearance.first || hasAppearance.second)
3043 return false;
3044 break;
3045 }
3048 return false;
3050 {
3051 int32 restrictionIndex = referencePlayer->m_activePlayerData->CharacterRestrictions.FindIndexIf([reqValue](UF::CharacterRestriction const& restriction)
3052 {
3053 return restriction.Type == reqValue;
3054 });
3055 if (restrictionIndex < 0)
3056 return false;
3057 break;
3058 }
3060 return false;
3062 if (Hours(reqValue) >= Seconds(referencePlayer->GetTotalPlayedTime()))
3063 return false;
3064 break;
3066 {
3067 Quest const* quest = sObjectMgr->GetQuestTemplate(miscValue1);
3068 if (!quest || quest->GetQuestInfoID() != reqValue)
3069 return false;
3070 break;
3071 }
3073 return false;
3075 {
3076 if (Aura const* artifactAura = referencePlayer->GetAura(ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE))
3077 if (Item* artifact = referencePlayer->GetItemByGuid(artifactAura->GetCastItemGUID()))
3078 if (ArtifactAppearanceEntry const* artifactAppearance = sArtifactAppearanceStore.LookupEntry(artifact->GetModifier(ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID)))
3079 if (artifactAppearance->ArtifactAppearanceSetID == reqValue)
3080 break;
3081 return false;
3082 }
3084 if (referencePlayer->GetCurrencyQuantity(reqValue) != secondaryAsset)
3085 return false;
3086 break;
3088 return false;
3090 {
3091 Scenario const* scenario = referencePlayer->GetScenario();
3092 if (!scenario)
3093 return false;
3094 if (scenario->GetEntry()->Type != int32(reqValue))
3095 return false;
3096 break;
3097 }
3099 if (referencePlayer->GetSession()->GetAccountExpansion() < reqValue)
3100 return false;
3101 break;
3105 return false;
3107 {
3108 uint32 memberCount = 0;
3109 if (Group const* group = referencePlayer->GetGroup())
3110 for (GroupReference const& itr : group->GetMembers())
3111 if (itr.GetSource() != referencePlayer && *referencePlayer->m_playerData->VirtualPlayerRealm == *itr.GetSource()->m_playerData->VirtualPlayerRealm)
3112 ++memberCount;
3113 if (memberCount < reqValue)
3114 return false;
3115 break;
3116 }
3118 {
3119 Item const* artifact = referencePlayer->GetItemByEntry(secondaryAsset, ItemSearchLocation::Everywhere);
3120 if (!artifact)
3121 return false;
3122 if (artifact->GetTotalUnlockedArtifactPowers() < reqValue)
3123 return false;
3124 break;
3125 }
3127 if (referencePlayer->GetReputationMgr().GetParagonLevel(miscValue1) < int32(reqValue))
3128 return false;
3129 return false;
3131 return false;
3133 {
3134 BattlemasterListEntry const* bg = sBattlemasterListStore.LookupEntry(referencePlayer->GetBattlegroundTypeId());
3135 if (!bg || !(bg->GetFlags().HasFlag(BattlemasterListFlags::IsBrawl)))
3136 return false;
3137 break;
3138 }
3140 {
3141 FactionEntry const* faction = sFactionStore.LookupEntry(secondaryAsset);
3142 if (!faction)
3143 return false;
3144 if (referencePlayer->GetReputationMgr().GetParagonLevel(faction->ParagonFactionID) < int32(reqValue))
3145 return false;
3146 break;
3147 }
3149 {
3150 std::vector<int32> bonusListIDs = ItemBonusMgr::GetAllBonusListsForTree(reqValue);
3151 if (bonusListIDs.empty())
3152 return false;
3153
3154 bool bagScanReachedEnd = referencePlayer->ForEachItem(ItemSearchLocation::Everywhere, [&bonusListIDs](Item const* item)
3155 {
3156 bool hasBonus = std::any_of(item->GetBonusListIDs().begin(), item->GetBonusListIDs().end(), [&bonusListIDs](int32 bonusListID)
3157 {
3158 return std::find(bonusListIDs.begin(), bonusListIDs.end(), bonusListID) != bonusListIDs.end();
3159 });
3161 });
3162 if (bagScanReachedEnd)
3163 return false;
3164 break;
3165 }
3167 if (referencePlayer->GetFreeInventorySlotCount(ItemSearchLocation::Inventory) < reqValue)
3168 return false;
3169 break;
3171 return false;
3173 {
3174 Aura const* artifactAura = referencePlayer->GetAura(ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE);
3175 if (!artifactAura)
3176 return false;
3177 Item const* artifact = referencePlayer->GetItemByGuid(artifactAura->GetCastItemGUID());
3178 if (!artifact)
3179 return false;
3180 UF::ArtifactPower const* artifactPower = artifact->GetArtifactPower(secondaryAsset);
3181 if (!artifactPower)
3182 return false;
3183 if (artifactPower->PurchasedRank < reqValue)
3184 return false;
3185 break;
3186 }
3188 if (referencePlayer->HasLevelBoosted())
3189 return false;
3190 break;
3192 if (referencePlayer->HasRaceChanged())
3193 return false;
3194 break;
3196 if (referencePlayer->HasBeenGrantedLevelsFromRaF())
3197 return false;
3198 break;
3200 return false;
3202 if (!referencePlayer->GetSession()->CanAccessAlliedRaces())
3203 return false;
3204 break;
3206 {
3207 if (Group const* group = referencePlayer->GetGroup())
3208 {
3209 uint32 membersWithAchievement = 0;
3210 for (GroupReference const& itr : group->GetMembers())
3211 if (itr.GetSource()->HasAchieved(secondaryAsset))
3212 ++membersWithAchievement;
3213
3214 if (membersWithAchievement > reqValue)
3215 return false;
3216 }
3217 // true if no group
3218 break;
3219 }
3221 {
3222 UF::VisibleItem const& visibleItem = referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_MAINHAND];
3224 if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(visibleItem.ItemID))
3225 {
3226 if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
3227 {
3228 itemSubclass = itemTemplate->GetSubClass();
3229
3230 if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(visibleItem.ItemModifiedAppearanceID))
3231 if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
3232 itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
3233 }
3234 }
3235 if (itemSubclass != reqValue)
3236 return false;
3237 break;
3238 }
3240 {
3241 UF::VisibleItem const& visibleItem = referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_OFFHAND];
3243 if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(visibleItem.ItemID))
3244 {
3245 if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
3246 {
3247 itemSubclass = itemTemplate->GetSubClass();
3248
3249 if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(visibleItem.ItemModifiedAppearanceID))
3250 if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
3251 itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
3252 }
3253 }
3254 if (itemSubclass != reqValue)
3255 return false;
3256 break;
3257 }
3259 {
3260 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(reqValue);
3261 if (!pvpTier)
3262 return false;
3263 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(pvpTier->BracketID);
3264 if (!pvpInfo)
3265 return false;
3266 if (pvpTier->ID != pvpInfo->PvpTierID)
3267 return false;
3268 break;
3269 }
3271 {
3272 Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
3273 if (!heartOfAzeroth || heartOfAzeroth->ToAzeriteItem()->GetLevel() < reqValue)
3274 return false;
3275 break;
3276 }
3278 {
3279 if (!QuestMgr::IsQuestLineQuestActiveForPlayer(reqValue, referencePlayer))
3280 return false;
3281 break;
3282 }
3284 return false; // OBSOLETE (db2 removed)
3286 {
3287 Group const* group = referencePlayer->GetGroup();
3288 if (!group || !group->isRaidGroup())
3289 return false;
3290 break;
3291 }
3293 {
3294 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(secondaryAsset);
3295 if (!pvpInfo)
3296 return false;
3297 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(pvpInfo->PvpTierID);
3298 if (!pvpTier)
3299 return false;
3300 if (pvpTier->Rank < int32(reqValue))
3301 return false;
3302 break;
3303 }
3305 {
3306 if (!QuestMgr::IsQuestLineQuestAvailableForPlayer(reqValue, referencePlayer))
3307 return false;
3308 break;
3309 }
3311 {
3312 if (!QuestMgr::IsQuestLineCompletedByPlayer(reqValue, referencePlayer))
3313 return false;
3314 break;
3315 }
3317 {
3318 if (QuestMgr::GetQuestLineStatsForPlayer(reqValue, referencePlayer).Completed < reqValue)
3319 return false;
3320 break;
3321 }
3323 {
3324 QuestMgr::QuestLineStats questLineStats = QuestMgr::GetQuestLineStatsForPlayer(reqValue, referencePlayer);
3325 if (GetPctOf(questLineStats.Completed, questLineStats.Total) < reqValue)
3326 return false;
3327 break;
3328 }
3330 if (!referencePlayer->HasPlayerLocalFlag(PLAYER_LOCAL_FLAG_WAR_MODE))
3331 return false;
3332 break;
3334 if (!referencePlayer->HasPlayerFlag(PLAYER_FLAGS_WAR_MODE_ACTIVE))
3335 return false;
3336 break;
3338 if (!referencePlayer->CanEnableWarModeInArea())
3339 return false;
3340 break;
3346 return false;
3348 {
3349 CreatureDisplayInfoEntry const* creatureDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(referencePlayer->GetDisplayId());
3350 if (!creatureDisplayInfo)
3351 return false;
3352 CreatureDisplayInfoExtraEntry const* creatureDisplayInfoExtra = sCreatureDisplayInfoExtraStore.LookupEntry(creatureDisplayInfo->ExtendedDisplayInfoID);
3353 if (!creatureDisplayInfoExtra)
3354 return false;
3355 if (uint32(creatureDisplayInfoExtra->DisplayRaceID) != reqValue)
3356 return false;
3357 break;
3358 }
3360 {
3361 if (!ref || !ref->IsUnit())
3362 return false;
3363 CreatureDisplayInfoEntry const* creatureDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(ref->ToUnit()->GetDisplayId());
3364 if (!creatureDisplayInfo)
3365 return false;
3366 CreatureDisplayInfoExtraEntry const* creatureDisplayInfoExtra = sCreatureDisplayInfoExtraStore.LookupEntry(creatureDisplayInfo->ExtendedDisplayInfoID);
3367 if (!creatureDisplayInfoExtra)
3368 return false;
3369 if (uint32(creatureDisplayInfoExtra->DisplayRaceID) != reqValue)
3370 return false;
3371 break;
3372 }
3374 {
3375 FriendshipRepReactionEntry const* friendshipRepReaction = sFriendshipRepReactionStore.LookupEntry(reqValue);
3376 if (!friendshipRepReaction)
3377 return false;
3378 FriendshipReputationEntry const* friendshipReputation = sFriendshipReputationStore.LookupEntry(friendshipRepReaction->FriendshipRepID);
3379 if (!friendshipReputation)
3380 return false;
3381 DB2Manager::FriendshipRepReactionSet const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(reqValue);
3382 if (!friendshipReactions)
3383 return false;
3384 uint32 rank = referencePlayer->GetReputationRank(friendshipReputation->FactionID);
3385 if (rank >= friendshipReactions->size())
3386 return false;
3387 auto itr = friendshipReactions->begin();
3388 std::advance(itr, rank);
3389 if ((*itr)->ID != reqValue)
3390 return false;
3391 break;
3392 }
3394 if (referencePlayer->GetAuraCount(secondaryAsset) != reqValue)
3395 return false;
3396 break;
3398 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetAuraCount(secondaryAsset) != reqValue)
3399 return false;
3400 break;
3402 if (referencePlayer->GetAuraCount(secondaryAsset) < reqValue)
3403 return false;
3404 break;
3406 if (!ref || !ref->IsUnit() || ref->ToUnit()->GetAuraCount(secondaryAsset) < reqValue)
3407 return false;
3408 break;
3410 {
3411 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3412 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3413 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3414 if (essence.AzeriteEssenceID == reqValue && essence.Rank < secondaryAsset)
3415 return true;
3416 return false;
3417 }
3419 {
3420 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3421 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3422 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3423 if (essence.AzeriteEssenceID == reqValue && essence.Rank == secondaryAsset)
3424 return true;
3425 return false;
3426 }
3428 {
3429 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3430 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3431 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3432 if (essence.AzeriteEssenceID == reqValue && essence.Rank > secondaryAsset)
3433 return true;
3434 return false;
3435 }
3437 if (!referencePlayer->GetAuraEffect(reqValue, secondaryAsset))
3438 return false;
3439 break;
3441 {
3442 ChrSpecializationEntry const* spec = referencePlayer->GetPrimarySpecializationEntry();
3443 if (!spec || spec->Role != int32(reqValue))
3444 return false;
3445 break;
3446 }
3448 if (!referencePlayer->IsMaxLevel())
3449 return false;
3450 break;
3452 {
3453 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(miscValue2);
3454 if (!itemModifiedAppearance)
3455 return false;
3456 if (itemModifiedAppearance->TransmogSourceTypeEnum != int32(reqValue))
3457 return false;
3458 break;
3459 }
3461 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3462 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3463 if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
3464 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3465 if (essence.AzeriteEssenceID == selectedEssences->AzeriteEssenceID[reqValue] && essence.Rank < secondaryAsset)
3466 return true;
3467 return false;
3469 if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
3470 if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
3471 if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
3472 for (UF::UnlockedAzeriteEssence const& essence : azeriteItem->m_azeriteItemData->UnlockedEssences)
3473 if (essence.AzeriteEssenceID == selectedEssences->AzeriteEssenceID[reqValue] && essence.Rank > secondaryAsset)
3474 return true;
3475 return false;
3477 {
3478 uint8 level = referencePlayer->GetLevel();
3479 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, {}))
3480 {
3481 if (secondaryAsset)
3482 return level >= levels->MinLevelWithDelta && level <= levels->MaxLevelWithDelta;
3483 return level >= levels->MinLevel && level <= levels->MaxLevel;
3484 }
3485 return false;
3486 }
3488 {
3489 if (!ref || !ref->IsUnit())
3490 return false;
3491 uint8 level = ref->ToUnit()->GetLevel();
3492 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, {}))
3493 {
3494 if (secondaryAsset)
3495 return level >= levels->MinLevelWithDelta && level <= levels->MaxLevelWithDelta;
3496 return level >= levels->MinLevel && level <= levels->MaxLevel;
3497 }
3498 return false;
3499 }
3501 return false;
3503 {
3504 QuestStatus status = referencePlayer->GetQuestStatus(reqValue);
3505 if (status == QUEST_STATUS_NONE || status == QUEST_STATUS_FAILED)
3506 return false;
3507 break;
3508 }
3510 {
3511 uint8 level = referencePlayer->GetLevel();
3512 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, {}))
3513 return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel;
3514 return false;
3515 }
3517 {
3518 if (!ref || !ref->IsUnit())
3519 return false;
3520 uint8 level = ref->ToUnit()->GetLevel();
3521 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, {}))
3522 return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel;
3523 return false;
3524 }
3527 return false;
3529 if (referencePlayer->m_activePlayerData->JailersTowerLevelMax < int32(reqValue))
3530 return false;
3531 break;
3533 {
3534 Group const* group = referencePlayer->GetGroup();
3535 if (!group)
3536 return false;
3537 for (GroupReference const& itr : group->GetMembers())
3538 if (itr.GetSource()->GetSession()->GetRecruiterId() == referencePlayer->GetSession()->GetAccountId())
3539 return true;
3540 return false;
3541 }
3543 {
3544 Group const* group = referencePlayer->GetGroup();
3545 if (!group)
3546 return false;
3547 for (GroupReference const& itr : group->GetMembers())
3548 if (itr.GetSource()->GetSession()->GetAccountId() == referencePlayer->GetSession()->GetRecruiterId())
3549 return true;
3550 return false;
3551 }
3553 if (referencePlayer->GetPrimarySpecialization() != ChrSpecialization(reqValue))
3554 return false;
3555 break;
3557 {
3558 MapEntry const* map = referencePlayer->GetMap()->GetEntry();
3559 if (map->ID != reqValue && map->CosmeticParentMapID != int32(reqValue))
3560 return false;
3561 break;
3562 }
3564 if (referencePlayer->GetSession()->GetAccountExpansion() < EXPANSION_SHADOWLANDS)
3565 return false;
3566 break;
3570 case ModifierTreeType::HonorGainSource: // 285 NYI
3573 return false;
3575 if (referencePlayer->m_playerData->CovenantID != int32(reqValue))
3576 return false;
3577 break;
3579 {
3580 time_t eventTimestamp = GameTime::GetGameTime();
3581 switch (reqValue)
3582 {
3583 case 111: // Battle for Azeroth Season 4 Start
3584 eventTimestamp = time_t(1579618800); // January 21, 2020 8:00
3585 break;
3586 case 120: // Patch 9.0.1
3587 eventTimestamp = time_t(1602601200); // October 13, 2020 8:00
3588 break;
3589 case 121: // Shadowlands Season 1 Start
3590 eventTimestamp = time_t(1607439600); // December 8, 2020 8:00
3591 break;
3592 case 123: // Shadowlands Season 1 End
3593 // timestamp = unknown
3594 break;
3595 case 149: // Shadowlands Season 2 End
3596 // timestamp = unknown
3597 break;
3598 case 349: // Dragonflight Season 3 Start (pre-season)
3599 eventTimestamp = time_t(1699340400); // November 7, 2023 8:00
3600 break;
3601 case 350: // Dragonflight Season 3 Start
3602 eventTimestamp = time_t(1699945200); // November 14, 2023 8:00
3603 break;
3604 case 352: // Dragonflight Season 3 End
3605 // eventTimestamp = time_t(); unknown
3606 break;
3607 default:
3608 break;
3609 }
3610 if (GameTime::GetGameTime() < eventTimestamp)
3611 return false;
3612 break;
3613 }
3615 return false;
3617 if (referencePlayer->m_playerData->SoulbindID != int32(reqValue))
3618 return false;
3619 break;
3621 return false;
3627 return false;
3629 {
3630 std::vector<uint32> areas = sDB2Manager.GetAreasForGroup(reqValue);
3631 for (uint32 areaInGroup : areas)
3632 if (DB2Manager::IsInArea(referencePlayer->GetAreaId(), areaInGroup))
3633 return true;
3634 return false;
3635 }
3637 {
3638 if (!ref)
3639 return false;
3640 std::vector<uint32> areas = sDB2Manager.GetAreasForGroup(reqValue);
3641 for (uint32 areaInGroup : areas)
3642 if (DB2Manager::IsInArea(ref->GetAreaId(), areaInGroup))
3643 return true;
3644 return false;
3645 }
3647 if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID != int32(reqValue))
3648 return false;
3649 break;
3651 if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID == 0)
3652 return false;
3653 break;
3655 if (!sDB2Manager.GetAzeriteEmpoweredItem(miscValue1))
3656 return false;
3657 break;
3659 {
3660 uint32 block = reqValue / 32;
3661 if (block >= referencePlayer->m_activePlayerData->RuneforgePowers.size())
3662 return false;
3663
3664 uint32 bit = reqValue % 32;
3665 return referencePlayer->m_activePlayerData->RuneforgePowers[block] & (1 << bit);
3666 }
3668 if (referencePlayer->m_playerData->CtrOptions->ConditionalFlags.empty() || !(referencePlayer->m_playerData->CtrOptions->ConditionalFlags[0] & 1))
3669 return false;
3670 break;
3672 if (!referencePlayer->GetSession()->GetRecruiterId())
3673 return false;
3674 break;
3676 {
3677 if (Group const* group = referencePlayer->GetGroup())
3678 {
3679 for (GroupReference const& itr : group->GetMembers())
3680 if (!itr.GetSource()->HasAchieved(reqValue))
3681 return false;
3682 }
3683 else if (!referencePlayer->HasAchieved(reqValue))
3684 return false;
3685 break;
3686 }
3688 return false;
3690 {
3691 ShapeshiftFormModelData const* formModelData = sDB2Manager.GetShapeshiftFormModelData(referencePlayer->GetRace(), referencePlayer->GetNativeGender(), secondaryAsset);
3692 if (!formModelData)
3693 return false;
3694 uint32 formChoice = referencePlayer->GetCustomizationChoice(formModelData->OptionID);
3695 auto choiceItr = std::find_if(formModelData->Choices->begin(), formModelData->Choices->end(), [formChoice](ChrCustomizationChoiceEntry const* choice)
3696 {
3697 return choice->ID == formChoice;
3698 });
3699 if (choiceItr == formModelData->Choices->end())
3700 return false;
3701 if (int32(reqValue) != formModelData->Displays[std::distance(formModelData->Choices->begin(), choiceItr)]->DisplayID)
3702 return false;
3703 break;
3704 }
3706 return false;
3708 return false;
3710 if (!referencePlayer->IsFlying())
3711 return false;
3712 break;
3714 {
3715 Scenario const* scenario = referencePlayer->GetScenario();
3716 if (!scenario)
3717 return false;
3718 if (scenario->GetStep() != scenario->GetLastStep())
3719 return false;
3720 break;
3721 }
3723 if (!*referencePlayer->m_activePlayerData->WeeklyRewardsPeriodSinceOrigin)
3724 return false;
3725 break;
3727 if (!ref || !ref->IsPlayer())
3728 return false;
3729 if (ref->ToPlayer()->m_playerData->CovenantID != int32(reqValue))
3730 return false;
3731 break;
3734 return false;
3741 return false;
3743 {
3744 int32 customizationChoiceIndex = referencePlayer->m_playerData->Customizations.FindIndexIf([reqValue](UF::ChrCustomizationChoice const& choice)
3745 {
3746 return choice.ChrCustomizationChoiceID == reqValue;
3747 });
3748 if (customizationChoiceIndex < 0)
3749 return false;
3750 break;
3751 }
3753 {
3754 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(reqValue);
3755 if (!pvpTier)
3756 return false;
3757 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(pvpTier->BracketID);
3758 if (!pvpInfo)
3759 return false;
3760 if (pvpTier->ID != pvpInfo->WeeklyBestWinPvpTierID)
3761 return false;
3762 break;
3763 }
3765 {
3766 UF::PVPInfo const* pvpInfo = referencePlayer->GetPvpInfoForBracket(secondaryAsset);
3767 if (!pvpInfo)
3768 return false;
3769 PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(pvpInfo->WeeklyBestWinPvpTierID);
3770 if (!pvpTier)
3771 return false;
3772 if (pvpTier->Rank < int32(reqValue))
3773 return false;
3774 break;
3775 }
3777 return false;
3779 {
3780 bool bagScanReachedEnd = referencePlayer->ForEachItem(ItemSearchLocation::Inventory, [reqValue, secondaryAsset](Item const* item)
3781 {
3782 if (item->GetEntry() != reqValue)
3784
3785 if (item->GetModifier(ITEM_MODIFIER_CHALLENGE_KEYSTONE_LEVEL) < secondaryAsset)
3787
3789 });
3790 if (bagScanReachedEnd)
3791 return false;
3792 break;
3793 }
3795 {
3796 uint32 count = 0;
3797 referencePlayer->HasAura([secondaryAsset, &count](Aura const* aura)
3798 {
3799 if (aura->GetSpellInfo()->HasLabel(secondaryAsset))
3800 count += aura->GetStackAmount();
3801 return false;
3802 });
3803 if (count < reqValue)
3804 return false;
3805 break;
3806 }
3808 {
3809 uint32 count = 0;
3810 referencePlayer->HasAura([secondaryAsset, &count](Aura const* aura)
3811 {
3812 if (aura->GetSpellInfo()->HasLabel(secondaryAsset))
3813 count += aura->GetStackAmount();
3814 return false;
3815 });
3816 if (count != reqValue)
3817 return false;
3818 break;
3819 }
3821 {
3822 uint32 count = 0;
3823 referencePlayer->HasAura([secondaryAsset, &count](Aura const* aura)
3824 {
3825 if (aura->GetSpellInfo()->HasLabel(secondaryAsset))
3826 count += aura->GetStackAmount();
3827 return false;
3828 });
3829 if (count > reqValue)
3830 return false;
3831 break;
3832 }
3834 {
3835 Group const* group = referencePlayer->GetGroup();
3836 if (!(group->GetGroupFlags() & GROUP_FLAG_CROSS_FACTION))
3837 return false;
3838 break;
3839 }
3841 {
3842 auto hasTraitNodeEntry = [referencePlayer, reqValue]
3843 {
3844 UF::TraitConfig const* config = referencePlayer->GetTraitConfig(referencePlayer->m_activePlayerData->ActiveCombatTraitConfigID);
3846 for (UF::TraitEntry const& traitEntry : config->Entries)
3847 if (traitEntry.TraitNodeEntryID == int32(reqValue))
3848 return true;
3849
3850 return false;
3851 }();
3852 if (!hasTraitNodeEntry)
3853 return false;
3854 break;
3855 }
3857 {
3858 auto traitNodeEntryRank = [referencePlayer, secondaryAsset]() -> Optional<uint16>
3859 {
3860 UF::TraitConfig const* config = referencePlayer->GetTraitConfig(referencePlayer->m_activePlayerData->ActiveCombatTraitConfigID);
3862 for (UF::TraitEntry const& traitEntry : config->Entries)
3863 if (traitEntry.TraitNodeEntryID == int32(secondaryAsset))
3864 return traitEntry.Rank;
3865
3866 return {};
3867 }();
3868 if (!traitNodeEntryRank || traitNodeEntryRank < int32(reqValue))
3869 return false;
3870 break;
3871 }
3873 if (GameTime::GetGameTime() - referencePlayer->m_playerData->LogoutTime < int64(reqValue) * DAY)
3874 return false;
3875 break;
3877 if (!referencePlayer->m_activePlayerData->HasPerksProgramPendingReward)
3878 return false;
3879 break;
3881 {
3882 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(reqValue);
3883 if (!itemTemplate || !referencePlayer->CanUseItem(itemTemplate))
3884 return false;
3885 break;
3886 }
3888 if (referencePlayer->m_playerData->CurrentBattlePetSpeciesID != int32(reqValue))
3889 return false;
3890 break;
3892 if (referencePlayer->m_unitData->WildBattlePetLevel != BattlePets::MAX_BATTLE_PET_LEVEL)
3893 return false;
3894 break;
3896 {
3897 uint32 traitNodeEntryRankCount = [referencePlayer, secondaryAsset]
3898 {
3899 uint32 ranks = 0;
3900 for (auto const& [_, traitConfig] : referencePlayer->m_activePlayerData->TraitConfigs)
3901 {
3902 if (TraitConfigType(*traitConfig.value.Type) != TraitConfigType::Profession)
3903 continue;
3904
3905 if (*traitConfig.value.SkillLineID != int32(secondaryAsset))
3906 continue;
3907
3908 for (UF::TraitEntry const& traitEntry : traitConfig.value.Entries)
3909 if (sTraitNodeEntryStore.AssertEntry(traitEntry.TraitNodeEntryID)->GetNodeEntryType() == TraitNodeEntryType::ProfPath)
3910 ranks += traitEntry.Rank + traitEntry.GrantedRanks;
3911 }
3912 return ranks;
3913 }();
3914 if (traitNodeEntryRankCount < reqValue)
3915 return false;
3916 break;
3917 }
3919 {
3920 ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(reqValue);
3921
3922 bool bagScanReachedEnd = referencePlayer->ForEachItem(ItemSearchLocation::Inventory, [referencePlayer, itemModifiedAppearance](Item const* item)
3923 {
3924 if (item->GetVisibleAppearanceModId(referencePlayer) == itemModifiedAppearance->ID)
3926
3927 if (item->GetEntry() == itemModifiedAppearance->ItemID)
3929
3931 });
3932 if (bagScanReachedEnd)
3933 return false;
3934 break;
3935 }
3937 if (!referencePlayer->IsLockedToDungeonEncounter(reqValue, Difficulty(secondaryAsset)))
3938 return false;
3939 break;
3941 {
3942 QuestStatus status = referencePlayer->GetQuestStatus(reqValue);
3943 if (status == QUEST_STATUS_NONE || status == QUEST_STATUS_FAILED)
3944 return false;
3945 if (referencePlayer->IsQuestRewarded(secondaryAsset))
3946 return false;
3947 break;
3948 }
3950 {
3951 Scenario const* scenario = referencePlayer->GetScenario();
3952 if (!scenario)
3953 return false;
3954 if (scenario->GetStep()->ID != reqValue)
3955 return false;
3956 break;
3957 }
3959 if (referencePlayer->GetPositionZ() >= reqValue)
3960 return false;
3961 break;
3963 if (!referencePlayer->HasDataFlagAccount(reqValue))
3964 return false;
3965 break;
3967 if (!referencePlayer->HasDataFlagCharacter(reqValue))
3968 return false;
3969 break;
3971 {
3972 MapEntry const* mapEntry = referencePlayer->GetMap()->GetEntry();
3973 if (mapEntry->ExpansionID != reqValue)
3974 return false;
3975 break;
3976 }
3978 {
3979 int32 const* traitConfigWithSubtree = referencePlayer->m_activePlayerData->TraitConfigs.FindIf([referencePlayer, reqValue](UF::TraitConfig const& traitConfig)
3980 {
3981 if (TraitConfigType(*traitConfig.Type) == TraitConfigType::Combat
3982 && (int32(*referencePlayer->m_activePlayerData->ActiveCombatTraitConfigID) != traitConfig.ID
3984 return false;
3985
3986 return traitConfig.SubTrees.FindIndexIf([reqValue](UF::TraitSubTreeCache const& traitSubTree)
3987 {
3988 return traitSubTree.TraitSubTreeID == int32(reqValue) && traitSubTree.Active;
3989 }) >= 0;
3990 }).first;
3991 if (!traitConfigWithSubtree)
3992 return false;
3993 break;
3994 }
3996 if (referencePlayer->m_activePlayerData->TimerunningSeasonID != int32(reqValue))
3997 return false;
3998 break;
4000 if (!QuestMgr::IsCampaignCompletedByPlayer(reqValue, referencePlayer))
4001 return false;
4002 break;
4004 {
4005 Creature const* targetCreature = Object::ToCreature(ref);
4006 if (!targetCreature)
4007 return false;
4008 if (targetCreature->GetCreatureClassification() != CreatureClassifications(reqValue))
4009 return false;
4010 break;
4011 }
4013 return std::visit([&]<typename T>(T value) { return value >= T(secondaryAsset) && value <= T(tertiaryAsset); },
4014 referencePlayer->GetDataElementCharacter(reqValue));
4016 return std::visit([&]<typename T>(T value) { return value >= T(secondaryAsset) && value <= T(tertiaryAsset); },
4017 referencePlayer->GetDataElementAccount(reqValue));
4019 {
4020 QuestStatus status = referencePlayer->GetQuestStatus(reqValue);
4021 if (status != QUEST_STATUS_COMPLETE && status != QUEST_STATUS_REWARDED)
4022 return false;
4023 break;
4024 }
4026 if (referencePlayer->m_playerData->PlayerTitle != int32(reqValue))
4027 return false;
4028 break;
4030 if (!referencePlayer->GetGuildId())
4031 return false;
4032 break;
4034 switch (reqValue)
4035 {
4036 case 1: if (referencePlayer->GetMoney() <= secondaryAsset) return false; break;
4037 case 2: if (referencePlayer->GetMoney() >= secondaryAsset) return false; break;
4038 case 3: if (referencePlayer->GetMoney() < secondaryAsset) return false; break;
4039 case 4: if (referencePlayer->GetMoney() > secondaryAsset) return false; break;
4040 default: if (referencePlayer->GetMoney() != secondaryAsset) return false; break;
4041 }
4042 break;
4043 default:
4044 return false;
4045 }
4046 return true;
4047}
4048
4050
4052{
4053 return GetCriteriaTypeString(CriteriaType(type));
4054}
4055
4057{
4058 switch (type)
4059 {
4061 return "KillCreature";
4063 return "WinBattleground";
4065 return "CompleteResearchProject";
4067 return "CompleteAnyResearchProject";
4069 return "FindResearchObject";
4071 return "ReachLevel";
4073 return "ExhaustAnyResearchSite";
4075 return "SkillRaised";
4077 return "EarnAchievement";
4079 return "CompleteQuestsCount";
4081 return "CompleteAnyDailyQuestPerDay";
4083 return "CompleteQuestsInZone";
4085 return "CurrencyGained";
4087 return "DamageDealt";
4089 return "CompleteDailyQuest";
4091 return "ParticipateInBattleground";
4093 return "DieOnMap";
4095 return "DieAnywhere";
4097 return "DieInInstance";
4099 return "RunInstance";
4101 return "KilledByCreature";
4103 return "CompleteInternalCriteria";
4105 return "CompleteAnyChallengeMode";
4107 return "KilledByPlayer";
4109 return "MaxDistFallenWithoutDying";
4111 return "EarnChallengeModeMedal";
4113 return "DieFromEnviromentalDamage";
4115 return "CompleteQuest";
4117 return "BeSpellTarget";
4119 return "CastSpell";
4121 return "TrackedWorldStateUIModified";
4123 return "PVPKillInArea";
4125 return "WinArena";
4127 return "ParticipateInArena";
4129 return "LearnOrKnowSpell";
4131 return "EarnHonorableKill";
4133 return "AcquireItem";
4135 return "WinAnyRankedArena";
4137 return "EarnTeamArenaRating";
4139 return "EarnPersonalArenaRating";
4141 return "AchieveSkillStep";
4143 return "UseItem";
4145 return "LootItem";
4147 return "RevealWorldMapOverlay";
4149 return "EarnTitle";
4151 return "BankSlotsPurchased";
4153 return "ReputationGained";
4155 return "TotalExaltedFactions";
4157 return "GotHaircut";
4159 return "EquipItemInSlot";
4161 return "RollNeed";
4163 return "RollGreed";
4165 return "DeliverKillingBlowToClass";
4167 return "DeliverKillingBlowToRace";
4169 return "DoEmote";
4171 return "HealingDone";
4173 return "DeliveredKillingBlow";
4175 return "EquipItem";
4177 return "CompleteQuestsInSort";
4179 return "MoneyEarnedFromSales";
4181 return "MoneySpentOnRespecs";
4183 return "TotalRespecs";
4185 return "MoneyEarnedFromQuesting";
4187 return "MoneySpentOnTaxis";
4189 return "KilledAllUnitsInSpawnRegion";
4191 return "MoneySpentAtBarberShop";
4193 return "MoneySpentOnPostage";
4195 return "MoneyLootedFromCreatures";
4197 return "UseGameobject";
4199 return "GainAura";
4201 return "KillPlayer";
4203 return "CompleteChallengeMode";
4205 return "CatchFishInFishingHole";
4207 return "PlayerTriggerGameEvent";
4209 return "Login";
4211 return "LearnSpellFromSkillLine";
4213 return "WinDuel";
4215 return "LoseDuel";
4217 return "KillAnyCreature";
4219 return "CreatedItemsByCastingSpellWithLimit";
4221 return "MoneyEarnedFromAuctions";
4223 return "BattlePetAchievementPointsEarned";
4225 return "ItemsPostedAtAuction";
4227 return "HighestAuctionBid";
4229 return "AuctionsWon";
4231 return "HighestAuctionSale";
4233 return "MostMoneyOwned";
4235 return "TotalReveredFactions";
4237 return "TotalHonoredFactions";
4239 return "TotalFactionsEncountered";
4241 return "LootAnyItem";
4243 return "ObtainAnyItem";
4245 return "AnyoneTriggerGameEventScenario";
4247 return "RollAnyNeed";
4249 return "RollAnyGreed";
4251 return "ReleasedSpirit";
4253 return "AccountKnownPet";
4255 return "DefeatDungeonEncounterWhileElegibleForLoot";
4257 return "HighestDamageDone";
4259 return "HighestDamageTaken";
4261 return "TotalDamageTaken";
4263 return "HighestHealCast";
4265 return "TotalHealReceived";
4267 return "HighestHealReceived";
4269 return "AbandonAnyQuest";
4271 return "BuyTaxi";
4273 return "GetLootByType";
4275 return "LandTargetedSpellOnTarget";
4277 return "LearnTradeskillSkillLine";
4279 return "HonorableKills";
4281 return "AcceptSummon";
4283 return "EarnAchievementPoints";
4285 return "RollDisenchant";
4287 return "RollAnyDisenchant";
4289 return "CompletedLFGDungeon";
4291 return "CompletedLFGDungeonWithStrangers";
4293 return "KickInitiatorInLFGDungeon";
4295 return "KickVoterInLFGDungeon";
4297 return "KickTargetInLFGDungeon";
4299 return "AbandonedLFGDungeon";
4301 return "MoneySpentOnGuildRepair";
4303 return "GuildAttainedLevel";
4305 return "CreatedItemsByCastingSpell";
4307 return "FishInAnyPool";
4309 return "GuildBankTabsPurchased";
4311 return "EarnGuildAchievementPoints";
4313 return "WinAnyBattleground";
4315 return "ParticipateInAnyBattleground";
4317 return "EarnBattlegroundRating";
4319 return "GuildTabardCreated";
4321 return "CompleteQuestsCountForGuild";
4323 return "HonorableKillsForGuild";
4325 return "KillAnyCreatureForGuild";
4327 return "GroupedTankLeftEarlyInLFGDungeon";
4329 return "CompleteGuildChallenge";
4331 return "CompleteAnyGuildChallenge";
4333 return "MarkedAFKInBattleground";
4335 return "RemovedAFKInBattleground";
4337 return "StartAnyBattleground";
4339 return "CompleteAnyBattleground";
4341 return "MarkedSomeoneAFKInBattleground";
4343 return "CompletedLFRDungeon";
4345 return "AbandonedLFRDungeon";
4347 return "KickInitiatorInLFRDungeon";
4349 return "KickVoterInLFRDungeon";
4351 return "KickTargetInLFRDungeon";
4353 return "GroupedTankLeftEarlyInLFRDungeon";
4355 return "CompleteAnyScenario";
4357 return "CompleteScenario";
4359 return "EnterAreaTriggerWithActionSet";
4361 return "LeaveAreaTriggerWithActionSet";
4363 return "LearnedNewPet";
4365 return "UniquePetsOwned";
4367 return "AccountObtainPetThroughBattle";
4369 return "WinPetBattle";
4371 return "LosePetBattle";
4373 return "BattlePetReachLevel";
4375 return "PlayerObtainPetThroughBattle";
4377 return "ActivelyEarnPetLevel";
4379 return "EnterArea";
4381 return "LeaveArea";
4383 return "DefeatDungeonEncounter";
4385 return "PlaceAnyGarrisonBuilding";
4387 return "PlaceGarrisonBuilding";
4389 return "ActivateAnyGarrisonBuilding";
4391 return "ActivateGarrisonBuilding";
4393 return "UpgradeGarrison";
4395 return "StartAnyGarrisonMissionWithFollowerType";
4397 return "StartGarrisonMission";
4399 return "SucceedAnyGarrisonMissionWithFollowerType";
4401 return "SucceedGarrisonMission";
4403 return "RecruitAnyGarrisonFollower";
4405 return "RecruitGarrisonFollower";
4407 return "AcquireGarrison";
4409 return "LearnAnyGarrisonBlueprint";
4411 return "LearnGarrisonBlueprint";
4413 return "LearnAnyGarrisonSpecialization";
4415 return "LearnGarrisonSpecialization";
4417 return "CollectGarrisonShipment";
4419 return "ItemLevelChangedForGarrisonFollower";
4421 return "LevelChangedForGarrisonFollower";
4423 return "LearnToy";
4425 return "LearnAnyToy";
4427 return "QualityUpgradedForGarrisonFollower";
4429 return "LearnHeirloom";
4431 return "LearnAnyHeirloom";
4433 return "EarnArtifactXP";
4435 return "AnyArtifactPowerRankPurchased";
4437 return "LearnTransmog";
4439 return "LearnAnyTransmog";
4441 return "HonorLevelIncrease";
4443 return "PrestigeLevelIncrease";
4445 return "ActivelyReachLevel";
4447 return "CompleteResearchAnyGarrisonTalent";
4449 return "CompleteResearchGarrisonTalent";
4451 return "LearnAnyTransmogInSlot";
4453 return "RecruitAnyGarrisonTroop";
4455 return "StartResearchAnyGarrisonTalent";
4457 return "StartResearchGarrisonTalent";
4459 return "CompleteAnyWorldQuest";
4461 return "EarnLicense";
4463 return "CollectTransmogSetFromGroup";
4465 return "ParagonLevelIncreaseWithFaction";
4467 return "PlayerHasEarnedHonor";
4469 return "KillCreatureScenario";
4471 return "ArtifactPowerRankPurchased";
4473 return "ChooseAnyRelicTalent";
4475 return "ChooseRelicTalent";
4477 return "EarnExpansionLevel";
4479 return "AccountHonorLevelReached";
4481 return "EarnArtifactXPForAzeriteItem";
4483 return "AzeriteLevelReached";
4485 return "MythicPlusCompleted";
4487 return "ScenarioGroupCompleted";
4489 return "CompleteAnyReplayQuest";
4491 return "BuyItemsFromVendors";
4493 return "SellItemsToVendors";
4495 return "ReachMaxLevel";
4497 return "MemorizeSpell";
4499 return "LearnTransmogIllusion";
4501 return "LearnAnyTransmogIllusion";
4503 return "EnterTopLevelArea";
4505 return "LeaveTopLevelArea";
4507 return "SocketGarrisonTalent";
4509 return "SocketAnySoulbindConduit";
4511 return "ObtainAnyItemWithCurrencyValue";
4513 return "MythicPlusRatingAttained";
4515 return "SpentTalentPoint";
4517 return "MythicPlusDisplaySeasonEnded";
4519 return "WinRatedSoloShuffleRound";
4521 return "ParticipateInRatedSoloShuffleRound";
4523 return "ReputationAmountGained";
4525 return "FulfillAnyCraftingOrder";
4527 return "FulfillCraftingOrderType";
4529 return "PerksProgramMonthComplete";
4531 return "CompleteTrackingQuest";
4533 return "GainLevels";
4535 return "CompleteQuestsCountOnAccount";
4537 return "BankTabPurchased";
4539 return "ReachRenownLevel";
4541 return "LearnTaxiNode";
4542 default:
4543 return "MissingType";
4544 }
4545}
4546
4548{
4549 static CriteriaMgr instance;
4550 return &instance;
4551}
4552
4553namespace
4554{
4555inline bool IsCriteriaTypeStoredByAsset(CriteriaType type)
4556{
4557 switch (type)
4558 {
4594 return true;
4595 default:
4596 break;
4597 }
4598 return false;
4599}
4600}
4601
4603{
4604 if (asset && IsCriteriaTypeStoredByAsset(type))
4605 {
4606 auto itr = _criteriasByAsset[size_t(type)].find(asset);
4607 if (itr != _criteriasByAsset[size_t(type)].end())
4608 return itr->second;
4609
4610 return EmptyCriteriaList;
4611 }
4612
4613 return _criteriasByType[size_t(type)];
4614}
4615
4617{
4618 if (CriteriaList const* criteriaList = Trinity::Containers::MapGetValuePtr(_scenarioCriteriasByTypeAndScenarioId[size_t(type)], scenarioId))
4619 return *criteriaList;
4620
4621 return EmptyCriteriaList;
4622}
4623
4628
4629std::unordered_map<int32, CriteriaList> const& CriteriaMgr::GetCriteriaByStartEvent(CriteriaStartEvent startEvent) const
4630{
4631 return _criteriasByStartEvent[size_t(startEvent)];
4632}
4633
4635{
4636 return Trinity::Containers::MapGetValuePtr(_criteriasByStartEvent[size_t(startEvent)], asset);
4637}
4638
4639std::unordered_map<int32, CriteriaList> const& CriteriaMgr::GetCriteriaByFailEvent(CriteriaFailEvent failEvent) const
4640{
4641 return _criteriasByFailEvent[size_t(failEvent)];
4642}
4643
4645{
4646 return Trinity::Containers::MapGetValuePtr(_criteriasByFailEvent[size_t(failEvent)], asset);
4647}
4648
4653
4654CriteriaMgr::CriteriaMgr() = default;
4655
4656//==========================================================
4658{
4659 for (std::pair<uint32 const, CriteriaTree*>& criteriaTree : _criteriaTrees)
4660 delete criteriaTree.second;
4661
4662 for (std::pair<uint32 const, Criteria*>& criteria : _criteria)
4663 delete criteria.second;
4664
4665 for (std::pair<uint32 const, ModifierTreeNode*>& criteriaModifier : _criteriaModifiers)
4666 delete criteriaModifier.second;
4667}
4668
4670{
4671 uint32 oldMSTime = getMSTime();
4672
4673 if (sModifierTreeStore.GetNumRows() == 0)
4674 {
4675 TC_LOG_ERROR("server.loading", ">> Loaded 0 criteria modifiers.");
4676 return;
4677 }
4678
4679 // Load modifier tree nodes
4680 for (uint32 i = 0; i < sModifierTreeStore.GetNumRows(); ++i)
4681 {
4682 ModifierTreeEntry const* tree = sModifierTreeStore.LookupEntry(i);
4683 if (!tree)
4684 continue;
4685
4686 ModifierTreeNode* node = new ModifierTreeNode();
4687 node->Entry = tree;
4688 _criteriaModifiers[node->Entry->ID] = node;
4689 }
4690
4691 // Build tree
4692 for (std::pair<uint32 const, ModifierTreeNode*>& criteriaModifier : _criteriaModifiers)
4693 if (ModifierTreeNode* parentNode = Trinity::Containers::MapGetValuePtr(_criteriaModifiers, criteriaModifier.second->Entry->Parent))
4694 parentNode->Children.push_back(criteriaModifier.second);
4695
4696 TC_LOG_INFO("server.loading", ">> Loaded {} criteria modifiers in {} ms", uint32(_criteriaModifiers.size()), GetMSTimeDiffToNow(oldMSTime));
4697}
4698
4699template<typename T>
4700T GetEntry(std::unordered_map<uint32, T> const& map, CriteriaTreeEntry const* tree)
4701{
4702 CriteriaTreeEntry const* cur = tree;
4703 auto itr = map.find(tree->ID);
4704 while (itr == map.end())
4705 {
4706 if (!cur->Parent)
4707 break;
4708
4709 cur = sCriteriaTreeStore.LookupEntry(cur->Parent);
4710 if (!cur)
4711 break;
4712
4713 itr = map.find(cur->ID);
4714 }
4715
4716 if (itr == map.end())
4717 return nullptr;
4718
4719 return itr->second;
4720}
4721
4723{
4724 uint32 oldMSTime = getMSTime();
4725
4726 std::unordered_map<uint32 /*criteriaTreeID*/, AchievementEntry const*> achievementCriteriaTreeIds;
4727 for (AchievementEntry const* achievement : sAchievementStore)
4728 if (achievement->CriteriaTree)
4729 achievementCriteriaTreeIds[achievement->CriteriaTree] = achievement;
4730
4731 std::unordered_map<uint32 /*criteriaTreeID*/, ScenarioStepEntry const*> scenarioCriteriaTreeIds;
4732 for (ScenarioStepEntry const* scenarioStep : sScenarioStepStore)
4733 if (scenarioStep->Criteriatreeid)
4734 scenarioCriteriaTreeIds[scenarioStep->Criteriatreeid] = scenarioStep;
4735
4736 std::unordered_map<uint32 /*criteriaTreeID*/, QuestObjective const*> questObjectiveCriteriaTreeIds;
4737 for (auto const& [questId, quest] : sObjectMgr->GetQuestTemplates())
4738 {
4739 for (QuestObjective const& objective : quest->Objectives)
4740 {
4741 if (objective.Type != QUEST_OBJECTIVE_CRITERIA_TREE)
4742 continue;
4743
4744 if (objective.ObjectID)
4745 questObjectiveCriteriaTreeIds[objective.ObjectID] = &objective;
4746 }
4747 }
4748
4749 // Load criteria tree nodes
4750 for (CriteriaTreeEntry const* tree : sCriteriaTreeStore)
4751 {
4752 // Find linked achievement
4753 AchievementEntry const* achievement = GetEntry(achievementCriteriaTreeIds, tree);
4754 ScenarioStepEntry const* scenarioStep = GetEntry(scenarioCriteriaTreeIds, tree);
4755 QuestObjective const* questObjective = GetEntry(questObjectiveCriteriaTreeIds, tree);
4756 if (!achievement && !scenarioStep && !questObjective)
4757 continue;
4758
4759 CriteriaTree* criteriaTree = new CriteriaTree();
4760 criteriaTree->ID = tree->ID;
4761 criteriaTree->Achievement = achievement;
4762 criteriaTree->ScenarioStep = scenarioStep;
4763 criteriaTree->QuestObjective = questObjective;
4764 criteriaTree->Entry = tree;
4765
4766 _criteriaTrees[criteriaTree->Entry->ID] = criteriaTree;
4767 }
4768
4769 // Build tree
4770 for (std::pair<uint32 const, CriteriaTree*> const& criteriaTree : _criteriaTrees)
4771 {
4772 if (CriteriaTree* parent = Trinity::Containers::MapGetValuePtr(_criteriaTrees, criteriaTree.second->Entry->Parent))
4773 parent->Children.push_back(criteriaTree.second);
4774
4775 if (sCriteriaStore.HasRecord(criteriaTree.second->Entry->CriteriaID))
4776 _criteriaTreeByCriteria[criteriaTree.second->Entry->CriteriaID].push_back(criteriaTree.second);
4777 }
4778
4779 // Load criteria
4780 uint32 criterias = 0;
4781 uint32 guildCriterias = 0;
4782 uint32 scenarioCriterias = 0;
4783 uint32 questObjectiveCriterias = 0;
4784 for (CriteriaEntry const* criteriaEntry : sCriteriaStore)
4785 {
4786 ASSERT(criteriaEntry->Type < AsUnderlyingType(CriteriaType::Count), "CriteriaType::Count must be greater than or equal to %u but is currently equal to %u",
4787 criteriaEntry->Type + 1, uint32(CriteriaType::Count));
4788 ASSERT(criteriaEntry->StartEvent < AsUnderlyingType(CriteriaStartEvent::Count), "CriteriaStartEvent::Count must be greater than or equal to %u but is currently equal to %u",
4789 criteriaEntry->StartEvent + 1, uint32(CriteriaStartEvent::Count));
4790 ASSERT(criteriaEntry->FailEvent < AsUnderlyingType(CriteriaFailEvent::Count), "CriteriaFailEvent::Count must be greater than or equal to %u but is currently equal to %u",
4791 criteriaEntry->FailEvent + 1, uint32(CriteriaFailEvent::Count));
4792
4793 auto treeItr = _criteriaTreeByCriteria.find(criteriaEntry->ID);
4794 if (treeItr == _criteriaTreeByCriteria.end())
4795 continue;
4796
4797 Criteria* criteria = new Criteria();
4798 criteria->ID = criteriaEntry->ID;
4799 criteria->Entry = criteriaEntry;
4800 criteria->Modifier = Trinity::Containers::MapGetValuePtr(_criteriaModifiers, criteriaEntry->ModifierTreeId);
4801
4802 _criteria[criteria->ID] = criteria;
4803
4804 std::vector<uint32> scenarioIds;
4805
4806 for (CriteriaTree const* tree : treeItr->second)
4807 {
4808 const_cast<CriteriaTree*>(tree)->Criteria = criteria;
4809
4810 if (AchievementEntry const* achievement = tree->Achievement)
4811 {
4812 if (achievement->Flags & ACHIEVEMENT_FLAG_GUILD)
4813 criteria->FlagsCu |= CRITERIA_FLAG_CU_GUILD;
4814 else if (achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT)
4815 criteria->FlagsCu |= CRITERIA_FLAG_CU_ACCOUNT;
4816 else
4817 criteria->FlagsCu |= CRITERIA_FLAG_CU_PLAYER;
4818 }
4819 else if (tree->ScenarioStep)
4820 {
4822 scenarioIds.push_back(tree->ScenarioStep->ScenarioID);
4823 }
4824 else if (tree->QuestObjective)
4826 }
4827
4829 {
4830 ++criterias;
4831 _criteriasByType[criteriaEntry->Type].push_back(criteria);
4832 if (IsCriteriaTypeStoredByAsset(CriteriaType(criteriaEntry->Type)))
4833 {
4834 if (CriteriaType(criteriaEntry->Type) != CriteriaType::RevealWorldMapOverlay)
4835 _criteriasByAsset[criteriaEntry->Type][criteriaEntry->Asset.ID].push_back(criteria);
4836 else
4837 {
4838 WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(criteriaEntry->Asset.WorldMapOverlayID);
4839 if (!worldOverlayEntry)
4840 break;
4841
4842 for (uint8 j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
4843 {
4844 if (worldOverlayEntry->AreaID[j])
4845 {
4846 bool valid = true;
4847 for (uint8 i = 0; i < j; ++i)
4848 if (worldOverlayEntry->AreaID[j] == worldOverlayEntry->AreaID[i])
4849 valid = false;
4850 if (valid)
4851 _criteriasByAsset[criteriaEntry->Type][worldOverlayEntry->AreaID[j]].push_back(criteria);
4852 }
4853 }
4854 }
4855 }
4856 }
4857
4858 if (criteria->FlagsCu & CRITERIA_FLAG_CU_GUILD)
4859 {
4860 ++guildCriterias;
4861 _guildCriteriasByType[criteriaEntry->Type].push_back(criteria);
4862 }
4863
4864 if (criteria->FlagsCu & CRITERIA_FLAG_CU_SCENARIO)
4865 {
4866 ++scenarioCriterias;
4867 for (uint32 scenarioId : scenarioIds)
4868 _scenarioCriteriasByTypeAndScenarioId[criteriaEntry->Type][scenarioId].push_back(criteria);
4869 }
4870
4872 {
4873 ++questObjectiveCriterias;
4874 _questObjectiveCriteriasByType[criteriaEntry->Type].push_back(criteria);
4875 }
4876
4877 if (criteriaEntry->StartEvent)
4878 _criteriasByStartEvent[criteriaEntry->StartEvent][criteriaEntry->StartAsset].push_back(criteria);
4879
4880 if (criteriaEntry->FailEvent)
4881 _criteriasByFailEvent[criteriaEntry->FailEvent][criteriaEntry->FailAsset].push_back(criteria);
4882 }
4883
4884 TC_LOG_INFO("server.loading", ">> Loaded {} criteria, {} guild criteria, {} scenario criteria and {} quest objective criteria in {} ms.", criterias, guildCriterias, scenarioCriterias, questObjectiveCriterias, GetMSTimeDiffToNow(oldMSTime));
4885}
4886
4888{
4889 uint32 oldMSTime = getMSTime();
4890
4891 _criteriaDataMap.clear(); // need for reload case
4892
4893 QueryResult result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM criteria_data");
4894
4895 if (!result)
4896 {
4897 TC_LOG_INFO("server.loading", ">> Loaded 0 additional criteria data. DB table `criteria_data` is empty.");
4898 return;
4899 }
4900
4901 uint32 count = 0;
4902
4903 do
4904 {
4905 Field* fields = result->Fetch();
4906 uint32 criteria_id = fields[0].GetUInt32();
4907
4908 Criteria const* criteria = GetCriteria(criteria_id);
4909
4910 if (!criteria)
4911 {
4912 TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains data for non-existing criteria (Entry: {}). Ignored.", criteria_id);
4913 continue;
4914 }
4915
4916 uint32 dataType = fields[1].GetUInt8();
4917 std::string_view scriptName = fields[4].GetStringView();
4918 uint32 scriptId = 0;
4919 if (!scriptName.empty())
4920 {
4921 if (dataType != CRITERIA_DATA_TYPE_SCRIPT)
4922 TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains a ScriptName for non-scripted data type (Entry: {}, type {}), useless data.", criteria_id, dataType);
4923 else
4924 scriptId = sObjectMgr->GetScriptId(scriptName);
4925 }
4926
4927 CriteriaData data(dataType, fields[2].GetUInt32(), fields[3].GetUInt32(), scriptId);
4928
4929 if (!data.IsValid(criteria))
4930 continue;
4931
4932 // this will allocate empty data set storage
4933 CriteriaDataSet& dataSet = _criteriaDataMap[criteria_id];
4934 dataSet.SetCriteriaId(criteria_id);
4935
4936 // add real data only for not NONE data types
4938 dataSet.Add(data);
4939
4940 // counting data by and data types
4941 ++count;
4942 }
4943 while (result->NextRow());
4944
4945 TC_LOG_INFO("server.loading", ">> Loaded {} additional criteria data in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
4946}
4947
4949{
4950 auto itr = _criteriaTrees.find(criteriaTreeId);
4951 if (itr == _criteriaTrees.end())
4952 return nullptr;
4953
4954 return itr->second;
4955}
4956
4958{
4959 auto itr = _criteria.find(criteriaId);
4960 if (itr == _criteria.end())
4961 return nullptr;
4962
4963 return itr->second;
4964}
4965
4967{
4968 auto itr = _criteriaModifiers.find(modifierTreeId);
4969 if (itr != _criteriaModifiers.end())
4970 return itr->second;
4971
4972 return nullptr;
4973}
4974
4976{
4977 static constexpr CriteriaType Types[] =
4978 {
4992 //CriteriaType::EarnTitle, /*NYI*/
4996 //CriteriaType::CompleteQuestsInSort, /*NYI*/
5002 //CriteriaType::AccountKnownPet, /*NYI*/
5005 //CriteriaType::GuildBankTabsPurchased, /*NYI*/
5006 //CriteriaType::EarnGuildAchievementPoints, /*NYI*/
5007 //CriteriaType::EarnBattlegroundRating, /*NYI*/
5008 //CriteriaType::GuildTabardCreated, /*NYI*/
5011 //CriteriaType::UpgradeGarrison, /*NYI*/
5012 //CriteriaType::AcquireGarrison, /*NYI*/
5013 //CriteriaType::LearnGarrisonBlueprint, /*NYI*/
5014 //CriteriaType::LearnGarrisonSpecialization, /*NYI*/
5015 //CriteriaType::LearnToy, /*NYI*/ // Learn Toy "{Item}"
5016 //CriteriaType::LearnAnyToy, /*NYI*/ // Learn Any Toy
5017 //CriteriaType::LearnTransmog, /*NYI*/
5019 //CriteriaType::AccountHonorLevelReached, /*NYI*/
5021 //CriteriaType::MemorizeSpell, /*NYI*/
5022 //CriteriaType::LearnTransmogIllusion, /*NYI*/
5023 //CriteriaType::MythicPlusRatingAttained, /*NYI*/
5024 //CriteriaType::MythicPlusDisplaySeasonEnded, /*NYI*/
5025 //CriteriaType::CompleteTrackingQuest, /*NYI*/
5028
5031 CriteriaType::EarnAchievement // criteria possibly completed by retroactive scan, must be last
5032 };
5033
5034 return Types;
5035}
#define sArenaTeamMgr
#define MAX_ARENA_SLOT
Definition ArenaTeam.h:109
constexpr uint32 ITEM_ID_HEART_OF_AZEROTH
Definition AzeriteItem.h:23
@ DAY
Definition Common.h:34
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< 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:569
#define MAX_WORLD_MAP_OVERLAY_AREA_IDX
TraitConfigType
Definition DBCEnums.h:2851
@ STRONG_MAX_LEVEL
Definition DBCEnums.h:49
PlayerConditionLfgStatus
Definition DBCEnums.h:2193
TraitCombatConfigFlags
Definition DBCEnums.h:2821
ModifierTreeOperator
Definition DBCEnums.h:2093
@ FACTION_MASK_ALLIANCE
Definition DBCEnums.h:1009
@ FACTION_MASK_HORDE
Definition DBCEnums.h:1010
@ FACTION_MASK_PLAYER
Definition DBCEnums.h:1008
@ ACHIEVEMENT_FLAG_ACCOUNT
Definition DBCEnums.h:95
@ ACHIEVEMENT_FLAG_GUILD
Definition DBCEnums.h:92
ModifierTreeType
Definition DBCEnums.h:1686
@ GroupMemberCountFromConnectedRealmEqualOrGreaterThan
@ GarrisonShipmentContainerIsFull
@ PlayerExpansionLevelEqualOrGreaterThan
@ PlayerHasTrackedCurrencyEqualOrGreaterThan
@ PlayerToTargetLevelDeltaGreaterThan
@ PlayerHasItemQuantityIncludingBank
@ PlayerBattlegroundRatingEqualOrGreaterThan
@ PlayerHasTraitNodeEntryInActiveConfig
@ GarrisonFollowersWithQualityEqualOrGreaterThan
@ PlayerHasCurrencyEqualOrGreaterThan
@ ReputationWithFactionIsEqualOrGreaterThan
@ PlayerMythicPlusRunCountInCurrentExpansionEqualOrGreaterThan
@ PlayerIsQnQuestLinkedToScheduledWorldStateGroup
@ BattlePetTeamWithTypeEqualOrGreaterThan
@ PlayerDataElementCharacterBetween
@ GarrisonBuildingIsUnderConstruction
@ UniqueBattlePetsEqualOrGreaterThan
@ PlayerSummonedBattlePetSpecies
@ PlayerLanguageSkillEqualOrGreaterThan
@ PlayerDataElementAccountBetween
@ 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
@ PlayerHasCompletedQuestOrIsReadyToTurnIn
@ GarrisonFollowersWithLevelEqualOrGreaterThan
@ PlayerIsAllowedToToggleWarModeInArea
@ PlayerUsedBoostLessThanHoursAgoGameTime
@ PlayerHasPerksProgramPendingReward
@ GarrisonPlotInstanceHasBuildingThatIsReadyToActivate
@ GarrisonFollowerWithLevelAssignedToBuilding
@ PlayerLevelWithinOrAboveContentTuning
@ BattlePetTeamWithSpeciesEqualOrGreaterThan
@ ServerExpansionEqualOrGreaterThan
@ ParagonReputationLevelEqualOrGreaterThan
@ GuildGroupMemberCountEqualOrGreaterThan
@ JailersTowerActiveFloorDifficultyEqualOrGreaterThan
@ PlayerAuraWithLabelStackCountEqual
@ PlayerAuraWithLabelStackCountEqualOrLessThan
@ GarrisonFollowerWithAbilityAtLevelEqualOrGreaterThan
@ GarrisonMissionIsReadyToCollect
@ TargetAuraStackCountEqualOrGreaterThan
@ TargetCreatureClassificationEqual
@ 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:398
Difficulty
Definition DBCEnums.h:932
@ DIFFICULTY_NONE
Definition DBCEnums.h:933
CriteriaStartEvent
Definition DBCEnums.h:513
CriteriaTreeOperator
Definition DBCEnums.h:828
CriteriaFailEvent
Definition DBCEnums.h:492
uint32 constexpr ACHIVEMENT_CATEGORY_PET_BATTLES
Definition DBCEnums.h:101
CriteriaType
Definition DBCEnums.h:546
@ 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
@ CompleteQuestsCountOnAccount
@ 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.
uint8_t uint8
Definition Define.h:156
int64_t int64
Definition Define.h:149
int16_t int16
Definition Define.h:151
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
@ DISABLE_TYPE_CRITERIA
Definition DisableMgr.h:31
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
std::chrono::hours Hours
Hours shorthand typedef.
Definition Duration.h:36
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:82
#define ASSERT
Definition Errors.h:80
bool IsHolidayActive(HolidayIds id)
bool IsEventActive(uint16 eventId)
#define sGameEventMgr
@ GARRISON_ABILITY_FLAG_TRAIT
Definition Garrison.h:69
GarrisonType
Definition Garrison.h:35
@ GARRISON_TYPE_GARRISON
Definition Garrison.h:36
@ FOLLOWER_STATUS_INACTIVE
Definition Garrison.h:179
@ GROUP_FLAG_CROSS_FACTION
Definition Group.h:105
@ ITEM_MODIFIER_CHALLENGE_KEYSTONE_LEVEL
@ ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID
BankType
@ ITEM_CLASS_WEAPON
@ ITEM_SUBCLASS_WEAPON_FIST_WEAPON
#define sLanguageMgr
Definition LanguageMgr.h:97
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
#define TC_LOG_TRACE(filterType__, message__,...)
Definition Log.h:178
#define sMapMgr
Definition MapManager.h:186
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
#define sObjectMgr
Definition ObjectMgr.h:1885
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
@ EQUIPMENT_SLOT_MAINHAND
Definition Player.h:744
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:745
@ PLAYER_FLAGS_WAR_MODE_ACTIVE
Definition Player.h:530
@ PLAYER_FLAGS_TIMEWALKING
Definition Player.h:550
@ PLAYER_LOCAL_FLAG_WAR_MODE
Definition Player.h:583
#define MAX_DRUNKEN
Definition Player.h:516
@ PLAYER_FLAGS_EX_MERCENARY_MODE
Definition Player.h:559
DrunkenState
Definition Player.h:509
std::set< uint32 > RewardedQuestSet
Definition Player.h:659
@ QUEST_OBJECTIVE_CRITERIA_TREE
Definition QuestDef.h:372
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:46
QuestStatus
Definition QuestDef.h:146
@ QUEST_STATUS_REWARDED
Definition QuestDef.h:153
@ QUEST_STATUS_FAILED
Definition QuestDef.h:152
@ QUEST_STATUS_NONE
Definition QuestDef.h:147
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:148
Role Based Access Control related classes definition.
constexpr Trinity::RaceMask< uint64 > RACEMASK_ALL_PLAYABLE
Definition RaceMask.h:289
#define sRealmList
Definition RealmList.h:93
#define sScriptMgr
Definition ScriptMgr.h:1449
SpellEffIndex
Language
Gender
@ GENDER_NONE
@ MAX_ITEM_QUALITY
CreatureFamily
@ TEAM_ALLIANCE
@ TEAM_HORDE
@ ALLIANCE
@ HORDE
#define CLASSMASK_ALL_PLAYABLE
CreatureClassifications
AuraStateType
HolidayIds
@ EXPANSION_SHADOWLANDS
#define sSpellMgr
Definition SpellMgr.h:812
std::pair< SkillLineAbilityMap::const_iterator, SkillLineAbilityMap::const_iterator > SkillLineAbilityMapBounds
Definition SpellMgr.h:579
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:38
float GetPctOf(T value, T max)
Definition Util.h:78
bool CompareValues(ComparisionType type, T val1, T val2)
Definition Util.h:543
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
ComparisionType
Definition Util.h:533
@ COMP_TYPE_MAX
Definition Util.h:539
ArenaTeamMember * GetMember(ObjectGuid guid)
uint32 GetType() const
Definition ArenaTeam.h:128
uint8 GetStackAmount() const
Definition SpellAuras.h:238
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:182
ObjectGuid GetCastItemGUID() const
Definition SpellAuras.h:188
uint32 GetLevel() const
Definition AzeriteItem.h:41
bool IsUnit() const
Definition BaseEntity.h:171
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
bool IsInWorld() const
Definition BaseEntity.h:158
bool IsCreature() const
Definition BaseEntity.h:172
bool IsPlayer() const
Definition BaseEntity.h:173
TypeID GetTypeId() const
Definition BaseEntity.h:166
uint32 GetPetUniqueSpeciesCount() const
std::vector< WorldPackets::BattlePet::BattlePetSlot > const & GetSlots() const
uint8 GetArenaType() const
uint32 GetTeamScore(TeamId teamId) const
bool isRated() const
bool isArena() const
bool isBattleground() const
Team GetPlayerTeam(ObjectGuid guid) const
HeirloomContainer const & GetAccountHeirlooms() const
bool HasToy(uint32 itemId) const
MountContainer const & GetAccountMounts() const
std::pair< bool, bool > HasItemAppearance(uint32 itemModifiedAppearanceId) const
static bool IsMeetingWorldStateExpression(Map const *map, WorldStateExpressionEntry const *expression)
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
static uint32 GetPlayerConditionLfgValue(Player const *player, PlayerConditionLfgStatus status)
CreatureClassifications GetCreatureClassification() const
Definition Creature.h:166
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:266
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 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
CriteriaTreeList const * GetCriteriaTreesByCriteria(uint32 criteriaId) const
CriteriaListByAsset _criteriasByAsset[size_t(CriteriaType::Count)]
static CriteriaMgr * Instance()
void LoadCriteriaModifiersTree()
CriteriaDataSet const * GetCriteriaDataSet(Criteria const *criteria) const
static std::span< CriteriaType const > GetRetroactivelyUpdateableCriteriaTypes()
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)
std::set< FriendshipRepReactionEntry const *, FriendshipRepReactionEntryComparator > FriendshipRepReactionSet
Definition DB2Stores.h:439
constexpr bool HasFlag(T flag) const
Definition EnumFlag.h:106
Class used to access individual fields of database query result.
Definition Field.h:94
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
std::string_view GetStringView() const noexcept
Definition Field.cpp:118
uint8 GetUInt8() const noexcept
Definition Field.cpp:29
std::vector< GameEventData > GameEventDataMap
Follower const * GetFollower(uint64 dbId) const
Definition Garrison.cpp:524
uint32 CountFollowers(Predicate &&predicate) const
Definition Garrison.h:254
GarrisonType GetType() const
Definition Garrison.h:234
Plot * GetPlot(uint32 garrPlotInstanceId)
Definition Garrison.cpp:317
bool HasBlueprint(uint32 garrBuildingId) const
Definition Garrison.h:245
GarrSiteLevelEntry const * GetSiteLevel() const
Definition Garrison.h:235
std::vector< Plot * > GetPlots()
Definition Garrison.cpp:307
Definition Group.h:205
uint32 GetMembersCount() const
Definition Group.h:335
GroupRefManager & GetMembers()
Definition Group.h:332
GroupFlags GetGroupFlags() const
Definition Group.h:337
bool isRaidGroup() const
Definition Group.cpp:1628
uint32 GetMaxPlayers() const
Definition Map.cpp:3396
InstanceScript * GetInstanceScript()
Definition Map.h:890
virtual bool CheckAchievementCriteriaMeet(uint32, Player const *, Unit const *=nullptr, uint32=0)
Definition Item.h:179
AzeriteItem * ToAzeriteItem()
Definition Item.h:253
std::vector< int32 > const & GetBonusListIDs() const
Definition Item.h:239
UF::ArtifactPower const * GetArtifactPower(uint32 artifactPowerId) const
Definition Item.cpp:2634
uint32 GetTotalUnlockedArtifactPowers() const
Definition Item.cpp:2688
uint16 GetVisibleAppearanceModId(Player const *owner) const
Definition Item.cpp:2527
uint32 GetModifier(ItemModifier modifier) const
Definition Item.cpp:2470
uint32 size() const
Definition LinkedList.h:129
Definition Map.h:225
bool IsDungeon() const
Definition Map.cpp:3267
Difficulty GetDifficultyID() const
Definition Map.h:360
MapEntry const * GetEntry() const
Definition Map.h:231
uint32 GetPlayersCountExceptGMs() const
Definition Map.cpp:2679
uint32 GetId() const
Definition Map.cpp:3257
InstanceMap * ToInstanceMap()
Definition Map.h:490
WeatherState GetZoneWeather(uint32 zoneId) const
Definition Map.cpp:4010
uint32 GetInstanceId() const
Definition Map.h:350
PlayerList const & GetPlayers() const
Definition Map.h:403
bool IsGarrison() const
Definition Map.cpp:3379
LowType GetCounter() const
Definition ObjectGuid.h:336
static ObjectGuid const Empty
Definition ObjectGuid.h:314
HighGuid GetHigh() const
Definition ObjectGuid.h:331
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
Unit * ToUnit()
Definition Object.h:116
static bool InDbPhaseShift(WorldObject const *object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId)
ChrSpecialization GetPrimarySpecialization() const
Definition Player.h:2008
UF::UpdateField< UF::PlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_PLAYER > m_playerData
Definition Player.h:3061
uint32 GetHonorLevel() const
Definition Player.h:2467
uint32 GetCustomizationChoice(uint32 chrCustomizationOptionId) const
Definition Player.h:2922
UF::PVPInfo const * GetPvpInfoForBracket(int8 bracket) const
Definition Player.cpp:23148
bool HasDataFlagAccount(uint32 dataFlagId) const
Definition Player.cpp:30416
uint32 GetCurrencyTrackedQuantity(uint32 id) const
Definition Player.cpp:7402
int32 GetReputation(uint32 factionentry) const
Definition Player.cpp:29544
BattlegroundTypeId GetBattlegroundTypeId() const
Definition Player.h:2587
bool HasPlayerFlagEx(PlayerFlagsEx flags) const
Definition Player.h:2915
bool CanEnableWarModeInArea() const
Definition Player.cpp:31068
std::vector< uint32 > GetCompletedAchievementIds() const
Definition Player.cpp:27567
bool ForEachItem(ItemSearchLocation location, T callback) const
Iterate over each item in the player storage.
Definition Player.h:1404
uint32 GetTotalPlayedTime() const
Definition Player.h:1347
RewardedQuestSet const & getRewardedQuests() const
Definition Player.h:1911
uint8 GetDrunkValue() const
Definition Player.h:2479
Gender GetNativeGender() const override
Definition Player.h:1350
UF::UpdateField< UF::ActivePlayerData, int32(WowCS::EntityFragment::CGObject), TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition Player.h:3062
bool GetQuestRewardStatus(uint32 quest_id) const
Definition Player.cpp:15945
bool HasRaceChanged() const
Definition Player.h:1320
bool HasDataFlagCharacter(uint32 dataFlagId) const
Definition Player.cpp:30453
uint16 FindQuestSlot(uint32 quest_id) const
Definition Player.cpp:16383
UF::TraitConfig const * GetTraitConfig(int32 configId) const
Definition Player.cpp:29192
bool HasCurrency(uint32 id, uint32 amount) const
Definition Player.cpp:7451
uint8 GetCharacterBankTabCount() const
Definition Player.h:1503
uint8 GetBankBagSlotCount() const
Definition Player.h:1501
bool InBattleground() const
Definition Player.h:2584
Item * GetItemByEntry(uint32 entry, ItemSearchLocation where=ItemSearchLocation::Default) const
Definition Player.cpp:12475
bool IsMaxLevel() const
Definition Player.cpp:2356
bool IsQuestCompletedBitSet(uint32 questId) const
Definition Player.cpp:16517
uint32 GetItemCount(uint32 item, bool inBankAlso=false, Item *skipItem=nullptr) const
Definition Player.cpp:9560
bool HasTitle(uint32 bitIndex) const
Definition Player.cpp:27052
uint16 GetPureSkillValue(uint32 skill) const
Definition Player.cpp:6066
bool HasAchieved(uint32 achievementId) const
Definition Player.cpp:27572
WorldSession * GetSession() const
Definition Player.h:2272
int32 GetQuestObjectiveData(uint32 questId, uint32 objectiveId) const
Definition Player.cpp:16440
uint8 GetAccountBankTabCount() const
Definition Player.h:1505
uint16 GetBaseSkillValue(uint32 skill) const
Definition Player.cpp:6052
PlayerSpellMap const & GetSpellMap() const
Definition Player.h:2070
uint16 GetPureMaxSkillValue(uint32 skill) const
Definition Player.cpp:6040
std::variant< int64, float > GetDataElementAccount(uint32 dataElementId) const
Definition Player.cpp:30314
bool HasExploredZone(uint32 areaId) const
Definition Player.cpp:6397
bool HasPlayerLocalFlag(PlayerLocalFlags flags) const
Definition Player.h:3007
Battleground * GetBattleground() const
Definition Player.cpp:25719
ObjectGuid::LowType GetGuildId() const
Definition Player.h:2164
uint32 GetFreeInventorySlotCount(EnumFlag< ItemSearchLocation > location=ItemSearchLocation::Inventory) const
Definition Player.cpp:9483
bool IsGameMaster() const
Definition Player.h:1309
std::variant< int64, float > GetDataElementCharacter(uint32 dataElementId) const
Definition Player.cpp:30368
uint32 GetRBGPersonalRating() const
Definition Player.h:2179
uint32 GetAchievementPoints() const
Definition Player.cpp:27562
bool CanTakeQuest(Quest const *quest, bool msg) const
Definition Player.cpp:14522
bool IsQuestObjectiveComplete(uint16 slot, Quest const *quest, QuestObjective const &objective) const
Definition Player.cpp:17208
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition Player.cpp:15962
Garrison * GetGarrison() const
Definition Player.h:2883
bool HasLevelBoosted() const
Definition Player.h:1324
uint64 GetMoney() const
Definition Player.h:1905
ReputationRank GetReputationRank(uint32 faction_id) const
Definition Player.cpp:6505
bool HasSpell(uint32 spell) const override
Definition Player.cpp:3735
Group * GetGroup(Optional< uint8 > partyIndex)
Definition Player.h:2796
bool HasPlayerFlag(PlayerFlags flags) const
Definition Player.h:2910
size_t GetRewardedQuestCount() const
Definition Player.h:1914
uint32 GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const
Definition Player.cpp:24013
Item * GetItemByGuid(ObjectGuid guid) const
Definition Player.cpp:9614
bool HasBeenGrantedLevelsFromRaF() const
Definition Player.h:1322
ChrSpecializationEntry const * GetPrimarySpecializationEntry() const
Definition Player.cpp:30819
uint32 GetArenaTeamId(uint8) const
Definition Player.h:2175
ReputationMgr & GetReputationMgr()
Definition Player.h:2439
static DrunkenState GetDrunkenstateByValue(uint8 value)
Definition Player.cpp:869
bool IsLockedToDungeonEncounter(uint32 dungeonEncounterId) const
Definition Player.cpp:21946
uint32 GetCurrencyQuantity(uint32 id) const
Definition Player.cpp:7384
bool IsQuestRewarded(uint32 quest_id) const
Definition Player.cpp:24889
Team GetTeam() const
Definition Player.h:2423
InventoryResult CanUseItem(Item *pItem, bool not_loading=true) const
Definition Player.cpp:11214
int32 GetZoneOrSort() const
Definition QuestDef.h:641
uint32 GetQuestInfoID() const
Definition QuestDef.h:643
uint8 GetHonoredFactionCount() const
uint8 GetReveredFactionCount() const
int32 GetReputation(uint32 faction_id) const
int32 GetParagonLevel(uint32 paragonFactionId) const
uint8 GetExaltedFactionCount() const
uint8 GetVisibleFactionCount() const
ScenarioEntry const * GetEntry() const
Definition Scenario.cpp:144
ScenarioStepEntry const * GetLastStep() const
Definition Scenario.cpp:297
ScenarioStepEntry const * GetStep() const
Definition Scenario.h:73
AuraType ApplyAuraName
Definition SpellInfo.h:216
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:588
std::vector< SpellEffectInfo > const & GetEffects() const
Definition SpellInfo.h:587
bool HasLabel(uint32 labelId) const
size_t GetThreatListSize() const
int32 FindIndexIf(Pred pred) const
Definition Unit.h:635
float GetHealthPct() const
Definition Unit.h:796
bool CanHaveThreatList() const
====================== THREAT & COMBAT ====================
Definition Unit.h:1030
ThreatManager & GetThreatManager()
Definition Unit.h:1078
uint8 GetClass() const
Definition Unit.h:764
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition Unit.cpp:4604
bool IsAlive() const
Definition Unit.h:1185
Gender GetGender() const
Definition Unit.h:767
uint32 GetCreatureType() const
Definition Unit.cpp:9451
uint32 GetDisplayId() const
Definition Unit.h:1610
uint32 GetAuraCount(uint32 spellId) const
Definition Unit.cpp:4788
bool HasAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid caster=ObjectGuid::Empty) const
Definition Unit.cpp:4774
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4700
uint64 GetHealth() const
Definition Unit.h:788
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
Definition Unit.cpp:6146
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4814
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1881
bool HealthAbovePct(float pct) const
Definition Unit.h:794
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4804
bool IsFlying() const
Definition Unit.h:1807
ObjectGuid GetTarget() const
Definition Unit.h:1831
uint8 GetLevel() const
Definition Unit.h:757
uint8 GetRace() const
Definition Unit.h:761
bool isDead() const
Definition Unit.h:1187
constexpr uint32 GetMapId() const
Definition Position.h:216
Map * GetMap() const
Definition Object.h:411
Scenario * GetScenario() const
Definition Object.cpp:1389
virtual uint8 GetLevelForTarget(WorldObject const *) const
Definition Object.h:385
bool IsHostileTo(WorldObject const *target) const
Definition Object.cpp:2181
uint32 GetInstanceId() const
Definition Object.h:308
std::string const & GetName() const
Definition Object.h:342
uint32 GetAreaId() const
Definition Object.h:333
uint32 GetZoneId() const
Definition Object.h:332
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:916
WeatherState
Definition Weather.h:46
@ CONFIG_ARENA_SEASON_ID
Definition World.h:344
@ CONFIG_EXPANSION
Definition World.h:306
@ CONFIG_ARENA_SEASON_IN_PROGRESS
Definition World.h:143
static constexpr uint16 MAX_BATTLE_PET_LEVEL
uint32 GetMinorMajorBugfixVersionForBuild(uint32 build)
bool IsDisabledFor(DisableType type, uint32 entry, WorldObject const *ref, uint8 flags)
WowTime const * GetWowTime()
Definition GameTime.cpp:106
time_t GetGameTime()
Definition GameTime.cpp:52
std::vector< int32 > GetAllBonusListsForTree(uint32 itemBonusTreeId)
TC_GAME_API bool IsQuestLineQuestActiveForPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:110
TC_GAME_API bool IsQuestLineCompletedByPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:119
TC_GAME_API bool IsCampaignCompletedByPlayer(uint32 campaignId, Player const *player)
Definition QuestMgr.cpp:156
TC_GAME_API bool IsQuestLineQuestAvailableForPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:100
TC_GAME_API QuestLineStats GetQuestLineStatsForPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:133
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
TC_GAME_API int32 GetValue(int32 worldStateId, Map const *map)
@ RBAC_PERM_CANNOT_EARN_ACHIEVEMENTS
Definition RBAC.h:61
EnumFlag< BattlemasterListFlags > GetFlags() const
CreatureFamily family
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::@5::@9 Health
struct CriteriaData::@5::@8 ClassRace
struct CriteriaData::@5::@22 GameEvent
CriteriaDataType DataType
struct CriteriaData::@5::@12 Level
struct CriteriaData::@5::@21 KnownTitle
struct CriteriaData::@5::@19 EquippedItem
struct CriteriaData::@5::@23 ItemQuality
struct CriteriaData::@5::@16 Drunk
bool IsValid(Criteria const *criteria)
bool Meets(uint32 criteriaId, Player const *source, WorldObject const *target, uint32 miscValue1=0, uint32 miscValue2=0) const
struct CriteriaData::@5::@14 MapPlayers
struct CriteriaData::@5::@17 Holiday
int16 EligibilityWorldStateID
union CriteriaEntry::AssetNameAlias Asset
int8 EligibilityWorldStateValue
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:813
Optional< WorldPackets::Garrison::GarrisonBuildingInfo > PacketInfo
Definition Garrison.h:193
WorldPackets::Garrison::GarrisonFollower PacketInfo
Definition Garrison.h:215
bool HasAbility(uint32 garrAbilityId) const
Definition Garrison.cpp:830
uint32 GetItemLevel() const
Definition Garrison.cpp:825
Building BuildingInfo
Definition Garrison.h:207
uint32 GetBaseItemLevel() const
uint32 GetQuality() const
uint32 GetSubClass() const
uint32 GetClass() const
int16 CosmeticParentMapID
int8 InstanceType
uint8 ExpansionID
ModifierTreeEntry const * Entry
std::vector< ModifierTreeNode const * > Children
constexpr float GetPositionZ() const
Definition Position.h:89
uint32 QuestID
Definition QuestDef.h:483
std::vector< ChrCustomizationDisplayInfoEntry const * > Displays
Definition DB2Stores.h:353
std::vector< ChrCustomizationChoiceEntry const * > const * Choices
Definition DB2Stores.h:352
constexpr bool HasRace(uint32 raceId) const
Definition RaceMask.h:96
UpdateField< uint32, 0, 11 > PvpTierID
UpdateField< uint32, 0, 12 > WeeklyBestWinPvpTierID
UpdateField< int32, 4, 6 > Type
DynamicUpdateField< UF::TraitEntry, 0, 1 > Entries
UpdateField< int32, 0, 3 > ID
DynamicUpdateField< UF::TraitSubTreeCache, 0, 2 > SubTrees
UpdateField< int32, 8, 10 > CombatConfigFlags
UpdateField< uint32, 0, 8 > ItemModifiedAppearanceID
UpdateField< int32, 0, 3 > ItemID
std::array< uint32, MAX_WORLD_MAP_OVERLAY_AREA_IDX > AreaID