aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp10
-rw-r--r--src/server/game/Achievements/AchievementMgr.h1
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp1329
-rw-r--r--src/server/game/BattlePets/BattlePetMgr.cpp10
-rw-r--r--src/server/game/BattlePets/BattlePetMgr.h5
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp11
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DBCEnums.h644
-rw-r--r--src/server/game/Entities/Item/Item.cpp23
-rw-r--r--src/server/game/Entities/Item/Item.h1
-rw-r--r--src/server/game/Entities/Player/CollectionMgr.cpp2
-rw-r--r--src/server/game/Entities/Player/Player.cpp63
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp2
-rw-r--r--src/server/game/Scenarios/Scenario.cpp50
-rw-r--r--src/server/game/Scenarios/Scenario.h1
-rw-r--r--src/server/game/Server/WorldSession.cpp5
-rw-r--r--src/server/game/Server/WorldSession.h2
18 files changed, 1562 insertions, 600 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 4c632b59113..fd77d880dfc 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -71,6 +71,16 @@ uint32 AchievementMgr::GetAchievementPoints() const
return _achievementPoints;
}
+std::vector<uint32> AchievementMgr::GetCompletedAchievementIds() const
+{
+ std::vector<uint32> achievementIds;
+ std::transform(_completedAchievements.begin(), _completedAchievements.end(), std::back_inserter(achievementIds), [](std::pair<uint32 const, CompletedAchievementData> const& achievement)
+ {
+ return achievement.first;
+ });
+ return achievementIds;
+}
+
bool AchievementMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
{
AchievementEntry const* achievement = tree->Achievement;
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index c423b756114..f11856a6345 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -56,6 +56,7 @@ public:
virtual void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer) = 0;
bool HasAchieved(uint32 achievementId) const;
uint32 GetAchievementPoints() const;
+ std::vector<uint32> GetCompletedAchievementIds() const;
protected:
bool CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const override;
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 1366eba31ba..4552cd989c2 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -34,6 +34,7 @@
#include "Group.h"
#include "InstanceScript.h"
#include "Item.h"
+#include "LanguageMgr.h"
#include "Log.h"
#include "MapManager.h"
#include "ObjectMgr.h"
@@ -43,6 +44,7 @@
#include "ReputationMgr.h"
#include "Scenario.h"
#include "ScriptMgr.h"
+#include "SpellAuras.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "World.h"
@@ -1650,23 +1652,23 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
uint32 secondaryAsset = modifier->SecondaryAsset;
uint32 tertiaryAsset = modifier->TertiaryAsset;
- switch (CriteriaAdditionalCondition(modifier->Type))
+ switch (ModifierTreeType(modifier->Type))
{
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_DRUNK_VALUE: // 1
+ case ModifierTreeType::PlayerInebriationLevelEqualOrGreaterThan: // 1
{
uint32 inebriation = std::min(std::max<uint32>(referencePlayer->GetDrunkValue(), *referencePlayer->m_playerData->FakeInebriation), 100u);
if (inebriation < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_PLAYER_CONDITION: // 2
+ case ModifierTreeType::PlayerMeetsCondition: // 2
{
PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(reqValue);
if (!playerCondition || !ConditionMgr::IsPlayerMeetingCondition(referencePlayer, playerCondition))
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_ITEM_LEVEL: // 3
+ case ModifierTreeType::MinimumItemLevel: // 3
{
// miscValue1 is itemid
ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
@@ -1674,47 +1676,47 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY: // 4
+ case ModifierTreeType::TargetCreatureId: // 4
if (!unit || unit->GetEntry() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER: // 5
+ case ModifierTreeType::TargetIsPlayer: // 5
if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD: // 6
+ case ModifierTreeType::TargetIsDead: // 6
if (!unit || unit->IsAlive())
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY: // 7
+ case ModifierTreeType::TargetIsOppositeFaction: // 7
if (!unit || !referencePlayer->IsHostileTo(unit))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA: // 8
+ case ModifierTreeType::PlayerHasAura: // 8
if (!referencePlayer->HasAura(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA_TYPE: // 9
+ case ModifierTreeType::PlayerHasAuraEffect: // 9
if (!referencePlayer->HasAuraType(AuraType(reqValue)))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA: // 10
+ case ModifierTreeType::TargetHasAura: // 10
if (!unit || !unit->HasAura(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE: // 11
+ case ModifierTreeType::TargetHasAuraEffect: // 11
if (!unit || !unit->HasAuraType(AuraType(reqValue)))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_AURA_STATE: // 12
- if (!referencePlayer->HasAuraState(AuraStateType(reqValue)))
+ case ModifierTreeType::TargetHasAuraState: // 12
+ if (!unit || !unit->HasAuraState(AuraStateType(reqValue)))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_AURA_STATE: // 13
- if (!unit || !unit->HasAuraState(AuraStateType(reqValue)))
+ case ModifierTreeType::PlayerHasAuraState: // 13
+ if (!referencePlayer->HasAuraState(AuraStateType(reqValue)))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN: // 14
+ case ModifierTreeType::ItemQualityIsAtLeast: // 14
{
// miscValue1 is itemid
ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
@@ -1722,7 +1724,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS: // 15
+ case ModifierTreeType::ItemQualityIsExactly: // 15
{
// miscValue1 is itemid
ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
@@ -1730,11 +1732,11 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_IS_ALIVE: // 16
+ case ModifierTreeType::PlayerIsAlive: // 16
if (referencePlayer->isDead())
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE: // 17
+ case ModifierTreeType::PlayerIsInArea: // 17
{
uint32 zoneId, areaId;
referencePlayer->GetZoneAndAreaId(zoneId, areaId);
@@ -1742,7 +1744,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE: // 18
+ case ModifierTreeType::TargetIsInArea: // 18
{
if (!unit)
return false;
@@ -1752,49 +1754,57 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY_OLD: // 20
+ case ModifierTreeType::ItemId: // 19
+ if (miscValue1 != reqValue)
+ return false;
+ break;
+ case ModifierTreeType::LegacyDungeonDifficulty: // 20
{
DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(referencePlayer->GetMap()->GetDifficultyID());
if (!difficulty || difficulty->OldEnumValue == -1 || uint32(difficulty->OldEnumValue) != reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_ABOVE_TARGET: // 22
+ case ModifierTreeType::PlayerToTargetLevelDeltaGreaterThan: // 21
+ if (!unit || referencePlayer->getLevel() < unit->getLevel() + reqValue)
+ return false;
+ break;
+ case ModifierTreeType::TargetToPlayerLevelDeltaGreaterThan: // 22
if (!unit || referencePlayer->getLevel() + reqValue < unit->getLevel())
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_EQUAL_TARGET: // 23
+ case ModifierTreeType::PlayerLevelEqualTargetLevel: // 23
if (!unit || referencePlayer->getLevel() != unit->getLevel())
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE: // 24
+ case ModifierTreeType::PlayerInArenaWithTeamSize: // 24
{
Battleground* bg = referencePlayer->GetBattleground();
if (!bg || !bg->isArena() || bg->GetArenaType() != reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE: // 25
+ case ModifierTreeType::PlayerRace: // 25
if (referencePlayer->getRace() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS: // 26
+ case ModifierTreeType::PlayerClass: // 26
if (referencePlayer->getClass() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE: // 27
+ case ModifierTreeType::TargetRace: // 27
if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getRace() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS: // 28
+ case ModifierTreeType::TargetClass: // 28
if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getClass() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS: // 29
+ case ModifierTreeType::LessThanTappers: // 29
if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE: // 30
+ case ModifierTreeType::CreatureType: // 30
{
if (!unit)
return false;
@@ -1802,7 +1812,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_FAMILY: // 31
+ case ModifierTreeType::CreatureFamily: // 31
{
if (!unit)
return false;
@@ -1810,41 +1820,44 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: // 32
+ case ModifierTreeType::PlayerMap: // 32
if (referencePlayer->GetMapId() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_CLIENT_VERSION: // 33
+ case ModifierTreeType::ClientVersionEqualOrLessThan: // 33
if (reqValue < sRealmList->GetMinorMajorBugfixVersionForBuild(realm.Build))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_TEAM_LEVEL: // 34
+ case ModifierTreeType::BattlePetTeamLevel: // 34
for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
- if (slot.Pet.Level != reqValue)
+ if (slot.Pet.Level < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_NOT_IN_GROUP: // 35
+ case ModifierTreeType::PlayerIsNotInParty: // 35
if (referencePlayer->GetGroup())
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_IN_GROUP: // 36
+ case ModifierTreeType::PlayerIsInParty: // 36
if (!referencePlayer->GetGroup())
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX: // 38
- // miscValue1 is title's bit index
- if (miscValue1 != reqValue)
+ case ModifierTreeType::HasPersonalRatingEqualOrGreaterThan: // 37
+ if (referencePlayer->GetMaxPersonalArenaRatingRequirement(0) < reqValue)
+ return false;
+ break;
+ case ModifierTreeType::HasTitle: // 38
+ if (!referencePlayer->HasTitle(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL: // 39
+ case ModifierTreeType::PlayerLevelEqual: // 39
if (referencePlayer->getLevel() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL: // 40
+ case ModifierTreeType::TargetLevelEqual: // 40
if (!unit || unit->GetLevelForTarget(referencePlayer) != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_ZONE: // 41
+ case ModifierTreeType::PlayerIsInZone: // 41
{
uint32 zoneId = referencePlayer->GetAreaId();
if (AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId))
@@ -1854,7 +1867,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE: // 42
+ case ModifierTreeType::TargetIsInZone: // 42
{
if (!unit)
return false;
@@ -1866,55 +1879,55 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_PCT_LOWER: // 43
+ case ModifierTreeType::PlayerHealthBelowPercent: // 43
if (referencePlayer->GetHealthPct() > float(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_PCT_GREATER: // 44
+ case ModifierTreeType::PlayerHealthAbovePercent: // 44
if (referencePlayer->GetHealthPct() < float(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_PCT_EQUAL: // 45
+ case ModifierTreeType::PlayerHealthEqualsPercent: // 45
if (referencePlayer->GetHealthPct() != float(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PCT_LOWER: // 46
+ case ModifierTreeType::TargetHealthBelowPercent: // 46
if (!unit || unit->GetHealthPct() > float(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PCT_GREATER: // 47
+ case ModifierTreeType::TargetHealthAbovePercent: // 47
if (!unit || unit->GetHealthPct() < float(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PCT_EQUAL: // 48
+ case ModifierTreeType::TargetHealthEqualsPercent: // 48
if (!unit || unit->GetHealthPct() != float(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_LOWER: // 49
+ case ModifierTreeType::PlayerHealthBelowValue: // 49
if (referencePlayer->GetHealth() > reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_GREATER: // 50
+ case ModifierTreeType::PlayerHealthAboveValue: // 50
if (referencePlayer->GetHealth() < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_EQUAL: // 51
+ case ModifierTreeType::PlayerHealthEqualsValue: // 51
if (referencePlayer->GetHealth() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_LOWER: // 52
+ case ModifierTreeType::TargetHealthBelowValue: // 52
if (!unit || unit->GetHealth() > reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_GREATER: // 53
+ case ModifierTreeType::TargetHealthAboveValue: // 53
if (!unit || unit->GetHealth() < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_EQUAL: // 54
+ case ModifierTreeType::TargetHealthEqualsValue: // 54
if (!unit || unit->GetHealth() != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_PLAYER_CONDITION: // 55
+ case ModifierTreeType::TargetIsPlayerAndMeetsCondition: // 55
{
if (!unit || !unit->IsPlayer())
return false;
@@ -1924,75 +1937,145 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_MIN_ACHIEVEMENT_POINTS: // 56
+ case ModifierTreeType::PlayerHasMoreThanAchievementPoints: // 56
if (referencePlayer->GetAchievementPoints() <= reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_IN_LFG_DUNGEON: // 57
+ case ModifierTreeType::PlayerInLfgDungeon: // 57
if (!ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus::InLFGDungeon))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_IN_LFG_RANDOM_DUNGEON: // 58
+ case ModifierTreeType::PlayerInRandomLfgDungeon: // 58
if (!ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus::InLFGRandomDungeon))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_IN_LFG_FIRST_RANDOM_DUNGEON: // 59
+ case ModifierTreeType::PlayerInFirstRandomLfgDungeon: // 59
if (!ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus::InLFGFirstRandomDungeon))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_GUILD_REPUTATION: // 62
+ case ModifierTreeType::PlayerInRankedArenaMatch: // 60
+ {
+ Battleground const* bg = referencePlayer->GetBattleground();
+ if (!bg || !bg->isArena() || !bg->isRated())
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerInGuildParty: // 61 NYI
+ return false;
+ case ModifierTreeType::PlayerGuildReputationEqualOrGreaterThan: // 62
if (referencePlayer->GetReputationMgr().GetReputation(1168) < int32(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND_RATING: // 64
+ case ModifierTreeType::PlayerInRatedBattleground: // 63
+ {
+ Battleground const* bg = referencePlayer->GetBattleground();
+ if (!bg || !bg->isBattleground() || !bg->isRated())
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerBattlegroundRatingEqualOrGreaterThan: // 64
if (referencePlayer->GetRBGPersonalRating() < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_WORLD_STATE_EXPRESSION: // 67
+ case ModifierTreeType::ResearchProjectRarity: // 65 NYI
+ case ModifierTreeType::ResearchProjectBranch: // 66 NYI
+ return false;
+ case ModifierTreeType::WorldStateExpression: // 67
if (WorldStateExpressionEntry const* worldStateExpression = sWorldStateExpressionStore.LookupEntry(reqValue))
return ConditionMgr::IsPlayerMeetingExpression(referencePlayer, worldStateExpression);
return false;
- case CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 68
- {
- DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(referencePlayer->GetMap()->GetDifficultyID());
- if (!difficulty || difficulty->ID != reqValue)
+ case ModifierTreeType::DungeonDifficulty: // 68
+ if (referencePlayer->GetMap()->GetDifficultyID() != reqValue)
return false;
break;
- }
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_GREATER: // 69
+ case ModifierTreeType::PlayerLevelEqualOrGreaterThan: // 69
if (referencePlayer->getLevel() < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_GREATER: // 70
+ case ModifierTreeType::TargetLevelEqualOrGreaterThan: // 70
if (!unit || unit->getLevel() < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_LOWER: // 71
+ case ModifierTreeType::PlayerLevelEqualOrLessThan: // 71
if (referencePlayer->getLevel() > reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_LOWER: // 72
+ case ModifierTreeType::TargetLevelEqualOrLessThan: // 72
if (!unit || unit->getLevel() > reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_MODIFIER_TREE: // 73
+ case ModifierTreeType::ModifierTree: // 73
if (ModifierTreeNode const* nextModifierTree = sCriteriaMgr->GetModifierTree(reqValue))
return ModifierTreeSatisfied(nextModifierTree, miscValue1, miscValue2, unit, referencePlayer);
return false;
- case CRITERIA_ADDITIONAL_CONDITION_SCENARIO_ID: // 74
+ case ModifierTreeType::PlayerScenario: // 74
{
Scenario const* scenario = referencePlayer->GetScenario();
- if (!scenario)
- return false;
- if (scenario->GetEntry()->ID != reqValue)
+ if (!scenario || scenario->GetEntry()->ID != reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_THE_TILLERS_REPUTATION: // 75
+ case ModifierTreeType::TillersReputationGreaterThan: // 75
if (referencePlayer->GetReputationMgr().GetReputation(1272) < int32(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SCENARIO_STEP_INDEX: // 82
+ case ModifierTreeType::BattlePetAchievementPointsEqualOrGreaterThan: // 76
+ {
+ auto getRootAchievementCategory = [](AchievementEntry const* achievement)
+ {
+ int16 category = achievement->Category;
+ do
+ {
+ Achievement_CategoryEntry const* categoryEntry = sAchievementCategoryStore.LookupEntry(category);
+ if (!categoryEntry || categoryEntry->Parent == -1)
+ break;
+
+ category = categoryEntry->Parent;
+ } while (true);
+
+ return category;
+ };
+
+ uint32 petAchievementPoints = 0;
+ for (uint32 achievementId : referencePlayer->GetCompletedAchievementIds())
+ {
+ AchievementEntry const* achievement = sAchievementStore.AssertEntry(achievementId);
+ if (getRootAchievementCategory(achievement) == ACHIVEMENT_CATEGORY_PET_BATTLES)
+ petAchievementPoints += uint32(achievement->Points);
+ }
+
+ if (petAchievementPoints < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::UniqueBattlePetsEqualOrGreaterThan: // 77
+ if (referencePlayer->GetSession()->GetBattlePetMgr()->GetPetUniqueSpeciesCount() < reqValue)
+ return false;
+ break;
+ case ModifierTreeType::BattlePetType: // 78
+ {
+ BattlePetSpeciesEntry const* speciesEntry = sBattlePetSpeciesStore.LookupEntry(miscValue1);
+ if (!speciesEntry || speciesEntry->PetTypeEnum != reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::BattlePetHealthPercentLessThan: // 79 NYI - use target battle pet here, the one we were just battling
+ return false;
+ case ModifierTreeType::GuildGroupMemberCountEqualOrGreaterThan: // 80
+ {
+ uint32 guildMemberCount = 0;
+ if (Group const* group = referencePlayer->GetGroup())
+ for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ if (itr->GetSource()->GetGuildId() == referencePlayer->GetGuildId())
+ ++guildMemberCount;
+
+ if (guildMemberCount < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::BattlePetOpponentCreatureId: // 81 NYI
+ return false;
+ case ModifierTreeType::PlayerScenarioStep: // 82
{
Scenario const* scenario = referencePlayer->GetScenario();
if (!scenario)
@@ -2001,81 +2084,141 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_IS_ON_QUEST: // 84
+ case ModifierTreeType::ChallengeModeMedal: // 83
+ return false; // OBSOLETE
+ case ModifierTreeType::PlayerOnQuest: // 84
if (referencePlayer->FindQuestSlot(reqValue) == MAX_QUEST_LOG_SIZE)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_EXALTED_WITH_FACTION: // 85
+ case ModifierTreeType::ExaltedWithFaction: // 85
if (referencePlayer->GetReputationMgr().GetReputation(reqValue) < 42000)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_HAS_ACHIEVEMENT: // 86
- case CRITERIA_ADDITIONAL_CONDITION_HAS_ACHIEVEMENT_ON_CHARACTER: // 87
+ case ModifierTreeType::EarnedAchievementOnAccount: // 86
+ case ModifierTreeType::EarnedAchievementOnPlayer: // 87
if (!referencePlayer->HasAchieved(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_CLOUD_SERPENT_REPUTATION: // 88
+ case ModifierTreeType::OrderOfTheCloudSerpentReputationGreaterThan: // 88
if (referencePlayer->GetReputationMgr().GetReputation(1271) < int32(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES: // 91
+ case ModifierTreeType::BattlePetQuality: // 89 NYI
+ case ModifierTreeType::BattlePetFightWasPVP: // 90 NYI
+ return false;
+ case ModifierTreeType::BattlePetSpecies: // 91
if (miscValue1 != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_ACTIVE_EXPANSION: // 92
- if (referencePlayer->GetSession()->GetExpansion() < reqValue)
+ case ModifierTreeType::ServerExpansionEqualOrGreaterThan: // 92
+ if (sWorld->getIntConfig(CONFIG_EXPANSION) < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_FACTION_STANDING: // 95
+ case ModifierTreeType::PlayerHasBattlePetJournalLock: // 93
+ if (!referencePlayer->GetSession()->GetBattlePetMgr()->HasJournalLock())
+ return false;
+ break;
+ case ModifierTreeType::FriendshipRepReactionIsMet: // 94
+ {
+ FriendshipRepReactionEntry const* friendshipRepReaction = sFriendshipRepReactionStore.LookupEntry(reqValue);
+ if (!friendshipRepReaction)
+ return false;
+ FriendshipReputationEntry const* friendshipReputation = sFriendshipReputationStore.LookupEntry(friendshipRepReaction->FriendshipRepID);
+ if (!friendshipReputation)
+ return false;
+ if (referencePlayer->GetReputation(friendshipReputation->FactionID) < int32(friendshipRepReaction->ReactionThreshold))
+ return false;
+ break;
+ }
+ case ModifierTreeType::ReputationWithFactionIsEqualOrGreaterThan: // 95
if (referencePlayer->GetReputationMgr().GetReputation(reqValue) < int32(secondaryAsset))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_SEX: // 97
+ case ModifierTreeType::ItemClassAndSubclass: // 96
+ {
+ ItemTemplate const* item = sObjectMgr->GetItemTemplate(miscValue1);
+ if (!item || item->GetClass() != reqValue || item->GetSubClass() != secondaryAsset)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerGender: // 97
if (referencePlayer->getGender() != uint8(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_NATIVE_SEX: // 98
+ case ModifierTreeType::PlayerNativeGender: // 98
if (referencePlayer->GetNativeSex() != uint8(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SKILL: // 99
+ case ModifierTreeType::PlayerSkillEqualOrGreaterThan: // 99
if (referencePlayer->GetPureSkillValue(reqValue) < uint16(secondaryAsset))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_NORMAL_PHASE_SHIFT: // 101
+ case ModifierTreeType::PlayerLanguageSkillEqualOrGreaterThan: // 100
+ {
+ auto languageDescs = sLanguageMgr->GetLanguageDescById(Language(reqValue));
+ bool hasLanguageSkil = std::any_of(languageDescs.begin(), languageDescs.end(), [&](std::pair<uint32 const, LanguageDesc> const& desc)
+ {
+ return referencePlayer->GetSkillValue(desc.second.SkillId) >= secondaryAsset;
+ });
+ if (!hasLanguageSkil)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerIsInNormalPhase: // 101
if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, 0, 0))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_IN_PHASE: // 102
+ case ModifierTreeType::PlayerIsInPhase: // 102
if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, reqValue, 0))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_NOT_IN_PHASE: // 103
- if (PhasingHandler::InDbPhaseShift(referencePlayer, 0, reqValue, 0))
+ case ModifierTreeType::PlayerIsInPhaseGroup: // 103
+ if (!PhasingHandler::InDbPhaseShift(referencePlayer, 0, 0, reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_HAS_SPELL: // 104
+ case ModifierTreeType::PlayerKnowsSpell: // 104
if (!referencePlayer->HasSpell(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_ITEM_COUNT: // 105
+ case ModifierTreeType::PlayerHasItemQuantity: // 105
if (referencePlayer->GetItemCount(reqValue, false) < secondaryAsset)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_ACCOUNT_EXPANSION: // 106
- if (referencePlayer->GetSession()->GetAccountExpansion() < reqValue)
+ case ModifierTreeType::PlayerExpansionLevelEqualOrGreaterThan: // 106
+ if (referencePlayer->GetSession()->GetExpansion() < reqValue)
+ return false;
+ break;
+ case ModifierTreeType::PlayerHasAuraWithLabel: // 107
+ if (!referencePlayer->HasAura([labelId = reqValue](Aura const* aura) { return aura->GetSpellInfo()->HasLabel(labelId); }))
+ return false;
+ break;
+ case ModifierTreeType::PlayersRealmWorldState: // 108
+ if (sWorld->getWorldState(reqValue) != secondaryAsset)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_REWARDED_QUEST: // 110
+ case ModifierTreeType::TimeBetween: // 109
+ {
+ ByteBuffer unpacker;
+ unpacker << reqValue;
+ time_t from = unpacker.ReadPackedTime();
+ unpacker.rpos(0);
+ unpacker.wpos(0);
+ unpacker << secondaryAsset;
+ time_t to = unpacker.ReadPackedTime();
+ if (GameTime::GetGameTime() < from || GameTime::GetGameTime() > to)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasCompletedQuest: // 110
if (uint32 questBit = sDB2Manager.GetQuestUniqueBitFlag(reqValue))
if (!(referencePlayer->m_activePlayerData->QuestCompleted[((questBit - 1) >> 6)] & (UI64LIT(1) << ((questBit - 1) & 63))))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_COMPLETED_QUEST: // 111
+ case ModifierTreeType::PlayerIsReadyToTurnInQuest: // 111
if (referencePlayer->GetQuestStatus(reqValue) != QUEST_STATUS_COMPLETE)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_COMPLETED_QUEST_OBJECTIVE: // 112
+ case ModifierTreeType::PlayerHasCompletedQuestObjective: // 112
{
QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
if (!objective)
@@ -2088,7 +2231,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_EXPLORED_AREA: // 113
+ case ModifierTreeType::PlayerHasExploredArea: // 113
{
AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(reqValue);
if (!areaTable)
@@ -2102,11 +2245,15 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_ITEM_COUNT_INCLUDING_BANK: // 114
+ case ModifierTreeType::PlayerHasItemQuantityIncludingBank: // 114
if (referencePlayer->GetItemCount(reqValue, true) < secondaryAsset)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_PVP_FACTION_INDEX: // 116
+ case ModifierTreeType::Weather: // 115
+ if (referencePlayer->GetMap()->GetZoneWeather(referencePlayer->GetZoneId()) != WeatherState(reqValue))
+ return false;
+ break;
+ case ModifierTreeType::PlayerFaction: // 116
{
ChrRacesEntry const* race = sChrRacesStore.LookupEntry(referencePlayer->getRace());
if (!race)
@@ -2125,93 +2272,113 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_LFG_VALUE_EQUAL: // 117
+ case ModifierTreeType::LfgStatusEqual: // 117
if (ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus(reqValue)) != secondaryAsset)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_LFG_VALUE_GREATER: // 118
+ case ModifierTreeType::LFgStatusEqualOrGreaterThan: // 118
if (ConditionMgr::GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus(reqValue)) < secondaryAsset)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_CURRENCY_AMOUNT: // 119
+ case ModifierTreeType::PlayerHasCurrencyEqualOrGreaterThan: // 119
if (!referencePlayer->HasCurrency(reqValue, secondaryAsset))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_CURRENCY_TRACKED_AMOUNT: // 121
+ case ModifierTreeType::TargetThreatListSizeLessThan: // 120
+ {
+ if (!unit || !unit->CanHaveThreatList())
+ return false;
+ if (unit->GetThreatManager().GetThreatListSize() >= reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasTrackedCurrencyEqualOrGreaterThan: // 121
if (referencePlayer->GetTrackedCurrencyCount(reqValue) < secondaryAsset)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_MAP_INSTANCE_TYPE: // 122
+ case ModifierTreeType::PlayerMapInstanceType: // 122
if (referencePlayer->GetMap()->GetEntry()->InstanceType != int8(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_MENTOR: // 123
+ case ModifierTreeType::PlayerInTimeWalkerInstance: // 123
if (!referencePlayer->HasPlayerFlag(PLAYER_FLAGS_TIMEWALKING))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_LEVEL_ABOVE: // 126
+ case ModifierTreeType::PvpSeasonIsActive: // 124
+ if (!sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS))
+ return false;
+ break;
+ case ModifierTreeType::PvpSeason: // 125
+ if (sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) != reqValue)
+ return false;
+ break;
+ case ModifierTreeType::GarrisonTierEqualOrGreaterThan: // 126
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ABOVE_LEVEL: // 127
+ case ModifierTreeType::GarrisonFollowersWithLevelEqualOrGreaterThan: // 127
{
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
+ if (!garrison)
return false;
- uint32 followerCount = garrison->CountFollowers([secondaryAsset](Garrison::Follower const& follower)
+ uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
{
- return follower.PacketInfo.FollowerLevel >= secondaryAsset;
+ GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
+ return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= secondaryAsset;
});
if (followerCount < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ABOVE_QUALITY: // 128
+ case ModifierTreeType::GarrisonFollowersWithQualityEqualOrGreaterThan: // 128
{
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
+ if (!garrison)
return false;
- uint32 followerCount = garrison->CountFollowers([secondaryAsset](Garrison::Follower const& follower)
+ uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
{
- return follower.PacketInfo.Quality >= secondaryAsset;
+ GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
+ return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.Quality >= secondaryAsset;
});
if (followerCount < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_LEVEL_WITH_ABILITY: // 129
+ case ModifierTreeType::GarrisonFollowerWithAbilityAtLevelEqualOrGreaterThan: // 129
{
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
+ if (!garrison)
return false;
- uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
+ uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
{
- return follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
+ GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
+ return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
});
if (followerCount < 1)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_LEVEL_WITH_TRAIT: // 130
+ case ModifierTreeType::GarrisonFollowerWithTraitAtLevelEqualOrGreaterThan: // 130
{
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
+ if (!garrison)
return false;
GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(secondaryAsset);
if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
return false;
- uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
+ uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
{
- return follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
+ GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
+ return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility(secondaryAsset);
});
if (followerCount < 1)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_ABILITY_IN_BUILDING: // 131
+ case ModifierTreeType::GarrisonFollowerWithAbilityAssignedToBuilding: // 131
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
@@ -2227,7 +2394,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_TRAIT_IN_BUILDING: // 132
+ case ModifierTreeType::GarrisonFollowerWithTraitAssignedToBuilding: // 132
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
@@ -2246,7 +2413,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_LEVEL_IN_BUILDING: // 133
+ case ModifierTreeType::GarrisonFollowerWithLevelAssignedToBuilding: // 133
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
@@ -2264,7 +2431,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_ABOVE_LEVEL: // 134
+ case ModifierTreeType::GarrisonBuildingWithLevelEqualOrGreaterThan: // 134
{
Garrison* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
@@ -2282,19 +2449,34 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
}
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_BLUEPRINT: // 135
+ case ModifierTreeType::HasBlueprintForGarrisonBuilding: // 135
{
- GarrBuildingEntry const* blueprintBuilding = sGarrBuildingStore.LookupEntry(reqValue);
- if (!blueprintBuilding)
- return false;
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GarrisonType(blueprintBuilding->GarrTypeID))
+ if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
return false;
if (!garrison->HasBlueprint(reqValue))
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_INACTIVE: // 140
+ case ModifierTreeType::HasGarrisonBuildingSpecialization: // 136
+ return false; // OBSOLETE
+ case ModifierTreeType::AllGarrisonPlotsAreFull: // 137
+ {
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison || garrison->GetType() != GarrisonType(reqValue))
+ return false;
+ for (Garrison::Plot const* plot : garrison->GetPlots())
+ if (!plot->BuildingInfo.PacketInfo)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerIsInOwnGarrison: // 138
+ if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() != referencePlayer->GetGUID().GetCounter())
+ return false;
+ break;
+ case ModifierTreeType::GarrisonShipmentOfTypeIsPending: // 139 NYI
+ return false;
+ case ModifierTreeType::GarrisonBuildingIsUnderConstruction: // 140
{
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(reqValue);
if (!building)
@@ -2311,7 +2493,9 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
}
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_EQUAL_LEVEL: // 142
+ case ModifierTreeType::GarrisonMissionHasBeenCompleted: // 141 NYI
+ return false;
+ case ModifierTreeType::GarrisonBuildingLevelEqual: // 142
{
Garrison* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
@@ -2322,14 +2506,14 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
continue;
GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
- if (!building || building->UpgradeLevel != reqValue || building->BuildingType != secondaryAsset)
+ if (!building || building->UpgradeLevel != secondaryAsset || building->BuildingType != reqValue)
continue;
return true;
}
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_ABILITY: // 143
+ case ModifierTreeType::GarrisonFollowerHasAbility: // 143
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
@@ -2353,7 +2537,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
}
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_TRAIT: // 144
+ case ModifierTreeType::GarrisonFollowerHasTrait: // 144
{
GarrAbilityEntry const* traitEntry = sGarrAbilityStore.LookupEntry(reqValue);
if (!traitEntry || !(traitEntry->Flags & GARRISON_ABILITY_FLAG_TRAIT))
@@ -2378,7 +2562,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
}
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_QUALITY_WOD: // 145
+ case ModifierTreeType::GarrisonFollowerQualityEqual: // 145
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GARRISON_TYPE_GARRISON)
@@ -2400,7 +2584,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
}
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_EQUAL_LEVEL: // 146
+ case ModifierTreeType::GarrisonFollowerLevelEqual: // 146
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset))
@@ -2408,21 +2592,56 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
if (miscValue1)
{
Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
- if (!follower || follower->PacketInfo.FollowerLevel < reqValue)
+ if (!follower || follower->PacketInfo.FollowerLevel != reqValue)
return false;
}
else
{
uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
{
- return follower.PacketInfo.FollowerLevel >= reqValue;
+ return follower.PacketInfo.FollowerLevel == reqValue;
});
if (followerCount < 1)
return false;
}
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES_IN_TEAM: // 151
+ case ModifierTreeType::GarrisonMissionIsRare: // 147 NYI
+ case ModifierTreeType::GarrisonMissionIsElite: // 148 NYI
+ return false;
+ case ModifierTreeType::CurrentGarrisonBuildingLevelEqual: // 149
+ {
+ if (!miscValue1)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ for (Garrison::Plot const* plot : garrison->GetPlots())
+ {
+ if (!plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->GarrBuildingID != miscValue1)
+ continue;
+
+ GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
+ if (!building || building->UpgradeLevel != reqValue)
+ continue;
+
+ return true;
+ }
+ break;
+ }
+ case ModifierTreeType::GarrisonPlotInstanceHasBuildingThatIsReadyToActivate: // 150
+ {
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Plot const* plot = garrison->GetPlot(reqValue);
+ if (!plot)
+ return false;
+ if (!plot->BuildingInfo.CanActivate() || !plot->BuildingInfo.PacketInfo || plot->BuildingInfo.PacketInfo->Active)
+ return false;
+ break;
+ }
+ case ModifierTreeType::BattlePetTeamWithSpeciesEqualOrGreaterThan: // 151
{
uint32 count = 0;
for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
@@ -2432,7 +2651,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_FAMILY_IN_TEAM: // 152
+ case ModifierTreeType::BattlePetTeamWithTypeEqualOrGreaterThan: // 152
{
uint32 count = 0;
for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
@@ -2443,113 +2662,219 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ID: // 157
+ case ModifierTreeType::PetBattleLastAbility: // 153 NYI
+ case ModifierTreeType::PetBattleLastAbilityType: // 154 NYI
+ return false;
+ case ModifierTreeType::BattlePetTeamWithAliveEqualOrGreaterThan: // 155
+ {
+ uint32 count = 0;
+ for (WorldPackets::BattlePet::BattlePetSlot const& slot : referencePlayer->GetSession()->GetBattlePetMgr()->GetSlots())
+ if (slot.Pet.Health > 0)
+ ++count;
+ if (count < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::HasGarrisonBuildingActiveSpecialization: // 156
+ return false; // OBSOLETE
+ case ModifierTreeType::HasGarrisonFollower: // 157
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison)
return false;
- if (miscValue1)
+ uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
{
- Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
- if (!follower || follower->PacketInfo.GarrFollowerID != reqValue)
- return false;
- }
- else
+ return follower.PacketInfo.GarrFollowerID == reqValue;
+ });
+ if (followerCount < 1)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerQuestObjectiveProgressEqual: // 158
+ {
+ QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
+ if (!objective)
+ return false;
+ if (referencePlayer->GetQuestObjectiveData(*objective) != int32(secondaryAsset))
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerQuestObjectiveProgressEqualOrGreaterThan: // 159
+ {
+ QuestObjective const* objective = sObjectMgr->GetQuestObjective(reqValue);
+ if (!objective)
+ return false;
+ if (referencePlayer->GetQuestObjectiveData(*objective) < int32(secondaryAsset))
+ return false;
+ break;
+ }
+ case ModifierTreeType::IsPTRRealm: // 160
+ case ModifierTreeType::IsBetaRealm: // 161
+ case ModifierTreeType::IsQARealm: // 162
+ return false; // always false
+ case ModifierTreeType::GarrisonShipmentContainerIsFull: // 163
+ return false;
+ case ModifierTreeType::PlayerCountIsValidToStartGarrisonInvasion: // 164
+ return true; // Only 1 player is required and referencePlayer->GetMap() will ALWAYS have at least the referencePlayer on it
+ case ModifierTreeType::InstancePlayerCountEqualOrLessThan: // 165
+ if (referencePlayer->GetMap()->GetPlayersCountExceptGMs() > reqValue)
+ return false;
+ break;
+ case ModifierTreeType::AllGarrisonPlotsFilledWithBuildingsWithLevelEqualOrGreater: // 166
+ {
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison || garrison->GetType() != GarrisonType(reqValue))
+ return false;
+ for (Garrison::Plot const* plot : garrison->GetPlots())
{
- uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
- {
- return follower.PacketInfo.GarrFollowerID == reqValue;
- });
- if (followerCount < 1)
+ if (!plot->BuildingInfo.PacketInfo)
+ return false;
+ GarrBuildingEntry const* building = sGarrBuildingStore.LookupEntry(plot->BuildingInfo.PacketInfo->GarrBuildingID);
+ if (!building || building->UpgradeLevel != reqValue)
return false;
}
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_ITEM_LEVEL: // 168
+ case ModifierTreeType::GarrisonMissionType: // 167 NYI
+ return false;
+ case ModifierTreeType::GarrisonFollowerItemLevelEqualOrGreaterThan: // 168
{
+ if (!miscValue1)
+ return false;
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison)
return false;
- if (miscValue1)
+ uint32 followerCount = garrison->CountFollowers([miscValue1, reqValue](Garrison::Follower const& follower)
{
- Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
- if (!follower || follower->PacketInfo.GarrFollowerID != reqValue)
- return false;
- }
- else
- {
- uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
- {
- return follower.GetItemLevel() >= reqValue;
- });
- if (followerCount < 1)
- return false;
- }
+ return follower.PacketInfo.GarrFollowerID == miscValue1 && follower.GetItemLevel() >= reqValue;
+ });
+ if (followerCount < 1)
+ return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ABOVE_ITEM_LEVEL: // 169
+ case ModifierTreeType::GarrisonFollowerCountWithItemLevelEqualOrGreaterThan: // 169
{
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
+ if (!garrison)
return false;
- uint32 followerCount = garrison->CountFollowers([secondaryAsset](Garrison::Follower const& follower)
+ uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
{
- return follower.GetItemLevel() >= secondaryAsset;
+ GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
+ return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.GetItemLevel() >= secondaryAsset;
});
if (followerCount < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_LEVEL_EQUAL: // 170
+ case ModifierTreeType::GarrisonTierEqual: // 170
{
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GARRISON_TYPE_GARRISON || garrison->GetSiteLevel()->GarrLevel != reqValue)
+ if (!garrison || garrison->GetType() != GarrisonType(secondaryAsset) || garrison->GetSiteLevel()->GarrLevel != reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGETING_CORPSE: // 173
+ case ModifierTreeType::InstancePlayerCountEqual: // 171
+ if (referencePlayer->GetMap()->GetPlayers().getSize() != reqValue)
+ return false;
+ break;
+ case ModifierTreeType::CurrencyId: // 172
+ if (miscValue1 != reqValue)
+ return false;
+ break;
+ case ModifierTreeType::SelectionIsPlayerCorpse: // 173
if (referencePlayer->GetTarget().GetHigh() != HighGuid::Corpse)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_LEVEL_EQUAL: // 175
+ case ModifierTreeType::PlayerCanAcceptQuest: // 174
+ {
+ Quest const* quest = sObjectMgr->GetQuestTemplate(reqValue);
+ if (!quest)
+ return false;
+ if (!referencePlayer->CanTakeQuest(quest, false))
+ return false;
+ break;
+ }
+ case ModifierTreeType::GarrisonFollowerCountWithLevelEqualOrGreaterThan: // 175
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison || garrison->GetType() != GarrisonType(tertiaryAsset))
return false;
- uint32 followerCount = garrison->CountFollowers([secondaryAsset](Garrison::Follower const& follower)
+ uint32 followerCount = garrison->CountFollowers([secondaryAsset, tertiaryAsset](Garrison::Follower const& follower)
{
- return follower.PacketInfo.FollowerLevel >= secondaryAsset;
+ GarrFollowerEntry const* garrFollower = sGarrFollowerStore.AssertEntry(follower.PacketInfo.GarrFollowerID);
+ return garrFollower->GarrFollowerTypeID == tertiaryAsset && follower.PacketInfo.FollowerLevel == secondaryAsset;
});
if (followerCount < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ID_IN_BUILDING: // 176
+ case ModifierTreeType::GarrisonFollowerIsInBuilding: // 176
{
Garrison const* garrison = referencePlayer->GetGarrison();
- if (!garrison || garrison->GetType() != GARRISON_TYPE_GARRISON)
+ if (!garrison)
return false;
uint32 followerCount = garrison->CountFollowers([reqValue, secondaryAsset](Garrison::Follower const& follower)
{
- if (follower.PacketInfo.GarrFollowerID != reqValue)
- return false;
- GarrBuildingEntry const* followerBuilding = sGarrBuildingStore.LookupEntry(follower.PacketInfo.CurrentBuildingID);
- if (!followerBuilding)
- return false;
- return followerBuilding->BuildingType == secondaryAsset;
+ return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentBuildingID == secondaryAsset;
});
if (followerCount < 1)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_WORLD_PVP_AREA: // 179
+ case ModifierTreeType::GarrisonMissionCountLessThan: // 177 NYI
+ return false;
+ case ModifierTreeType::GarrisonPlotInstanceCountEqualOrGreaterThan: // 178
{
- Battlefield const* bf = sBattlefieldMgr->GetBattlefieldToZoneId(referencePlayer->GetZoneId());
- if (!bf || bf->GetBattleId() != reqValue)
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison || garrison->GetType() != GarrisonType(reqValue))
+ return false;
+ uint32 plotCount = 0;
+ for (Garrison::Plot const* plot : garrison->GetPlots())
+ {
+ GarrPlotInstanceEntry const* garrPlotInstance = sGarrPlotInstanceStore.LookupEntry(plot->PacketInfo.GarrPlotInstanceID);
+ if (!garrPlotInstance || garrPlotInstance->GarrPlotID != secondaryAsset)
+ continue;
+ ++plotCount;
+ }
+ if (plotCount < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::CurrencySource: // 179 NYI
+ return false;
+ case ModifierTreeType::PlayerIsInNotOwnGarrison: // 180
+ if (!referencePlayer->GetMap()->IsGarrison() || referencePlayer->GetMap()->GetInstanceId() == referencePlayer->GetGUID().GetCounter())
+ return false;
+ break;
+ case ModifierTreeType::HasActiveGarrisonFollower: // 181
+ {
+ Garrison const* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
+ {
+ return follower.PacketInfo.GarrFollowerID == reqValue && !(follower.PacketInfo.FollowerStatus & FOLLOWER_STATUS_INACTIVE);
+ });
+ if (followerCount < 1)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ITEM_LEVEL_ABOVE: // 184
+ case ModifierTreeType::PlayerDailyRandomValueMod_X_Equals: // 182 NYI
+ return false;
+ case ModifierTreeType::PlayerHasMount: // 183
+ {
+ for (auto&& p : referencePlayer->GetSession()->GetCollectionMgr()->GetAccountMounts())
+ {
+ MountEntry const* mount = sDB2Manager.GetMount(p.first);
+ if (!mount)
+ continue;
+
+ if (mount->ID == reqValue)
+ return true;
+ }
+ return false;
+ }
+ case ModifierTreeType::GarrisonFollowerCountWithInactiveWithItemLevelEqualOrGreaterThan: // 184
{
Garrison const* garrison = referencePlayer->GetGarrison();
if (!garrison)
@@ -2565,48 +2890,108 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_USED_LEVEL_BOOST_LESS_THAN_HOURS_AGO: // 188
+ case ModifierTreeType::GarrisonFollowerIsOnAMission: // 185
+ {
+ Garrison const* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ uint32 followerCount = garrison->CountFollowers([reqValue](Garrison::Follower const& follower)
+ {
+ return follower.PacketInfo.GarrFollowerID == reqValue && follower.PacketInfo.CurrentMissionID != 0;
+ });
+ if (followerCount < 1)
+ return false;
+ break;
+ }
+ case ModifierTreeType::GarrisonMissionCountInSetLessThan: // 186 NYI
+ return false;
+ case ModifierTreeType::GarrisonFollowerType: // 187
+ {
+ GarrFollowerEntry const* garrFollower = sGarrFollowerStore.LookupEntry(miscValue1);
+ if (!garrFollower || garrFollower->GarrFollowerTypeID != reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerUsedBoostLessThanHoursAgoRealTime: // 188 NYI
+ case ModifierTreeType::PlayerUsedBoostLessThanHoursAgoGameTime: // 189 NYI
+ return false;
+ case ModifierTreeType::PlayerIsMercenary: // 190
+ if (!referencePlayer->HasPlayerFlagEx(PLAYER_FLAGS_EX_MERCENARY_MODE))
+ return false;
+ break;
+ case ModifierTreeType::PlayerEffectiveRace: // 191 NYI
+ case ModifierTreeType::TargetEffectiveRace: // 192 NYI
return false;
- case CRITERIA_ADDITIONAL_CONDITION_HONOR_LEVEL: // 193
- if (referencePlayer->GetHonorLevel() != reqValue)
+ case ModifierTreeType::HonorLevelEqualOrGreaterThan: // 193
+ if (referencePlayer->GetHonorLevel() < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_PRESTIGE_LEVEL: // 194
+ case ModifierTreeType::PrestigeLevelEqualOrGreaterThan: // 194
+ return false; // OBSOLOTE
+ case ModifierTreeType::GarrisonMissionIsReadyToCollect: // 195 NYI
+ case ModifierTreeType::PlayerIsInstanceOwner: // 196 NYI
return false;
- case CRITERIA_ADDITIONAL_CONDITION_ITEM_MODIFIED_APPEARANCE: // 200
+ case ModifierTreeType::PlayerHasHeirloom: // 197
+ if (!Trinity::Containers::MapGetValuePtr(referencePlayer->GetSession()->GetCollectionMgr()->GetAccountHeirlooms(), reqValue))
+ return false;
+ break;
+ case ModifierTreeType::TeamPoints: // 198 NYI
+ return false;
+ case ModifierTreeType::PlayerHasToy: // 199
+ if (!referencePlayer->GetSession()->GetCollectionMgr()->HasToy(reqValue))
+ return false;
+ break;
+ case ModifierTreeType::PlayerHasTransmog: // 200
{
std::pair<bool, bool> hasAppearance = referencePlayer->GetSession()->GetCollectionMgr()->HasItemAppearance(reqValue);
if (!hasAppearance.first || hasAppearance.second)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_HAS_CHARACTER_RESTRICTIONS: // 203
+ case ModifierTreeType::GarrisonTalentSelected: // 201 NYI
+ case ModifierTreeType::GarrisonTalentResearched: // 202 NYI
+ return false;
+ case ModifierTreeType::PlayerHasRestriction: // 203
{
- if (referencePlayer->m_activePlayerData->CharacterRestrictions.empty())
+ int32 restrictionIndex = referencePlayer->m_activePlayerData->CharacterRestrictions.FindIndexIf([reqValue](UF::CharacterRestriction const& restriction)
+ {
+ return restriction.Type == reqValue;
+ });
+ if (restrictionIndex < 0)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_QUEST_INFO_ID: // 206
+ case ModifierTreeType::PlayerCreatedCharacterLessThanHoursAgoRealTime: // 204 NYI
+ return false;
+ case ModifierTreeType::PlayerCreatedCharacterLessThanHoursAgoGameTime: // 205
+ if (Hours(reqValue) >= Seconds(referencePlayer->GetTotalPlayedTime()))
+ return false;
+ break;
+ case ModifierTreeType::QuestHasQuestInfoId: // 206
{
Quest const* quest = sObjectMgr->GetQuestTemplate(miscValue1);
if (!quest || quest->GetQuestInfoID() != reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_ARTIFACT_APPEARANCE_SET_USED: // 208
+ case ModifierTreeType::GarrisonTalentResearchInProgress: // 207 NYI
+ return false;
+ case ModifierTreeType::PlayerEquippedArtifactAppearanceSet: // 208
{
- for (uint8 slot = EQUIPMENT_SLOT_MAINHAND; slot <= EQUIPMENT_SLOT_RANGED; ++slot)
- if (Item* artifact = referencePlayer->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
+ if (Aura const* artifactAura = referencePlayer->GetAura(ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE))
+ if (Item* artifact = referencePlayer->GetItemByGuid(artifactAura->GetCastItemGUID()))
if (ArtifactAppearanceEntry const* artifactAppearance = sArtifactAppearanceStore.LookupEntry(artifact->GetModifier(ITEM_MODIFIER_ARTIFACT_APPEARANCE_ID)))
if (artifactAppearance->ArtifactAppearanceSetID == reqValue)
- return true;
+ break;
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_CURRENCY_AMOUNT_EQUAL: // 209
+ case ModifierTreeType::PlayerHasCurrencyEqual: // 209
if (referencePlayer->GetCurrency(reqValue) != secondaryAsset)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SCENARIO_TYPE: // 211
+ case ModifierTreeType::MinimumAverageItemHighWaterMarkForSpec: // 210 NYI
+ return false;
+ case ModifierTreeType::PlayerScenarioType: // 211
{
Scenario const* scenario = referencePlayer->GetScenario();
if (!scenario)
@@ -2615,45 +3000,292 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_ACCOUNT_EXPANSION_EQUAL: // 212
- if (referencePlayer->GetSession()->GetAccountExpansion() != reqValue)
+ case ModifierTreeType::PlayersAuthExpansionLevelEqualOrGreaterThan: // 212
+ if (referencePlayer->GetSession()->GetAccountExpansion() < reqValue)
+ return false;
+ break;
+ case ModifierTreeType::PlayerLastWeek2v2Rating: // 213 NYI
+ case ModifierTreeType::PlayerLastWeek3v3Rating: // 214 NYI
+ case ModifierTreeType::PlayerLastWeekRBGRating: // 215 NYI
+ return false;
+ case ModifierTreeType::GroupMemberCountFromConnectedRealmEqualOrGreaterThan: // 216
+ {
+ uint32 memberCount = 0;
+ if (Group const* group = referencePlayer->GetGroup())
+ for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ if (itr->GetSource() != referencePlayer && *referencePlayer->m_playerData->VirtualPlayerRealm == *itr->GetSource()->m_playerData->VirtualPlayerRealm)
+ ++memberCount;
+ if (memberCount < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::ArtifactTraitUnlockedCountEqualOrGreaterThan: // 217
+ {
+ Item const* artifact = referencePlayer->GetItemByEntry(secondaryAsset, ItemSearchLocation::Everywhere);
+ if (!artifact)
+ return false;
+ if (artifact->GetTotalUnlockedArtifactPowers() < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::ParagonReputationLevelEqualOrGreaterThan: // 218
+ if (referencePlayer->GetReputationMgr().GetParagonLevel(miscValue1) < int32(reqValue))
+ return false;
+ return false;
+ case ModifierTreeType::GarrisonShipmentIsReady: // 219 NYI
+ return false;
+ case ModifierTreeType::PlayerIsInPvpBrawl: // 220
+ {
+ BattlemasterListEntry const* bg = sBattlemasterListStore.LookupEntry(referencePlayer->GetBattlegroundTypeId());
+ if (!bg || !(bg->Flags & BATTLEMASTER_LIST_FLAG_BRAWL))
+ return false;
+ break;
+ }
+ case ModifierTreeType::ParagonReputationLevelWithFactionEqualOrGreaterThan: // 221
+ {
+ FactionEntry const* faction = sFactionStore.LookupEntry(secondaryAsset);
+ if (!faction)
+ return false;
+ if (referencePlayer->GetReputationMgr().GetParagonLevel(faction->ParagonFactionID) < int32(reqValue))
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasItemWithBonusListFromTreeAndQuality: // 222
+ {
+ std::set<uint32> bonusListIDs = sDB2Manager.GetAllItemBonusTreeBonuses(reqValue);
+ if (bonusListIDs.empty())
+ return false;
+
+ bool bagScanReachedEnd = referencePlayer->ForEachItem(ItemSearchLocation::Everywhere, [&bonusListIDs](Item const* item)
+ {
+ bool hasBonus = std::any_of(item->m_itemData->BonusListIDs->begin(), item->m_itemData->BonusListIDs->end(), [&bonusListIDs](int32 bonusListID)
+ {
+ return bonusListIDs.find(bonusListID) != bonusListIDs.end();
+ });
+ return hasBonus ? ItemSearchCallbackResult::Stop : ItemSearchCallbackResult::Continue;
+ });
+ if (bagScanReachedEnd)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasEmptyInventorySlotCountEqualOrGreaterThan: // 223
+ if (referencePlayer->GetFreeInventorySlotCount(ItemSearchLocation::Inventory) < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_ACHIEVEMENT_GLOBALLY_INCOMPLETED: // 231
+ case ModifierTreeType::PlayerHasItemInHistoryOfProgressiveEvent: // 224 NYI
+ return false;
+ case ModifierTreeType::PlayerHasArtifactPowerRankCountPurchasedEqualOrGreaterThan: // 225
{
- AchievementEntry const* achievement = sAchievementStore.LookupEntry(secondaryAsset);
- if (!achievement)
+ Aura const* artifactAura = referencePlayer->GetAura(ARTIFACTS_ALL_WEAPONS_GENERAL_WEAPON_EQUIPPED_PASSIVE);
+ if (!artifactAura)
+ return false;
+ Item const* artifact = referencePlayer->GetItemByGuid(artifactAura->GetCastItemGUID());
+ if (!artifact)
return false;
- if (sAchievementMgr->IsRealmCompleted(achievement))
+ UF::ArtifactPower const* artifactPower = artifact->GetArtifactPower(secondaryAsset);
+ if (!artifactPower)
+ return false;
+ if (artifactPower->PurchasedRank < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_MAIN_HAND_VISIBLE_SUBCLASS: // 232
+ case ModifierTreeType::PlayerHasBoosted: // 226
+ if (referencePlayer->HasLevelBoosted())
+ return false;
+ break;
+ case ModifierTreeType::PlayerHasRaceChanged: // 227
+ if (referencePlayer->HasRaceChanged())
+ return false;
+ break;
+ case ModifierTreeType::PlayerHasBeenGrantedLevelsFromRaF: // 228
+ if (referencePlayer->HasBeenGrantedLevelsFromRaF())
+ return false;
+ break;
+ case ModifierTreeType::IsTournamentRealm: // 229
+ return false;
+ case ModifierTreeType::PlayerCanAccessAlliedRaces: // 230
+ if (!referencePlayer->GetSession()->CanAccessAlliedRaces())
+ return false;
+ break;
+ case ModifierTreeType::GroupMemberCountWithAchievementEqualOrLessThan: // 231
{
+ if (Group const* group = referencePlayer->GetGroup())
+ {
+ uint32 membersWithAchievement = 0;
+ for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ if (itr->GetSource()->HasAchieved(secondaryAsset))
+ ++membersWithAchievement;
+
+ if (membersWithAchievement > reqValue)
+ return false;
+ }
+ // true if no group
+ break;
+ }
+ case ModifierTreeType::PlayerMainhandWeaponType: // 232
+ {
+ UF::VisibleItem const& visibleItem = referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_MAINHAND];
uint32 itemSubclass = ITEM_SUBCLASS_WEAPON_FIST_WEAPON;
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_MAINHAND].ItemID))
- itemSubclass = itemTemplate->GetSubClass();
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(visibleItem.ItemID))
+ {
+ if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
+ {
+ itemSubclass = itemTemplate->GetSubClass();
+
+ if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sDB2Manager.GetItemModifiedAppearance(visibleItem.ItemID, visibleItem.ItemAppearanceModID))
+ if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(itemModifiedAppearance->ID))
+ if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
+ itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
+ }
+ }
if (itemSubclass != reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_OFF_HAND_VISIBLE_SUBCLASS: // 233
+ case ModifierTreeType::PlayerOffhandWeaponType: // 233
{
+ UF::VisibleItem const& visibleItem = referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_OFFHAND];
uint32 itemSubclass = ITEM_SUBCLASS_WEAPON_FIST_WEAPON;
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(referencePlayer->m_playerData->VisibleItems[EQUIPMENT_SLOT_OFFHAND].ItemID))
- itemSubclass = itemTemplate->GetSubClass();
+ if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(visibleItem.ItemID))
+ {
+ if (itemTemplate->GetClass() == ITEM_CLASS_WEAPON)
+ {
+ itemSubclass = itemTemplate->GetSubClass();
+
+ if (ItemModifiedAppearanceEntry const* itemModifiedAppearance = sDB2Manager.GetItemModifiedAppearance(visibleItem.ItemID, visibleItem.ItemAppearanceModID))
+ if (ItemModifiedAppearanceExtraEntry const* itemModifiedAppearaceExtra = sItemModifiedAppearanceExtraStore.LookupEntry(itemModifiedAppearance->ID))
+ if (itemModifiedAppearaceExtra->DisplayWeaponSubclassID > 0)
+ itemSubclass = itemModifiedAppearaceExtra->DisplayWeaponSubclassID;
+ }
+ }
if (itemSubclass != reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_AZERITE_ITEM_LEVEL: // 235
+ case ModifierTreeType::PlayerPvpTier: // 234
+ {
+ PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(reqValue);
+ if (!pvpTier)
+ return false;
+ if (std::size_t(pvpTier->BracketID) >= referencePlayer->m_activePlayerData->PvpInfo.size())
+ return false;
+ UF::PVPInfo const& pvpInfo = referencePlayer->m_activePlayerData->PvpInfo[pvpTier->BracketID];
+ if (pvpTier->ID != pvpInfo.PvpTierID || *pvpInfo.Disqualified)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerAzeriteLevelEqualOrGreaterThan: // 235
{
Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere);
if (!heartOfAzeroth || heartOfAzeroth->ToAzeriteItem()->GetLevel() < reqValue)
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_DISPLAY_RACE: // 252
+ case ModifierTreeType::PlayerIsOnQuestInQuestline: // 236
+ {
+ bool isOnQuest = false;
+ if (std::unordered_set<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue))
+ {
+ isOnQuest = std::any_of(questLineQuests->begin(), questLineQuests->end(), [referencePlayer](QuestLineXQuestEntry const* questLineQuest)
+ {
+ return referencePlayer->FindQuestSlot(questLineQuest->QuestID) < MAX_QUEST_LOG_SIZE;
+ });
+ }
+ if (!isOnQuest)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerIsQnQuestLinkedToScheduledWorldStateGroup: // 237
+ return false; // OBSOLETE (db2 removed)
+ case ModifierTreeType::PlayerIsInRaidGroup: // 238
+ {
+ Group const* group = referencePlayer->GetGroup();
+ if (!group || !group->isRaidGroup())
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerPvpTierInBracketEqualOrGreaterThan: // 239
+ {
+ if (secondaryAsset >= referencePlayer->m_activePlayerData->PvpInfo.size())
+ return false;
+ UF::PVPInfo const& pvpInfo = referencePlayer->m_activePlayerData->PvpInfo[secondaryAsset];
+ PvpTierEntry const* pvpTier = sPvpTierStore.LookupEntry(pvpInfo.PvpTierID);
+ if (!pvpTier)
+ return false;
+ if (pvpTier->Rank < int32(reqValue))
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerCanAcceptQuestInQuestline: // 240
+ {
+ std::unordered_set<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
+ if (!questLineQuests)
+ return false;
+ bool canTakeQuest = std::any_of(questLineQuests->begin(), questLineQuests->end(), [referencePlayer](QuestLineXQuestEntry const* questLineQuest)
+ {
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(questLineQuest->QuestID))
+ return referencePlayer->CanTakeQuest(quest, false);
+ return false;
+ });
+ if (!canTakeQuest)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasCompletedQuestline: // 241
+ {
+ std::unordered_set<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
+ if (!questLineQuests)
+ return false;
+ for (QuestLineXQuestEntry const* questLineQuest : *questLineQuests)
+ if (!referencePlayer->GetQuestRewardStatus(questLineQuest->QuestID))
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasCompletedQuestlineQuestCount: // 242
+ {
+ std::unordered_set<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
+ if (!questLineQuests)
+ return false;
+ uint32 completedQuests = 0;
+ for (QuestLineXQuestEntry const* questLineQuest : *questLineQuests)
+ if (referencePlayer->GetQuestRewardStatus(questLineQuest->QuestID))
+ ++completedQuests;
+ if (completedQuests < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasCompletedPercentageOfQuestline: // 243
+ {
+ std::unordered_set<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(reqValue);
+ if (!questLineQuests || questLineQuests->empty())
+ return false;
+ std::size_t completedQuests = 0;
+ for (QuestLineXQuestEntry const* questLineQuest : *questLineQuests)
+ if (referencePlayer->GetQuestRewardStatus(questLineQuest->QuestID))
+ ++completedQuests;
+ if (GetPctOf(completedQuests, questLineQuests->size()) < reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasWarModeEnabled: // 244
+ if (!referencePlayer->HasPlayerLocalFlag(PLAYER_LOCAL_FLAG_WAR_MODE))
+ return false;
+ break;
+ case ModifierTreeType::PlayerIsOnWarModeShard: // 245
+ if (!referencePlayer->HasPlayerFlag(PLAYER_FLAGS_WAR_MODE_ACTIVE))
+ return false;
+ break;
+ case ModifierTreeType::PlayerIsAllowedToToggleWarModeInArea: // 246
+ if (!referencePlayer->CanEnableWarModeInArea())
+ return false;
+ break;
+ case ModifierTreeType::MythicPlusKeystoneLevelEqualOrGreaterThan: // 247 NYI
+ case ModifierTreeType::MythicPlusCompletedInTime: // 248 NYI
+ case ModifierTreeType::MythicPlusMapChallengeMode: // 249 NYI
+ case ModifierTreeType::MythicPlusDisplaySeason: // 250 NYI
+ case ModifierTreeType::MythicPlusMilestoneSeason: // 251 NYI
+ return false;
+ case ModifierTreeType::PlayerVisibleRace: // 252
{
CreatureDisplayInfoEntry const* creatureDisplayInfo = sCreatureDisplayInfoStore.LookupEntry(referencePlayer->GetDisplayId());
if (!creatureDisplayInfo)
@@ -2665,7 +3297,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_DISPLAY_RACE: // 253
+ case ModifierTreeType::TargetVisibleRace: // 253
{
if (!unit)
return false;
@@ -2679,23 +3311,43 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_AURA_COUNT_EQUAL: // 255
+ case ModifierTreeType::FriendshipRepReactionEqual: // 254
+ {
+ FriendshipRepReactionEntry const* friendshipRepReaction = sFriendshipRepReactionStore.LookupEntry(reqValue);
+ if (!friendshipRepReaction)
+ return false;
+ FriendshipReputationEntry const* friendshipReputation = sFriendshipReputationStore.LookupEntry(friendshipRepReaction->FriendshipRepID);
+ if (!friendshipReputation)
+ return false;
+ DB2Manager::FriendshipRepReactionSet const* friendshipReactions = sDB2Manager.GetFriendshipRepReactions(reqValue);
+ if (!friendshipReactions)
+ return false;
+ uint32 rank = referencePlayer->GetReputationRank(friendshipReputation->FactionID);
+ if (rank >= friendshipReactions->size())
+ return false;
+ auto itr = friendshipReactions->begin();
+ std::advance(itr, rank);
+ if ((*itr)->ID != reqValue)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerAuraStackCountEqual: // 255
if (referencePlayer->GetAuraCount(secondaryAsset) != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_AURA_COUNT_EQUAL: // 256
+ case ModifierTreeType::TargetAuraStackCountEqual: // 256
if (!unit || unit->GetAuraCount(secondaryAsset) != reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_AURA_COUNT_GREATER: // 257
+ case ModifierTreeType::PlayerAuraStackCountEqualOrGreaterThan: // 257
if (referencePlayer->GetAuraCount(secondaryAsset) < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_AURA_COUNT_GREATER: // 258
+ case ModifierTreeType::TargetAuraStackCountEqualOrGreaterThan: // 258
if (!unit || unit->GetAuraCount(secondaryAsset) < reqValue)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_LOWER: // 259
+ case ModifierTreeType::PlayerHasAzeriteEssenceRankLessThan: // 259
{
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
@@ -2704,7 +3356,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return true;
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_EQUAL: // 260
+ case ModifierTreeType::PlayerHasAzeriteEssenceRankEqual: // 260
{
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
@@ -2713,7 +3365,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return true;
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_GREATER: // 261
+ case ModifierTreeType::PlayerHasAzeriteEssenceRankGreaterThan: // 261
{
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
@@ -2722,22 +3374,31 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return true;
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA_EFFECT_INDEX: // 262
+ case ModifierTreeType::PlayerHasAuraWithEffectIndex: // 262
if (!referencePlayer->GetAuraEffect(reqValue, secondaryAsset))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_SPECIALIZATION_ROLE: // 263
+ case ModifierTreeType::PlayerLootSpecializationMatchesRole: // 263
{
ChrSpecializationEntry const* spec = sChrSpecializationStore.LookupEntry(referencePlayer->GetPrimarySpecialization());
if (!spec || spec->Role != int32(reqValue))
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_120: // 264
- if (referencePlayer->getLevel() != 60)
+ case ModifierTreeType::PlayerIsAtMaxExpansionLevel: // 264
+ if (referencePlayer->getLevel() != GetMaxLevelForExpansion(sWorld->getIntConfig(CONFIG_EXPANSION)))
+ return false;
+ break;
+ case ModifierTreeType::TransmogSource: // 265
+ {
+ ItemModifiedAppearanceEntry const* itemModifiedAppearance = sItemModifiedAppearanceStore.LookupEntry(miscValue2);
+ if (!itemModifiedAppearance)
+ return false;
+ if (itemModifiedAppearance->TransmogSourceTypeEnum != int32(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_LOWER: // 266
+ }
+ case ModifierTreeType::PlayerHasAzeriteEssenceInSlotAtRankLessThan: // 266
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
@@ -2745,7 +3406,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
if (essence.AzeriteEssenceID == selectedEssences->AzeriteEssenceID[reqValue] && essence.Rank < secondaryAsset)
return true;
return false;
- case CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_GREATER: // 267
+ case ModifierTreeType::PlayerHasAzeriteEssenceInSlotAtRankGreaterThan: // 267
if (Item const* heartOfAzeroth = referencePlayer->GetItemByEntry(ITEM_ID_HEART_OF_AZEROTH, ItemSearchLocation::Everywhere))
if (AzeriteItem const* azeriteItem = heartOfAzeroth->ToAzeriteItem())
if (UF::SelectedAzeriteEssences const* selectedEssences = azeriteItem->GetSelectedAzeriteEssences())
@@ -2753,7 +3414,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
if (essence.AzeriteEssenceID == selectedEssences->AzeriteEssenceID[reqValue] && essence.Rank > secondaryAsset)
return true;
return false;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_IN_RANGE_CT: // 268
+ case ModifierTreeType::PlayerLevelWithinContentTuning: // 268
{
uint8 level = referencePlayer->getLevel();
if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0))
@@ -2764,7 +3425,7 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
}
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_IN_RANGE_CT: // 269
+ case ModifierTreeType::TargetLevelWithinContentTuning: // 269
{
if (!unit)
return false;
@@ -2777,14 +3438,23 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
}
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_GREATER_CT: // 272
+ case ModifierTreeType::PlayerIsScenarioInitiator: // 270 NYI
+ return false;
+ case ModifierTreeType::PlayerHasCompletedQuestOrIsOnQuest: // 271
+ {
+ QuestStatus status = referencePlayer->GetQuestStatus(reqValue);
+ if (status == QUEST_STATUS_NONE || status == QUEST_STATUS_FAILED)
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerLevelWithinOrAboveContentTuning: // 272
{
uint8 level = referencePlayer->getLevel();
if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(reqValue, 0))
return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel;
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_GREATER_CT: // 273
+ case ModifierTreeType::TargetLevelWithinOrAboveContentTuning: // 273
{
if (!unit)
return false;
@@ -2793,22 +3463,101 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return secondaryAsset ? level >= levels->MinLevelWithDelta : level >= levels->MinLevel;
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_MAP_OR_COSMETIC_MAP: // 280
+ case ModifierTreeType::PlayerLevelWithinOrAboveLevelRange: // 274 NYI
+ case ModifierTreeType::TargetLevelWithinOrAboveLevelRange: // 275 NYI
+ return false;
+ case ModifierTreeType::MaxJailersTowerLevelEqualOrGreaterThan: // 276
+ if (referencePlayer->m_activePlayerData->JailersTowerLevelMax < int32(reqValue))
+ return false;
+ break;
+ case ModifierTreeType::GroupedWithRaFRecruit: // 277
+ {
+ Group const* group = referencePlayer->GetGroup();
+ if (!group)
+ return false;
+ for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ if (itr->GetSource()->GetSession()->GetRecruiterId() == referencePlayer->GetSession()->GetAccountId())
+ return true;
+ return false;
+ }
+ case ModifierTreeType::GroupedWithRaFRecruiter: // 278
+ {
+ Group const* group = referencePlayer->GetGroup();
+ if (!group)
+ return false;
+ for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ if (itr->GetSource()->GetSession()->GetAccountId() == referencePlayer->GetSession()->GetRecruiterId())
+ return true;
+ return false;
+ }
+ case ModifierTreeType::PlayerSpecialization: // 279
+ if (referencePlayer->GetPrimarySpecialization() != reqValue)
+ return false;
+ break;
+ case ModifierTreeType::PlayerMapOrCosmeticChildMap: // 280
{
MapEntry const* map = referencePlayer->GetMap()->GetEntry();
if (map->ID != reqValue && map->CosmeticParentMapID != int32(reqValue))
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_COVENANT: // 288
+ case ModifierTreeType::PlayerCanAccessShadowlandsPrepurchaseContent: // 281
+ if (referencePlayer->GetSession()->GetAccountExpansion() < EXPANSION_SHADOWLANDS)
+ return false;
+ break;
+ case ModifierTreeType::PlayerHasEntitlement: // 282 NYI
+ case ModifierTreeType::PlayerIsInPartySyncGroup: // 283 NYI
+ case ModifierTreeType::QuestHasPartySyncRewards: // 284 NYI
+ case ModifierTreeType::HonorGainSource: // 285 NYI
+ case ModifierTreeType::JailersTowerActiveFloorIndexEqualOrGreaterThan: // 286 NYI
+ case ModifierTreeType::JailersTowerActiveFloorDifficultyEqualOrGreaterThan: // 287 NYI
+ return false;
+ case ModifierTreeType::PlayerCovenant: // 288
if (referencePlayer->m_playerData->CovenantID != int32(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOULBIND: // 291
+ case ModifierTreeType::HasTimeEventPassed: // 289
+ {
+ time_t eventTimestamp = GameTime::GetGameTime();
+ switch (reqValue)
+ {
+ case 111: // Battle for Azeroth Season 4 Start
+ eventTimestamp = time_t(1579618800); // January 21, 2020 8:00
+ break;
+ case 120: // Patch 9.0.1
+ eventTimestamp = time_t(1602601200); // October 13, 2020 8:00
+ break;
+ case 121: // Shadowlands Season 1 Start
+ eventTimestamp = time_t(1607439600); // December 8, 2020 8:00
+ break;
+ case 123: // Shadowlands Season 1 End
+ // timestamp = unknown
+ break;;
+ case 149: // Shadowlands Season 2 End
+ // timestamp = unknown
+ break;
+ default:
+ break;
+ }
+ if (GameTime::GetGameTime() < eventTimestamp)
+ return false;
+ break;
+ }
+ case ModifierTreeType::GarrisonHasPermanentTalent: // 290 NYI
+ return false;
+ case ModifierTreeType::HasActiveSoulbind: // 291
if (referencePlayer->m_playerData->SoulbindID != int32(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE_IN_GROUP: // 293
+ case ModifierTreeType::HasMemorizedSpell: // 292 NYI
+ return false;
+ case ModifierTreeType::PlayerHasAPACSubscriptionReward_2020: // 293
+ case ModifierTreeType::PlayerHasTBCCDEWarpStalker_Mount: // 294
+ case ModifierTreeType::PlayerHasTBCCDEDarkPortal_Toy: // 295
+ case ModifierTreeType::PlayerHasTBCCDEPathOfIllidan_Toy: // 296
+ case ModifierTreeType::PlayerHasImpInABallToySubscriptionReward: // 297
+ return false;
+ case ModifierTreeType::PlayerIsInAreaGroup: // 298
{
std::vector<uint32> areas = sDB2Manager.GetAreasForGroup(reqValue);
if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(referencePlayer->GetAreaId()))
@@ -2817,15 +3566,30 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return true;
return false;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_SPECIFIC_CHROMIE_TIME: // 300
+ case ModifierTreeType::TargetIsInAreaGroup: // 299
+ {
+ if (!unit)
+ return false;
+ std::vector<uint32> areas = sDB2Manager.GetAreasForGroup(reqValue);
+ if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(unit->GetAreaId()))
+ for (uint32 areaInGroup : areas)
+ if (areaInGroup == area->ID || areaInGroup == area->ParentAreaID)
+ return true;
+ return false;
+ }
+ case ModifierTreeType::PlayerIsInChromieTime: // 300
if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID != int32(reqValue))
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_ANY_CHROMIE_TIME: // 301
+ case ModifierTreeType::PlayerIsInAnyChromieTime: // 301
if (referencePlayer->m_activePlayerData->UiChromieTimeExpansionID == 0)
return false;
break;
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_RUNEFORGE_LEGENDARY_KNOWN: // 303
+ case ModifierTreeType::ItemIsAzeriteArmor: // 302
+ if (!sDB2Manager.GetAzeriteEmpoweredItem(miscValue1))
+ return false;
+ break;
+ case ModifierTreeType::PlayerHasRuneforgePower: // 303
{
uint32 block = reqValue / 32;
if (block >= referencePlayer->m_activePlayerData->RuneforgePowers.size())
@@ -2834,7 +3598,29 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
uint32 bit = reqValue % 32;
return referencePlayer->m_activePlayerData->RuneforgePowers[block] & (1 << bit);
}
- case CRITERIA_ADDITIONAL_CONDITION_SHAPESHIFT_FORM_CUSTOMIZATION_DISPLAY: // 308
+ case ModifierTreeType::PlayerInChromieTimeForScaling: // 304
+ if (!(referencePlayer->m_playerData->CtrOptions->ContentTuningConditionMask & 1))
+ return false;
+ break;
+ case ModifierTreeType::IsRaFRecruit: // 305
+ if (!referencePlayer->GetSession()->GetRecruiterId())
+ return false;
+ break;
+ case ModifierTreeType::AllPlayersInGroupHaveAchievement: // 306
+ {
+ if (Group const* group = referencePlayer->GetGroup())
+ {
+ for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
+ if (!itr->GetSource()->HasAchieved(reqValue))
+ return false;
+ }
+ else if (!referencePlayer->HasAchieved(reqValue))
+ return false;
+ break;
+ }
+ case ModifierTreeType::PlayerHasSoulbindConduitRankEqualOrGreaterThan: // 307 NYI
+ return false;
+ case ModifierTreeType::PlayerSpellShapeshiftFormCreatureDisplayInfoSelection: // 308
{
ShapeshiftFormModelData const* formModelData = sDB2Manager.GetShapeshiftFormModelData(referencePlayer->getRace(), referencePlayer->GetNativeSex(), secondaryAsset);
if (!formModelData)
@@ -2850,12 +3636,45 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
return false;
break;
}
- case CRITERIA_ADDITIONAL_CONDITION_SOURCE_FLYING: // 311
+ case ModifierTreeType::PlayerSoulbindConduitCountAtRankEqualOrGreaterThan: // 309 NYI
+ return false;
+ case ModifierTreeType::PlayerIsRestrictedAccount: // 310
+ return false;
+ case ModifierTreeType::PlayerIsFlying: // 311
if (!referencePlayer->IsFlying())
return false;
break;
- default:
+ case ModifierTreeType::PlayerScenarioIsLastStep: // 312
+ {
+ Scenario const* scenario = referencePlayer->GetScenario();
+ if (!scenario)
+ return false;
+ if (scenario->GetStep() != scenario->GetLastStep())
+ return false;
break;
+ }
+ case ModifierTreeType::PlayerHasWeeklyRewardsAvailable: // 313
+ if (!*referencePlayer->m_activePlayerData->WeeklyRewardsPeriodSinceOrigin)
+ return false;
+ break;
+ case ModifierTreeType::TargetCovenant: // 314
+ if (!unit || !unit->IsPlayer())
+ return false;
+ if (unit->ToPlayer()->m_playerData->CovenantID != int32(reqValue))
+ return false;
+ break;
+ case ModifierTreeType::PlayerHasTBCCollectorsEdition: // 315
+ case ModifierTreeType::PlayerHasWrathCollectorsEdition: // 316
+ return false;
+ case ModifierTreeType::GarrisonTalentResearchedAndAtRankEqualOrGreaterThan: // 317 NYI
+ case ModifierTreeType::CurrencySpentOnGarrisonTalentResearchEqualOrGreaterThan: // 318 NYI
+ case ModifierTreeType::RenownCatchupActive: // 319 NYI
+ case ModifierTreeType::RapidRenownCatchupActive: // 320 NYI
+ case ModifierTreeType::PlayerMythicPlusRatingEqualOrGreaterThan: // 321 NYI
+ case ModifierTreeType::PlayerMythicPlusRunCountInCurrentExpansionEqualOrGreaterThan: // 322 NYI
+ return false;
+ default:
+ return false;
}
return true;
}
diff --git a/src/server/game/BattlePets/BattlePetMgr.cpp b/src/server/game/BattlePets/BattlePetMgr.cpp
index fc02c8db8e8..5fd954f931f 100644
--- a/src/server/game/BattlePets/BattlePetMgr.cpp
+++ b/src/server/game/BattlePets/BattlePetMgr.cpp
@@ -359,6 +359,16 @@ uint8 BattlePetMgr::GetPetCount(uint32 species) const
}));
}
+uint32 BattlePetMgr::GetPetUniqueSpeciesCount() const
+{
+ std::set<uint32> speciesIds;
+ std::transform(_pets.begin(), _pets.end(), std::inserter(speciesIds, speciesIds.end()), [](std::pair<uint64 const, BattlePet> const& pet)
+ {
+ return pet.second.PacketInfo.Species;
+ });
+ return speciesIds.size();
+}
+
void BattlePetMgr::UnlockSlot(uint8 slot)
{
if (!_slots[slot].Locked)
diff --git a/src/server/game/BattlePets/BattlePetMgr.h b/src/server/game/BattlePets/BattlePetMgr.h
index edf0937ea76..49ed9edc23f 100644
--- a/src/server/game/BattlePets/BattlePetMgr.h
+++ b/src/server/game/BattlePets/BattlePetMgr.h
@@ -96,7 +96,7 @@ public:
void CalculateStats();
WorldPackets::BattlePet::BattlePet PacketInfo;
- BattlePetSaveInfo SaveInfo;
+ BattlePetSaveInfo SaveInfo = BATTLE_PET_UNCHANGED;
};
explicit BattlePetMgr(WorldSession* owner);
@@ -114,6 +114,7 @@ public:
void RemovePet(ObjectGuid guid);
uint8 GetPetCount(uint32 species) const;
+ uint32 GetPetUniqueSpeciesCount() const;
WorldPackets::BattlePet::BattlePetSlot* GetSlot(uint8 slot) { return slot < _slots.size() ? &_slots[slot] : nullptr; }
void UnlockSlot(uint8 slot);
@@ -134,6 +135,8 @@ public:
void SendUpdates(std::vector<std::reference_wrapper<BattlePet>> pets, bool petAdded);
void SendError(BattlePetError error, uint32 creatureId);
+ bool HasJournalLock() const { return true; }
+
private:
WorldSession* _owner;
uint16 _trapLevel = 0;
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 8666e5ec3e3..ee13cf121bd 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -2393,6 +2393,17 @@ std::set<uint32> DB2Manager::GetDefaultItemBonusTree(uint32 itemId, ItemContext
return bonusListIDs;
}
+std::set<uint32> DB2Manager::GetAllItemBonusTreeBonuses(uint32 itemBonusTreeId) const
+{
+ std::set<uint32> bonusListIDs;
+ VisitItemBonusTree(itemBonusTreeId, true, [&bonusListIDs](ItemBonusTreeNodeEntry const* bonusTreeNode)
+ {
+ if (bonusTreeNode->ChildItemBonusListID)
+ bonusListIDs.insert(bonusTreeNode->ChildItemBonusListID);
+ });
+ return bonusListIDs;
+}
+
void LoadAzeriteEmpoweredItemUnlockMappings(std::unordered_map<int32, std::vector<AzeriteUnlockMappingEntry const*>> const& azeriteUnlockMappingsBySet, uint32 itemId)
{
auto itemIdRange = _itemToBonusTree.equal_range(itemId);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 63ca97a66fa..ded5f83d646 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -373,6 +373,7 @@ public:
ItemBonusList const* GetItemBonusList(uint32 bonusListId) const;
uint32 GetItemBonusListForItemLevelDelta(int16 delta) const;
std::set<uint32> GetDefaultItemBonusTree(uint32 itemId, ItemContext itemContext) const;
+ std::set<uint32> GetAllItemBonusTreeBonuses(uint32 itemBonusTreeId) const;
ItemChildEquipmentEntry const* GetItemChildEquipment(uint32 itemId) const;
ItemClassEntry const* GetItemClassByOldEnum(uint32 itemClass) const;
bool HasItemCurrencyCost(uint32 itemId) const;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 875576fe4c5..58ed8877447 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -104,6 +104,8 @@ enum AchievementFlags
ACHIEVEMENT_FLAG_TRACKING_FLAG = 0x00100000, // hidden tracking flag, sent to client in all cases except completion announcements
};
+uint32 constexpr ACHIVEMENT_CATEGORY_PET_BATTLES = 15117;
+
enum AreaFlags
{
AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
@@ -244,321 +246,6 @@ enum class CorruptionEffectsFlag
DEFINE_ENUM_FLAG(CorruptionEffectsFlag);
-enum CriteriaAdditionalCondition
-{
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_DRUNK_VALUE = 1,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_PLAYER_CONDITION = 2,
- CRITERIA_ADDITIONAL_CONDITION_ITEM_LEVEL = 3,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY = 4,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER = 5,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD = 6,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY = 7,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA = 8,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA_TYPE = 9,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA = 10,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE = 11,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_AURA_STATE = 12,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_AURA_STATE = 13,
- CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN = 14,
- CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS = 15,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_IS_ALIVE = 16,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE = 17,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE = 18,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_19 = 19,
- CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY_OLD = 20,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_YIELDS_XP = 21, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_ABOVE_TARGET = 22,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_EQUAL_TARGET = 23,
- CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE = 24,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE = 25,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS = 26,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE = 27,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS = 28,
- CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS = 29,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE = 30,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_FAMILY = 31,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP = 32,
- CRITERIA_ADDITIONAL_CONDITION_CLIENT_VERSION = 33,
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_TEAM_LEVEL = 34,
- CRITERIA_ADDITIONAL_CONDITION_NOT_IN_GROUP = 35,
- CRITERIA_ADDITIONAL_CONDITION_IN_GROUP = 36,
- CRITERIA_ADDITIONAL_CONDITION_MIN_PERSONAL_RATING = 37, // NYI
- CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX = 38,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL = 39,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL = 40,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_ZONE = 41,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE = 42,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_PCT_LOWER = 43,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_PCT_GREATER = 44,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_PCT_EQUAL = 45,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PCT_LOWER = 46,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PCT_GREATER = 47,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PCT_EQUAL = 48,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_LOWER = 49,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_GREATER = 50,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HEALTH_EQUAL = 51,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_LOWER = 52,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_GREATER = 53,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_EQUAL = 54,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_PLAYER_CONDITION = 55,
- CRITERIA_ADDITIONAL_CONDITION_MIN_ACHIEVEMENT_POINTS = 56,
- CRITERIA_ADDITIONAL_CONDITION_IN_LFG_DUNGEON = 57,
- CRITERIA_ADDITIONAL_CONDITION_IN_LFG_RANDOM_DUNGEON = 58,
- CRITERIA_ADDITIONAL_CONDITION_IN_LFG_FIRST_RANDOM_DUNGEON = 59,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_60 = 60, // NYI
- CRITERIA_ADDITIONAL_CONDITION_REQUIRES_GUILD_GROUP = 61, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GUILD_REPUTATION = 62,
- CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
- CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND_RATING = 64,
- CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
- CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
- CRITERIA_ADDITIONAL_CONDITION_WORLD_STATE_EXPRESSION = 67,
- CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY = 68,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_GREATER = 69,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_GREATER = 70,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_LOWER = 71,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_LOWER = 72,
- CRITERIA_ADDITIONAL_CONDITION_MODIFIER_TREE = 73,
- CRITERIA_ADDITIONAL_CONDITION_SCENARIO_ID = 74,
- CRITERIA_ADDITIONAL_CONDITION_THE_TILLERS_REPUTATION = 75,
- CRITERIA_ADDITIONAL_CONDITION_PET_BATTLE_ACHIEVEMENT_POINTS = 76, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_77 = 77, // NYI
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_FAMILY = 78, // NYI
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_HEALTH_PCT = 79, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GUILD_GROUP_MEMBERS = 80, // NYI
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_ENTRY = 81, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SCENARIO_STEP_INDEX = 82,
- CRITERIA_ADDITIONAL_CONDITION_CHALLENGE_MODE_MEDAL = 83, // NYI
- CRITERIA_ADDITIONAL_CONDITION_IS_ON_QUEST = 84,
- CRITERIA_ADDITIONAL_CONDITION_EXALTED_WITH_FACTION = 85, // NYI
- CRITERIA_ADDITIONAL_CONDITION_HAS_ACHIEVEMENT = 86,
- CRITERIA_ADDITIONAL_CONDITION_HAS_ACHIEVEMENT_ON_CHARACTER = 87, // NYI
- CRITERIA_ADDITIONAL_CONDITION_CLOUD_SERPENT_REPUTATION = 88,
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_BREED_QUALITY_ID = 89, // NYI
- CRITERIA_ADDITIONAL_CONDITION_PET_BATTLE_IS_PVP = 90, // NYI
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES = 91,
- CRITERIA_ADDITIONAL_CONDITION_ACTIVE_EXPANSION = 92,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_93 = 93, // NYI
- CRITERIA_ADDITIONAL_CONDITION_FRIENDSHIP_REP_REACTION = 94, // NYI
- CRITERIA_ADDITIONAL_CONDITION_FACTION_STANDING = 95,
- CRITERIA_ADDITIONAL_CONDITION_ITEM_CLASS_AND_SUBCLASS = 96, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_SEX = 97,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_NATIVE_SEX = 98,
- CRITERIA_ADDITIONAL_CONDITION_SKILL = 99,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_100 = 100, // NYI
- CRITERIA_ADDITIONAL_CONDITION_NORMAL_PHASE_SHIFT = 101,
- CRITERIA_ADDITIONAL_CONDITION_IN_PHASE = 102,
- CRITERIA_ADDITIONAL_CONDITION_NOT_IN_PHASE = 103,
- CRITERIA_ADDITIONAL_CONDITION_HAS_SPELL = 104,
- CRITERIA_ADDITIONAL_CONDITION_ITEM_COUNT = 105,
- CRITERIA_ADDITIONAL_CONDITION_ACCOUNT_EXPANSION = 106,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA_LABEL = 107, // NYI, SpellLabel
- //CRITERIA_ADDITIONAL_CONDITION_UNK_108 = 108, // NYI
- CRITERIA_ADDITIONAL_CONDITION_TIME_IN_RANGE = 109, // NYI, packed time between asset and secondaryAsset
- CRITERIA_ADDITIONAL_CONDITION_REWARDED_QUEST = 110,
- CRITERIA_ADDITIONAL_CONDITION_COMPLETED_QUEST = 111,
- CRITERIA_ADDITIONAL_CONDITION_COMPLETED_QUEST_OBJECTIVE = 112, // QuestObjectiveID
- CRITERIA_ADDITIONAL_CONDITION_EXPLORED_AREA = 113,
- CRITERIA_ADDITIONAL_CONDITION_ITEM_COUNT_INCLUDING_BANK = 114,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_115 = 115, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_PVP_FACTION_INDEX = 116,
- CRITERIA_ADDITIONAL_CONDITION_LFG_VALUE_EQUAL = 117,
- CRITERIA_ADDITIONAL_CONDITION_LFG_VALUE_GREATER = 118,
- CRITERIA_ADDITIONAL_CONDITION_CURRENCY_AMOUNT = 119,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_120 = 120, // NYI
- CRITERIA_ADDITIONAL_CONDITION_CURRENCY_TRACKED_AMOUNT = 121,
- CRITERIA_ADDITIONAL_CONDITION_MAP_INSTANCE_TYPE = 122,
- CRITERIA_ADDITIONAL_CONDITION_MENTOR = 123,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_124 = 124, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_125 = 125, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_LEVEL_ABOVE = 126, // asset: garrLevel, secondaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ABOVE_LEVEL = 127, // asset: count, secondaryAsset: followerLevel, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ABOVE_QUALITY = 128, // asset: count, secondaryAsset: followerQuality, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_LEVEL_WITH_ABILITY = 129, // asset: followerLevel, secondaryAsset: ability, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_LEVEL_WITH_TRAIT = 130, // asset: followerLevel, secondaryAsset: ability, tertiaryAsset: garrType (same as above but ability must have GARRISON_ABILITY_FLAG_TRAIT)
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_ABILITY_IN_BUILDING = 131, // asset: ability, secondaryAsset: buildingType, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_TRAIT_IN_BUILDING = 132, // asset: ability, secondaryAsset: buildingType, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_LEVEL_IN_BUILDING = 133, // asset: followerLevel, secondaryAsset: buildingType, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_ABOVE_LEVEL = 134, // asset: buildingType, secondaryAsset: buildingLevel, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_BLUEPRINT = 135, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_136 = 136, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_137 = 137, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_138 = 138, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_139 = 139, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_INACTIVE = 140,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_141 = 141, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_EQUAL_LEVEL = 142, // asset: buildingType, secondaryAsset: buildingLevel, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_ABILITY= 143, // asset: ability, secondaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_WITH_TRAIT = 144, // asset: ability, secondaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_QUALITY_WOD = 145, // asset: followerQuality
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_EQUAL_LEVEL = 146, // asset: followerLevel, secondaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_RARE_MISSION = 147, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_148 = 148, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_LEVEL = 149, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_150 = 150, // NYI
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES_IN_TEAM = 151, // asset: count, secondaryAsset: battlePetSpeciesId
- CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_FAMILY_IN_TEAM = 152, // asset: count, secondaryAsset: battlePetFamily
- //CRITERIA_ADDITIONAL_CONDITION_UNK_153 = 153, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_154 = 154, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_155 = 155, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_156 = 156, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ID = 157, // follower with id, in any garrison
- CRITERIA_ADDITIONAL_CONDITION_QUEST_OBJECTIVE_PROGRESS_EQUAL= 158, // NYI asset: questObjectiveId, secondaryAsset: progress
- CRITERIA_ADDITIONAL_CONDITION_QUEST_OBJECTIVE_PROGRESS_ABOVE= 159, // NYI asset: questObjectiveId, secondaryAsset: progress
- //CRITERIA_ADDITIONAL_CONDITION_UNK_160 = 160, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_161 = 161, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_162 = 162, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_163 = 163, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_164 = 164, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_165 = 165, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_166 = 166, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_MISSION_TYPE = 167, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ABOVE_ITEM_LEVEL = 168, // asset: followerItemLevel
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ABOVE_ITEM_LEVEL = 169, // asset: count, secondaryAsset: followerItemLevel, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_LEVEL_EQUAL = 170, // asset: count
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_GROUP_SIZE = 171, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_172 = 172, // NYI something to do with currency but only used on criterias that require the same currency
- CRITERIA_ADDITIONAL_CONDITION_TARGETING_CORPSE = 173,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_174 = 174, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_LEVEL_EQUAL= 175, // asset: count, secondaryAsset: followerLevel, tertiaryAsset: garrType
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ID_IN_BUILDING = 176, // asset: followerId, secondaryAsset: buildingType
- //CRITERIA_ADDITIONAL_CONDITION_UNK_177 = 177, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_178 = 178, // NYI
- CRITERIA_ADDITIONAL_CONDITION_WORLD_PVP_AREA = 179, // NYI
- CRITERIA_ADDITIONAL_CONDITION_NON_OWN_GARRISON = 180, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_181 = 181, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_182 = 183, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_183 = 183, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWERS_ITEM_LEVEL_ABOVE = 184,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_185 = 185, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_186 = 186, // NYI
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_TYPE = 187, // NYI
- CRITERIA_ADDITIONAL_CONDITION_USED_LEVEL_BOOST_LESS_THAN_HOURS_AGO = 188, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_189 = 189, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_190 = 190, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_191 = 191, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_192 = 192, // NYI
- CRITERIA_ADDITIONAL_CONDITION_HONOR_LEVEL = 193,
- CRITERIA_ADDITIONAL_CONDITION_PRESTIGE_LEVEL = 194,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_195 = 195, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_196 = 196, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_197 = 197, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_198 = 198, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_198 = 199, // NYI
- CRITERIA_ADDITIONAL_CONDITION_ITEM_MODIFIED_APPEARANCE = 200,
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_SELECTED_TALENT = 201, // NYI asset: garrTalentId (talent selected, research timer doesn't matter)
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_RESEARCHED_TALENT = 202, // NYI asset: garrTalentId (talent selected, research must be finished)
- CRITERIA_ADDITIONAL_CONDITION_HAS_CHARACTER_RESTRICTIONS = 203,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_204 = 204, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_205 = 205, // NYI
- CRITERIA_ADDITIONAL_CONDITION_QUEST_INFO_ID = 206,
- CRITERIA_ADDITIONAL_CONDITION_GARRISON_RESEARCHING_TALENT = 207, // NYI asset: garrTalentId (talent selected, research must be in progress)
- CRITERIA_ADDITIONAL_CONDITION_ARTIFACT_APPEARANCE_SET_USED = 208,
- CRITERIA_ADDITIONAL_CONDITION_CURRENCY_AMOUNT_EQUAL = 209,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_210 = 210, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SCENARIO_TYPE = 211,
- CRITERIA_ADDITIONAL_CONDITION_ACCOUNT_EXPANSION_EQUAL = 212,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_213 = 213, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_214 = 214, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_215 = 215, // NYI
- CRITERIA_ADDITIONAL_CONDITION_CHALLENGE_MODE_MEDAL_2 = 216, // NYI keystone master, asset = 3
- //CRITERIA_ADDITIONAL_CONDITION_UNK_217 = 217, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_218 = 218, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_219 = 219, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_220 = 220, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_221 = 221, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_222 = 222, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_223 = 223, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_224 = 224, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_225 = 225, // NYI
- CRITERIA_ADDITIONAL_CONDITION_USED_LEVEL_BOOST = 226, // NYI
- CRITERIA_ADDITIONAL_CONDITION_USED_RACE_CHANGE = 227, // NYI
- CRITERIA_ADDITIONAL_CONDITION_USED_FACTION_CHANGE = 228, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_229 = 229, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_230 = 230, // NYI
- CRITERIA_ADDITIONAL_CONDITION_ACHIEVEMENT_GLOBALLY_INCOMPLETED = 231, // hall of fame stuff, asset: unk, secondaryAsset: achievementId
- CRITERIA_ADDITIONAL_CONDITION_MAIN_HAND_VISIBLE_SUBCLASS = 232,
- CRITERIA_ADDITIONAL_CONDITION_OFF_HAND_VISIBLE_SUBCLASS = 233,
- CRITERIA_ADDITIONAL_CONDITION_PVP_TIER = 234, // NYI asset: pvpTierId
- CRITERIA_ADDITIONAL_CONDITION_AZERITE_ITEM_LEVEL = 235,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_236 = 236, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_237 = 237, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_238 = 238, // NYI
- CRITERIA_ADDITIONAL_CONDITION_PVP_TIER_GREATER = 239, // NYI asset: pvpTierEnum, secondaryAsset: pvpBracket
- //CRITERIA_ADDITIONAL_CONDITION_UNK_240 = 240, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_241 = 241, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_242 = 242, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_243 = 243, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_244 = 244, // NYI
- CRITERIA_ADDITIONAL_CONDITION_IN_WAR_MODE = 245,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_246 = 246, // NYI
- CRITERIA_ADDITIONAL_CONDITION_KEYSTONE_LEVEL = 247, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_248 = 248, // NYI
- CRITERIA_ADDITIONAL_CONDITION_KEYSTONE_DUNGEON = 249, // NYI asset: mapChallengeModeId
- //CRITERIA_ADDITIONAL_CONDITION_UNK_250 = 250, // NYI
- CRITERIA_ADDITIONAL_CONDITION_PVP_SEASON = 251, // NYI asset: that unknown column in PvpSeason.db2
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_DISPLAY_RACE = 252,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_DISPLAY_RACE = 253,
- CRITERIA_ADDITIONAL_CONDITION_FRIENDSHIP_REP_REACTION_EXACT = 254, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_AURA_COUNT_EQUAL = 255,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_AURA_COUNT_EQUAL = 256,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_AURA_COUNT_GREATER = 257,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_AURA_COUNT_GREATER = 258,
- CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_LOWER = 259,
- CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_EQUAL = 260,
- CRITERIA_ADDITIONAL_CONDITION_UNLOCKED_AZERITE_ESSENCE_RANK_GREATER = 261,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA_EFFECT_INDEX = 262, // asset: spellId, secondaryAsset: index
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_SPECIALIZATION_ROLE = 263,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_120 = 264,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_265 = 265,
- CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_LOWER = 266,
- CRITERIA_ADDITIONAL_CONDITION_SELECTED_AZERITE_ESSENCE_RANK_GREATER = 267,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_IN_RANGE_CT = 268,
- CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_IN_RANGE_CT = 269,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_270 = 270,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_271 = 271,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL_GREATER_CT = 272, // compare levels using content tuning
- CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL_GREATER_CT = 273, // compare levels using content tuning
- //CRITERIA_ADDITIONAL_CONDITION_UNK_274 = 274,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_275 = 275,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_276 = 276,
- CRITERIA_ADDITIONAL_CONDITION_RAF_RECRUIT_IN_PARTY = 277, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_278 = 278,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_279 = 279,
- CRITERIA_ADDITIONAL_CONDITION_MAP_OR_COSMETIC_MAP = 280,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_281 = 281,
- CRITERIA_ADDITIONAL_CONDITION_HAS_ENTITLEMENT = 282, // NYI
- CRITERIA_ADDITIONAL_CONDITION_HAS_QUEST_SESSION = 283, // NYI
- //CRITERIA_ADDITIONAL_CONDITION_UNK_284 = 284,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_285 = 285,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_286 = 286,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_287 = 287,
- CRITERIA_ADDITIONAL_CONDITION_COVENANT = 288,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_289 = 289, // related to pvp ranking
- CRITERIA_ADDITIONAL_CONDITION_PERMANENT_ANIMA_DIVERSION_TALENT = 290, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SOULBIND = 291,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_292 = 292,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE_IN_GROUP = 293,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_294 = 294,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_295 = 295,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_296 = 296,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_297 = 297,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_298 = 298,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_299 = 299,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_SPECIFIC_CHROMIE_TIME = 300,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_IN_ANY_CHROMIE_TIME = 301,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_302 = 302,
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_RUNEFORGE_LEGENDARY_KNOWN = 303,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_304 = 304,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_305 = 305,
- //CRITERIA_ADDITIONAL_CONDITION_UNK_306 = 306,
- CRITERIA_ADDITIONAL_CONDITION_SOULBIND_CONDUIT_RANK = 307, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SHAPESHIFT_FORM_CUSTOMIZATION_DISPLAY = 308,
- CRITERIA_ADDITIONAL_CONDITION_SOULBIND_MIN_CONDUITS_AT_RANK = 309, // NYI
- CRITERIA_ADDITIONAL_CONDITION_IS_RESTRICTED_ACCOUNT = 310, // NYI
- CRITERIA_ADDITIONAL_CONDITION_SOURCE_FLYING = 311,
-};
-
enum class CriteriaFailEvent : uint8
{
None = 0,
@@ -1287,6 +974,333 @@ enum MapDifficultyFlags : uint8
MAP_DIFFICULTY_FLAG_CANNOT_EXTEND = 0x10
};
+enum class ModifierTreeType : int32
+{
+ None = 0, // No modifier
+ PlayerInebriationLevelEqualOrGreaterThan = 1, // Player inebriation level is {#Drunkenness} or more
+ PlayerMeetsCondition = 2, // Player meets condition "{PlayerCondition}"
+ MinimumItemLevel = 3, // Minimum item level is {#Item Level}
+ TargetCreatureId = 4, // Target is NPC "{Creature}"
+ TargetIsPlayer = 5, // Target is player
+ TargetIsDead = 6, // Target is dead
+ TargetIsOppositeFaction = 7, // Target is opposite faction
+ PlayerHasAura = 8, // Player has aura "{Spell}"
+ PlayerHasAuraEffect = 9, // Player has aura effect "{SpellAuraNames.EnumID}"
+ TargetHasAura = 10, // Target has aura "{Spell}"
+ TargetHasAuraEffect = 11, // Target has aura effect "{SpellAuraNames.EnumID}"
+ TargetHasAuraState = 12, // Target has aura state "{$Aura State}"
+ PlayerHasAuraState = 13, // Player has aura state "{$Aura State}"
+ ItemQualityIsAtLeast = 14, // Item quality is at least {$Item Quality}
+ ItemQualityIsExactly = 15, // Item quality is exactly {$Item Quality}
+ PlayerIsAlive = 16, // Player is alive
+ PlayerIsInArea = 17, // Player is in area "{AreaTable}"
+ TargetIsInArea = 18, // Target is in area "{AreaTable}"
+ ItemId = 19, // Item is "{Item}"
+ LegacyDungeonDifficulty = 20, // Legacy dungeon difficulty is "{$Dungeon Difficulty}"
+ PlayerToTargetLevelDeltaGreaterThan = 21, // Exceeds the target's level by {#Level Delta} levels
+ TargetToPlayerLevelDeltaGreaterThan = 22, // Target exceeds your level by {#Level Delta} levels
+ PlayerLevelEqualTargetLevel = 23, // You and the target are equal level
+ PlayerInArenaWithTeamSize = 24, // Player is in an arena with team size {#Team Size}
+ PlayerRace = 25, // Player race is "{ChrRaces}"
+ PlayerClass = 26, // Player class is "{ChrClasses}"
+ TargetRace = 27, // Target race is "{ChrRaces}"
+ TargetClass = 28, // Target class is "{ChrClasses}"
+ LessThanTappers = 29, // Less than {#Tappers} tappers
+ CreatureType = 30, // Creature is type "{CreatureType}"
+ CreatureFamily = 31, // Creature is family "{CreatureFamily}"
+ PlayerMap = 32, // Player is on map "{Map}"
+ ClientVersionEqualOrLessThan = 33, // Milestone is at or before "{WowStaticSchemas}"
+ BattlePetTeamLevel = 34, // All three winning battle pets are at or above level {#Battle Pet Level}
+ PlayerIsNotInParty = 35, // Player is not in a party
+ PlayerIsInParty = 36, // Player is in a party
+ HasPersonalRatingEqualOrGreaterThan = 37, // Has a Personal Rating of at least {#Personal Rating}
+ HasTitle = 38, // Has title "{CharTitles.Mask_ID}"
+ PlayerLevelEqual = 39, // Player is exactly level {#Level}
+ TargetLevelEqual = 40, // Target is exactly level {#Level}
+ PlayerIsInZone = 41, // Player is in top-level area "{AreaTable}"
+ TargetIsInZone = 42, // Target is in top-level area "{AreaTable}"
+ PlayerHealthBelowPercent = 43, // Player health below {#Percent}%
+ PlayerHealthAbovePercent = 44, // Player health above {#Percent}%
+ PlayerHealthEqualsPercent = 45, // Player health equals {#Percent}%
+ TargetHealthBelowPercent = 46, // Target health below {#Percent}%
+ TargetHealthAbovePercent = 47, // Target health above {#Percent}%
+ TargetHealthEqualsPercent = 48, // Target health equals {#Percent}%
+ PlayerHealthBelowValue = 49, // Player health below {#Hit Points} HP
+ PlayerHealthAboveValue = 50, // Player health above {#Hit Points} HP
+ PlayerHealthEqualsValue = 51, // Player health equals {#Hit Points} HP
+ TargetHealthBelowValue = 52, // Target health below {#Hit Points} HP
+ TargetHealthAboveValue = 53, // Target health above {#Hit Points} HP
+ TargetHealthEqualsValue = 54, // Target health equals {#Hit Points} HP
+ TargetIsPlayerAndMeetsCondition = 55, // Target is a player with condition "{PlayerCondition}"
+ PlayerHasMoreThanAchievementPoints = 56, // Player has over {#Achievement Pts} achievement points
+ PlayerInLfgDungeon = 57, // Player is in a LFG dungeon
+ PlayerInRandomLfgDungeon = 58, // Player is in a random LFG dungeon
+ PlayerInFirstRandomLfgDungeon = 59, // Player is in a first random LFG dungeon
+ PlayerInRankedArenaMatch = 60, // Player is in a ranked arena match
+ PlayerInGuildParty = 61, /*NYI*/ // Player is in a guild party
+ PlayerGuildReputationEqualOrGreaterThan = 62, // Player has guild reputation of {#Guild Reputation} or more
+ PlayerInRatedBattleground = 63, // Player is in rated battleground
+ PlayerBattlegroundRatingEqualOrGreaterThan = 64, // Player has a battleground rating of {#Battleground Rating} or more
+ ResearchProjectRarity = 65, /*NYI*/ // Research project rarity is "{$Project Rarity}"
+ ResearchProjectBranch = 66, /*NYI*/ // Research project is in branch "{ResearchBranch}"
+ WorldStateExpression = 67, // World state expression "{WorldStateExpression}" is true
+ DungeonDifficulty = 68, // Dungeon difficulty is "{Difficulty}"
+ PlayerLevelEqualOrGreaterThan = 69, // Player level is {#Level} or more
+ TargetLevelEqualOrGreaterThan = 70, // Target level is {#Level} or more
+ PlayerLevelEqualOrLessThan = 71, // Player level is {#Level} or less
+ TargetLevelEqualOrLessThan = 72, // Target level is {#Level} or less
+ ModifierTree = 73, // Modifier tree "{ModifierTree}" is also true
+ PlayerScenario = 74, // Player is on scenario "{Scenario}"
+ TillersReputationGreaterThan = 75, // Reputation with Tillers is above {#Reputation}
+ BattlePetAchievementPointsEqualOrGreaterThan = 76, // Battle pet achievement points are at least {#Achievement Pts}
+ UniqueBattlePetsEqualOrGreaterThan = 77, // (Account) At least {#Pets Known} unique pets known
+ BattlePetType = 78, // Battlepet is of type "{$Battle Pet Types}"
+ BattlePetHealthPercentLessThan = 79, /*NYI*/ // (Account) Battlepet's health is below {#Health Percent} percent
+ GuildGroupMemberCountEqualOrGreaterThan = 80, // Be in a group with at least {#Members} guild members
+ BattlePetOpponentCreatureId = 81, /*NYI*/ // Battle pet opponent is "{Creature}"
+ PlayerScenarioStep = 82, // Player is on scenario step number {#Step Number}
+ ChallengeModeMedal = 83, // Challenge mode medal earned is "{#Challenge Mode Medal(OBSOLETE)}" (OBSOLETE)
+ PlayerOnQuest = 84, // Player is currently on the quest "{QuestV2}"
+ ExaltedWithFaction = 85, // Reach exalted with "{Faction}"
+ EarnedAchievementOnAccount = 86, // Earned achievement "{Achievement}" on this account
+ EarnedAchievementOnPlayer = 87, // Earned achievement "{Achievement}" on this player
+ OrderOfTheCloudSerpentReputationGreaterThan = 88, // Reputation with Order of the Cloud Serpent is above {#Reputation}
+ BattlePetQuality = 89, /*NYI*/ // Battle pet is of quality "{BattlePetBreedQuality}"
+ BattlePetFightWasPVP = 90, /*NYI*/ // Battle pet fight was PVP
+ BattlePetSpecies = 91, // Battle pet is species type "{BattlePetSpecies}"
+ ServerExpansionEqualOrGreaterThan = 92, // Server expansion level is "{$Expansion Level}" or higher
+ PlayerHasBattlePetJournalLock = 93, // Player has battle pet journal lock
+ FriendshipRepReactionIsMet = 94, // Friendship rep reaction "{FriendshipRepReaction}" is met
+ ReputationWithFactionIsEqualOrGreaterThan = 95, // Reputation with "{Faction}" is {#Reputation} or more
+ ItemClassAndSubclass = 96, // Item is class "{ItemClass.ClassID}", subclass "{^ItemSubclass.SubclassID:ItemSubclass.ClassID = ?}"
+ PlayerGender = 97, // Player's gender is "{$Gender}"
+ PlayerNativeGender = 98, // Player's native gender is "{$Gender}"
+ PlayerSkillEqualOrGreaterThan = 99, // Player skill "{SkillLine}" is level {#Skill Level} or higher
+ PlayerLanguageSkillEqualOrGreaterThan = 100, // Player language "{Languages}" is level {#Language Level} or higher
+ PlayerIsInNormalPhase = 101, // Player is in normal phase
+ PlayerIsInPhase = 102, // Player is in phase "{Phase}"
+ PlayerIsInPhaseGroup = 103, // Player is in phase group "{PhaseGroup}"
+ PlayerKnowsSpell = 104, // Player knows spell "{Spell}"
+ PlayerHasItemQuantity = 105, // Player is carrying item "{Item}", quantity {#Quantity}
+ PlayerExpansionLevelEqualOrGreaterThan = 106, // Player expansion level is "{$Expansion Level}" or higher
+ PlayerHasAuraWithLabel = 107, // Player has aura with label {Label}
+ PlayersRealmWorldState = 108, // Player's realm state "{WorldState}" equals {#Value}
+ TimeBetween = 109, // Time is between "{/Begin Date}" and "{/End Date}"
+ PlayerHasCompletedQuest = 110, // Player has previously completed quest "{QuestV2}"
+ PlayerIsReadyToTurnInQuest = 111, // Player is ready to turn in quest "{QuestV2}"
+ PlayerHasCompletedQuestObjective = 112, // Player has completed Quest Objective "{QuestObjective}"
+ PlayerHasExploredArea = 113, // Player has explored area "{AreaTable}"
+ PlayerHasItemQuantityIncludingBank = 114, // Player or bank has item "{Item}", quantity {#Quantity}
+ Weather = 115, // Weather is "{Weather}"
+ PlayerFaction = 116, // Player faction is {$Player Faction}
+ LfgStatusEqual = 117, // Looking-for-group status "{$LFG Status}" equals {#Value}
+ LFgStatusEqualOrGreaterThan = 118, // Looking-for-group status "{$LFG Status}" is {#Value} or more
+ PlayerHasCurrencyEqualOrGreaterThan = 119, // Player has currency "{CurrencyTypes}" in amount {#Amount} or more
+ TargetThreatListSizeLessThan = 120, // Player Killed creature with less than "{#Targets}" threat list targets
+ PlayerHasTrackedCurrencyEqualOrGreaterThan = 121, // Player has currency "{CurrencyTypes}" tracked (per season) in amount {#Amount} or more
+ PlayerMapInstanceType = 122, // Player is on a map of type "{@INSTANCE_TYPE}"
+ PlayerInTimeWalkerInstance = 123, // Player was in a Time Walker instance
+ PvpSeasonIsActive = 124, // PVP season is active
+ PvpSeason = 125, // Current PVP season is {#Season}
+ GarrisonTierEqualOrGreaterThan = 126, // Garrison is tier {#Tier} or higher for garrison type "{GarrType}"
+ GarrisonFollowersWithLevelEqualOrGreaterThan = 127, // At least {#Followers} followers of at least level {#Level} for follower type "{GarrFollowerType}"
+ GarrisonFollowersWithQualityEqualOrGreaterThan = 128, // At least {#Followers} followers at least quality "{@GARR_FOLLOWER_QUALITY}" for follower type "{GarrFollowerType}"
+ GarrisonFollowerWithAbilityAtLevelEqualOrGreaterThan = 129, // Follower of at least level {#Level} has ability {GarrAbility} for follower type "{GarrFollowerType}"
+ GarrisonFollowerWithTraitAtLevelEqualOrGreaterThan = 130, // Follower of at least level {#Level} has trait {GarrAbility} for follower type "{GarrFollowerType}"
+ GarrisonFollowerWithAbilityAssignedToBuilding = 131, // Follower with ability "{GarrAbility}" is assigned to building type "{@GARRISON_BUILDING_TYPE}" for garrison type "{GarrType}"
+ GarrisonFollowerWithTraitAssignedToBuilding = 132, // Follower with trait "{GarrAbility}" is assigned to building type "{@GARRISON_BUILDING_TYPE}" for garrison type "{GarrType}"
+ GarrisonFollowerWithLevelAssignedToBuilding = 133, // Follower at least level {#Level} is assigned to building type "{@GARRISON_BUILDING_TYPE}" for garrison type "GarrType}"
+ GarrisonBuildingWithLevelEqualOrGreaterThan = 134, // Building "{@GARRISON_BUILDING_TYPE}" is at least level {#Level} for garrison type "{GarrType}"
+ HasBlueprintForGarrisonBuilding = 135, // Has blueprint for garrison building "{GarrBuilding}" of type "{GarrType}"
+ HasGarrisonBuildingSpecialization = 136, // Has garrison building specialization "{GarrSpecialization}"
+ AllGarrisonPlotsAreFull = 137, // All garrison type "{GarrType}" plots are full
+ PlayerIsInOwnGarrison = 138, // Player is in their own garrison
+ GarrisonShipmentOfTypeIsPending = 139, /*NYI*/ // Shipment of type "{CharShipmentContainer}" is pending
+ GarrisonBuildingIsUnderConstruction = 140, // Garrison building "{GarrBuilding}" is under construction
+ GarrisonMissionHasBeenCompleted = 141, /*NYI*/ // Garrison mission "{GarrMission}" has been completed
+ GarrisonBuildingLevelEqual = 142, // Building {@GARRISON_BUILDING_TYPE} is exactly level {#Level} for garrison type "{GarrType}"
+ GarrisonFollowerHasAbility = 143, // This follower has ability "{GarrAbility}" for garrison type "{GarrType}"
+ GarrisonFollowerHasTrait = 144, // This follower has trait "{GarrAbility}" for garrison type "{GarrType}"
+ GarrisonFollowerQualityEqual = 145, // This Garrison Follower is {@GARR_FOLLOWER_QUALITY} quality
+ GarrisonFollowerLevelEqual = 146, // This Garrison Follower is level {#Level}
+ GarrisonMissionIsRare = 147, /*NYI*/ // This Garrison Mission is Rare
+ GarrisonMissionIsElite = 148, /*NYI*/ // This Garrison Mission is Elite
+ CurrentGarrisonBuildingLevelEqual = 149, // This Garrison Building is level {#Level} - building type passed as argument
+ GarrisonPlotInstanceHasBuildingThatIsReadyToActivate = 150, // Garrison plot instance "{GarrPlotInstance}" has building that is ready to activate
+ BattlePetTeamWithSpeciesEqualOrGreaterThan = 151, // Battlepet: with at least {#Amount} "{BattlePetSpecies}"
+ BattlePetTeamWithTypeEqualOrGreaterThan = 152, // Battlepet: with at least {#Amount} pets of type "{$Battle Pet Types}"
+ PetBattleLastAbility = 153, /*NYI*/ // Battlepet: last ability was "{BattlePetAbility}"
+ PetBattleLastAbilityType = 154, /*NYI*/ // Battlepet: last ability was of type "{$Battle Pet Types}"
+ BattlePetTeamWithAliveEqualOrGreaterThan = 155, // Battlepet: with at least {#Alive} alive
+ HasGarrisonBuildingActiveSpecialization = 156, // Has Garrison building active specialization "{GarrSpecialization}"
+ HasGarrisonFollower = 157, // Has Garrison follower "{GarrFollower}"
+ PlayerQuestObjectiveProgressEqual = 158, // Player's progress on Quest Objective "{QuestObjective}" is equal to {#Value}
+ PlayerQuestObjectiveProgressEqualOrGreaterThan = 159, // Player's progress on Quest Objective "{QuestObjective}" is at least {#Value}
+ IsPTRRealm = 160, // This is a PTR Realm
+ IsBetaRealm = 161, // This is a Beta Realm
+ IsQARealm = 162, // This is a QA Realm
+ GarrisonShipmentContainerIsFull = 163, /*NYI*/ // Shipment Container "{CharShipmentContainer}" is full
+ PlayerCountIsValidToStartGarrisonInvasion = 164, // Player count is valid to start garrison invasion
+ InstancePlayerCountEqualOrLessThan = 165, // Instance has at most {#Players} players
+ AllGarrisonPlotsFilledWithBuildingsWithLevelEqualOrGreater = 166, // All plots are full and at least level {#Level} for garrison type "{GarrType}"
+ GarrisonMissionType = 167, /*NYI*/ // This mission is type "{GarrMissionType}"
+ GarrisonFollowerItemLevelEqualOrGreaterThan = 168, // This follower is at least item level {#Level}
+ GarrisonFollowerCountWithItemLevelEqualOrGreaterThan = 169, // At least {#Followers} followers are at least item level {#Level} for follower type "{GarrFollowerType}"
+ GarrisonTierEqual = 170, // Garrison is exactly tier {#Tier} for garrison type "{GarrType}"
+ InstancePlayerCountEqual = 171, // Instance has exactly {#Players} players
+ CurrencyId = 172, // The currency is type "{CurrencyTypes}"
+ SelectionIsPlayerCorpse = 173, // Target is player corpse
+ PlayerCanAcceptQuest = 174, // Player is currently eligible for quest "{QuestV2}"
+ GarrisonFollowerCountWithLevelEqualOrGreaterThan = 175, // At least {#Followers} followers exactly level {#Level} for follower type "{GarrFollowerType}"
+ GarrisonFollowerIsInBuilding = 176, // Garrison follower "{GarrFollower}" is in building "{GarrBuilding}"
+ GarrisonMissionCountLessThan = 177, /*NYI*/ // Player has less than {#Available} available and {#In-Progress} in-progress missions of garrison type "{GarrType}"
+ GarrisonPlotInstanceCountEqualOrGreaterThan = 178, // Player has at least {#Amount} instances of plot "{GarrPlot}" available
+ CurrencySource = 179, /*NYI*/ // Currency source is {$Currency Source}
+ PlayerIsInNotOwnGarrison = 180, // Player is in another garrison (not their own)
+ HasActiveGarrisonFollower = 181, // Has active Garrison follower "{GarrFollower}"
+ PlayerDailyRandomValueMod_X_Equals = 182, /*NYI*/ // Player daily random value mod {#Mod Value} equals {#Equals Value}
+ PlayerHasMount = 183, // Player has Mount "{Mount}"
+ GarrisonFollowerCountWithInactiveWithItemLevelEqualOrGreaterThan = 184, // At least {#Followers} followers (including inactive) are at least item level {#Level} for follower type "{GarrFollowerType}"
+ GarrisonFollowerIsOnAMission = 185, // Garrison follower "{GarrFollower}" is on a mission
+ GarrisonMissionCountInSetLessThan = 186, /*NYI*/ // Player has less than {#Missions} available and in-progress missions of set "{GarrMissionSet}" in garrison type "{GarrType}"
+ GarrisonFollowerType = 187, // This Garrison Follower is of type "{GarrFollowerType}"
+ PlayerUsedBoostLessThanHoursAgoRealTime = 188, /*NYI*/ // Player has boosted and boost occurred < {#Hours} hours ago (real time)
+ PlayerUsedBoostLessThanHoursAgoGameTime = 189, /*NYI*/ // Player has boosted and boost occurred < {#Hours} hours ago (in-game time)
+ PlayerIsMercenary = 190, // Player is currently Mercenary
+ PlayerEffectiveRace = 191, /*NYI*/ // Player effective race is "{ChrRaces}"
+ TargetEffectiveRace = 192, /*NYI*/ // Target effective race is "{ChrRaces}"
+ HonorLevelEqualOrGreaterThan = 193, // Honor level >= {#Level}
+ PrestigeLevelEqualOrGreaterThan = 194, // Prestige level >= {#Level}
+ GarrisonMissionIsReadyToCollect = 195, /*NYI*/ // Garrison mission "{GarrMission}" is ready to collect
+ PlayerIsInstanceOwner = 196, /*NYI*/ // Player is the instance owner (requires 'Lock Instance Owner' LFGDungeon flag)
+ PlayerHasHeirloom = 197, // Player has heirloom "{Item}"
+ TeamPoints = 198, /*NYI*/ // Team has {#Points} Points
+ PlayerHasToy = 199, // Player has toy "{Item}"
+ PlayerHasTransmog = 200, // Player has transmog "{ItemModifiedAppearance}"
+ GarrisonTalentSelected = 201, /*NYI*/ // Garrison has talent "{GarrTalent}" selected
+ GarrisonTalentResearched = 202, /*NYI*/ // Garrison has talent "{GarrTalent}" researched
+ PlayerHasRestriction = 203, // Player has restriction of type "{@CHARACTER_RESTRICTION_TYPE}"
+ PlayerCreatedCharacterLessThanHoursAgoRealTime = 204, /*NYI*/ // Player has created their character < {#Hours} hours ago (real time)
+ PlayerCreatedCharacterLessThanHoursAgoGameTime = 205, // Player has created their character < {#Hours} hours ago (in-game time)
+ QuestHasQuestInfoId = 206, // Quest has Quest Info "{QuestInfo}"
+ GarrisonTalentResearchInProgress = 207, /*NYI*/ // Garrison is researching talent "{GarrTalent}"
+ PlayerEquippedArtifactAppearanceSet = 208, // Player has equipped Artifact Appearance Set "{ArtifactAppearanceSet}"
+ PlayerHasCurrencyEqual = 209, // Player has currency "{CurrencyTypes}" in amount {#Amount} exactly
+ MinimumAverageItemHighWaterMarkForSpec = 210, /*NYI*/ // Minimum average item high water mark is {#Item High Water Mark} for "{$Item History Spec Match}")
+ PlayerScenarioType = 211, // Player in scenario of type "{$Scenario Type}"
+ PlayersAuthExpansionLevelEqualOrGreaterThan = 212, // Player's auth expansion level is "{$Expansion Level}" or higher
+ PlayerLastWeek2v2Rating = 213, /*NYI*/ // Player achieved at least a rating of {#Rating} in 2v2 last week player played
+ PlayerLastWeek3v3Rating = 214, /*NYI*/ // Player achieved at least a rating of {#Rating} in 3v3 last week player played
+ PlayerLastWeekRBGRating = 215, /*NYI*/ // Player achieved at least a rating of {#Rating} in RBG last week player played
+ GroupMemberCountFromConnectedRealmEqualOrGreaterThan = 216, // At least {#Num Players} members of the group are from your connected realms
+ ArtifactTraitUnlockedCountEqualOrGreaterThan = 217, // At least {#Num Traits} traits have been unlocked in artifact "{Item}"
+ ParagonReputationLevelEqualOrGreaterThan = 218, // Paragon level >= "{#Level}"
+ GarrisonShipmentIsReady = 219, /*NYI*/ // Shipment in container type "{CharShipmentContainer}" ready
+ PlayerIsInPvpBrawl = 220, // Player is in PvP Brawl
+ ParagonReputationLevelWithFactionEqualOrGreaterThan = 221, // Paragon level >= "{#Level}" with faction "{Faction}"
+ PlayerHasItemWithBonusListFromTreeAndQuality = 222, // Player has an item with bonus list from tree "{ItemBonusTree}" and of quality "{$Item Quality}"
+ PlayerHasEmptyInventorySlotCountEqualOrGreaterThan = 223, // Player has at least "{#Number of empty slots}" empty inventory slots
+ PlayerHasItemInHistoryOfProgressiveEvent = 224, /*NYI*/ // Player has item "{Item}" in the item history of progressive event "{ProgressiveEvent}"
+ PlayerHasArtifactPowerRankCountPurchasedEqualOrGreaterThan = 225, // Player has at least {#Purchased Ranks} ranks of {ArtifactPower} on equipped artifact
+ PlayerHasBoosted = 226, // Player has boosted
+ PlayerHasRaceChanged = 227, // Player has race changed
+ PlayerHasBeenGrantedLevelsFromRaF = 228, // Player has been granted levels from Recruit a Friend
+ IsTournamentRealm = 229, // Is Tournament Realm
+ PlayerCanAccessAlliedRaces = 230, // Player can access allied races
+ GroupMemberCountWithAchievementEqualOrLessThan = 231, // No More Than {#Group Members} With Achievement {Achievement} In Group (true if no group)
+ PlayerMainhandWeaponType = 232, // Player has main hand weapon of type "{$Weapon Type}"
+ PlayerOffhandWeaponType = 233, // Player has off-hand weapon of type "{$Weapon Type}"
+ PlayerPvpTier = 234, // Player is in PvP tier {PvpTier}
+ PlayerAzeriteLevelEqualOrGreaterThan = 235, // Players' Azerite Item is at or above level "{#Azerite Level}"
+ PlayerIsOnQuestInQuestline = 236, // Player is on quest in questline "{QuestLine}"
+ PlayerIsQnQuestLinkedToScheduledWorldStateGroup = 237, // Player is on quest associated with current progressive unlock group "{ScheduledWorldStateGroup}"
+ PlayerIsInRaidGroup = 238, // Player is in raid group
+ PlayerPvpTierInBracketEqualOrGreaterThan = 239, // Player is at or above "{@PVP_TIER_ENUM}" for "{@PVP_BRACKET}"
+ PlayerCanAcceptQuestInQuestline = 240, // Player is eligible for quest in questline "{Questline}"
+ PlayerHasCompletedQuestline = 241, // Player has completed questline "{Questline}"
+ PlayerHasCompletedQuestlineQuestCount = 242, // Player has completed "{#Quests}" quests in questline "{Questline}"
+ PlayerHasCompletedPercentageOfQuestline = 243, // Player has completed "{#Percentage}" % of quests in questline "{Questline}"
+ PlayerHasWarModeEnabled = 244, // Player has WarMode Enabled (regardless of shard state)
+ PlayerIsOnWarModeShard = 245, // Player is on a WarMode Shard
+ PlayerIsAllowedToToggleWarModeInArea = 246, // Player is allowed to toggle WarMode in area
+ MythicPlusKeystoneLevelEqualOrGreaterThan = 247, /*NYI*/ // Mythic Plus Keystone Level Atleast {#Level}
+ MythicPlusCompletedInTime = 248, /*NYI*/ // Mythic Plus Completed In Time
+ MythicPlusMapChallengeMode = 249, /*NYI*/ // Mythic Plus Map Challenge Mode {MapChallengeMode}
+ MythicPlusDisplaySeason = 250, /*NYI*/ // Mythic Plus Display Season {#Season}
+ MythicPlusMilestoneSeason = 251, /*NYI*/ // Mythic Plus Milestone Season {#Season}
+ PlayerVisibleRace = 252, // Player visible race is "{ChrRaces}"
+ TargetVisibleRace = 253, // Target visible race is "{ChrRaces}"
+ FriendshipRepReactionEqual = 254, // Friendship rep reaction is exactly "{FriendshipRepReaction}"
+ PlayerAuraStackCountEqual = 255, // Player has exactly {#Stacks} stacks of aura "{Spell}"
+ TargetAuraStackCountEqual = 256, // Target has exactly {#Stacks} stacks of aura "{Spell}"
+ PlayerAuraStackCountEqualOrGreaterThan = 257, // Player has at least {#Stacks} stacks of aura "{Spell}"
+ TargetAuraStackCountEqualOrGreaterThan = 258, // Target has at least {#Stacks} stacks of aura "{Spell}"
+ PlayerHasAzeriteEssenceRankLessThan = 259, // Player has Azerite Essence {AzeriteEssence} at less than rank {#rank}
+ PlayerHasAzeriteEssenceRankEqual = 260, // Player has Azerite Essence {AzeriteEssence} at rank {#rank}
+ PlayerHasAzeriteEssenceRankGreaterThan = 261, // Player has Azerite Essence {AzeriteEssence} at greater than rank {#rank}
+ PlayerHasAuraWithEffectIndex = 262, // Player has Aura {Spell} with Effect Index {#index} active
+ PlayerLootSpecializationMatchesRole = 263, // Player loot specialization matches role {@LFG_ROLE}
+ PlayerIsAtMaxExpansionLevel = 264, // Player is at max expansion level
+ TransmogSource = 265, // Transmog Source is "{@TRANSMOG_SOURCE}"
+ PlayerHasAzeriteEssenceInSlotAtRankLessThan = 266, // Player has Azerite Essence in slot {@AZERITE_ESSENCE_SLOT} at less than rank {#rank}
+ PlayerHasAzeriteEssenceInSlotAtRankGreaterThan = 267, // Player has Azerite Essence in slot {@AZERITE_ESSENCE_SLOT} at greater than rank {#rank}
+ PlayerLevelWithinContentTuning = 268, // Player has level within Content Tuning {ContentTuning}
+ TargetLevelWithinContentTuning = 269, // Target has level within Content Tuning {ContentTuning}
+ PlayerIsScenarioInitiator = 270, /*NYI*/ // Player is Scenario Initiator
+ PlayerHasCompletedQuestOrIsOnQuest = 271, // Player is currently on or previously completed quest "{QuestV2}"
+ PlayerLevelWithinOrAboveContentTuning = 272, // Player has level within or above Content Tuning {ContentTuning}
+ TargetLevelWithinOrAboveContentTuning = 273, // Target has level within or above Content Tuning {ContentTuning}
+ PlayerLevelWithinOrAboveLevelRange = 274, /*NYI*/ // Player has level within or above Level Range {LevelRange}
+ TargetLevelWithinOrAboveLevelRange = 275, /*NYI*/ // Target has level within or above Level Range {LevelRange}
+ MaxJailersTowerLevelEqualOrGreaterThan = 276, // Max Jailers Tower Level Atleast {#Level}
+ GroupedWithRaFRecruit = 277, // Grouped With Recruit
+ GroupedWithRaFRecruiter = 278, // Grouped with Recruiter
+ PlayerSpecialization = 279, // Specialization is "{ChrSpecialization}"
+ PlayerMapOrCosmeticChildMap = 280, // Player is on map or cosmetic child map "{Map}"
+ PlayerCanAccessShadowlandsPrepurchaseContent = 281, // Player can access Shadowlands (9.0) prepurchase content
+ PlayerHasEntitlement = 282, /*NYI*/ // Player has entitlement "{BattlePayDeliverable}"
+ PlayerIsInPartySyncGroup = 283, /*NYI*/ // Player is in party sync group
+ QuestHasPartySyncRewards = 284, /*NYI*/ // Quest is eligible for party sync rewards
+ HonorGainSource = 285, /*NYI*/ // Player gained honor from source {@SPECIAL_MISC_HONOR_GAIN_SOURCE}
+ JailersTowerActiveFloorIndexEqualOrGreaterThan = 286, /*NYI*/ // Active Floor Index Atleast {#Level}
+ JailersTowerActiveFloorDifficultyEqualOrGreaterThan = 287, /*NYI*/ // Active Floor Difficulty Atleast {#Level}
+ PlayerCovenant = 288, // Player is member of covenant "{Covenant}"
+ HasTimeEventPassed = 289, // Has time event "{TimeEvent}" passed
+ GarrisonHasPermanentTalent = 290, /*NYI*/ // Garrison has permanent talent "{GarrTalent}"
+ HasActiveSoulbind = 291, // Has Active Soulbind "{Soulbind}"
+ HasMemorizedSpell = 292, /*NYI*/ // Has memorized spell "{Spell}"
+ PlayerHasAPACSubscriptionReward_2020 = 293, // Player has APAC Subscription Reward 2020
+ PlayerHasTBCCDEWarpStalker_Mount = 294, // Player has TBCC:DE Warp Stalker Mount
+ PlayerHasTBCCDEDarkPortal_Toy = 295, // Player has TBCC:DE Dark Portal Toy
+ PlayerHasTBCCDEPathOfIllidan_Toy = 296, // Player has TBCC:DE Path of Illidan Toy
+ PlayerHasImpInABallToySubscriptionReward = 297, // Player has Imp in a Ball Toy Subscription Reward
+ PlayerIsInAreaGroup = 298, // Player is in area group "{AreaGroup}"
+ TargetIsInAreaGroup = 299, // Target is in area group "{AreaGroup}"
+ PlayerIsInChromieTime = 300, // Player has selected Chromie Time ID "{UiChromieTimeExpansionInfo}"
+ PlayerIsInAnyChromieTime = 301, // Player has selected ANY Chromie Time ID
+ ItemIsAzeriteArmor = 302, // Item is Azerite Armor
+ PlayerHasRuneforgePower = 303, // Player Has Runeforge Power "{RuneforgeLegendaryAbility}"
+ PlayerInChromieTimeForScaling = 304, // Player is Chromie Time for Scaling
+ IsRaFRecruit = 305, // Is RAF recruit
+ AllPlayersInGroupHaveAchievement = 306, // All Players In Group Have Achievement "{Achievement}"
+ PlayerHasSoulbindConduitRankEqualOrGreaterThan = 307, /*NYI*/ // Player has Conduit "{SoulbindConduit}" at Rank {#Rank} or Higher
+ PlayerSpellShapeshiftFormCreatureDisplayInfoSelection = 308, // Player has chosen {CreatureDisplayInfo} for shapeshift form {SpellShapeshiftForm}
+ PlayerSoulbindConduitCountAtRankEqualOrGreaterThan = 309, /*NYI*/ // Player has at least {#Level} Conduits at Rank {#Rank} or higher.
+ PlayerIsRestrictedAccount = 310, // Player is a Restricted Account
+ PlayerIsFlying = 311, // Player is flying
+ PlayerScenarioIsLastStep = 312, // Player is on the last step of a Scenario
+ PlayerHasWeeklyRewardsAvailable = 313, // Player has weekly rewards available
+ TargetCovenant = 314, // Target is member of covenant "{Covenant}"
+ PlayerHasTBCCollectorsEdition = 315, // Player has TBC Collector's Edition
+ PlayerHasWrathCollectorsEdition = 316, // Player has Wrath Collector's Edition
+ GarrisonTalentResearchedAndAtRankEqualOrGreaterThan = 317, /*NYI*/ // Garrison has talent "{GarrTalent}" researched and active at or above {#Rank}
+ CurrencySpentOnGarrisonTalentResearchEqualOrGreaterThan = 318, /*NYI*/ // Currency {CurrencyTypes} Spent on Garrison Talent Research in Tree {GarrTalentTree} is greater than or equal to {#Quantity}
+ RenownCatchupActive = 319, /*NYI*/ // Renown Catchup Active
+ RapidRenownCatchupActive = 320, /*NYI*/ // Rapid Renown Catchup Active
+ PlayerMythicPlusRatingEqualOrGreaterThan = 321, /*NYI*/ // Player has Mythic+ Rating of at least "{#DungeonScore}"
+ PlayerMythicPlusRunCountInCurrentExpansionEqualOrGreaterThan = 322, /*NYI*/ // Player has completed at least "{#MythicKeystoneRuns}" Mythic+ runs in current expansion
+};
+
enum class ModifierTreeOperator : int8
{
SingleTrue = 2,
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index a955c5904ca..3cd6b003daa 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -2468,6 +2468,29 @@ void Item::InitArtifactPowers(uint8 artifactId, uint8 artifactTier)
}
}
+uint32 Item::GetTotalUnlockedArtifactPowers() const
+{
+ uint32 purchased = GetTotalPurchasedArtifactPowers();
+ uint64 artifactXp = m_itemData->ArtifactXP;
+ uint32 currentArtifactTier = GetModifier(ITEM_MODIFIER_ARTIFACT_TIER);
+ uint32 extraUnlocked = 0;
+ do
+ {
+ uint64 xpCost = 0;
+ if (GtArtifactLevelXPEntry const* cost = sArtifactLevelXPGameTable.GetRow(purchased + extraUnlocked + 1))
+ xpCost = uint64(currentArtifactTier == MAX_ARTIFACT_TIER ? cost->XP2 : cost->XP);
+
+ if (artifactXp < xpCost)
+ break;
+
+ artifactXp -= xpCost;
+ ++extraUnlocked;
+
+ } while (true);
+
+ return purchased + extraUnlocked;
+}
+
uint32 Item::GetTotalPurchasedArtifactPowers() const
{
uint32 purchasedRanks = 0;
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index e620e6e5491..d2b3bb702ae 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -411,6 +411,7 @@ class TC_GAME_API Item : public Object
void SetArtifactPower(uint16 artifactPowerId, uint8 purchasedRank, uint8 currentRankWithBonus);
void InitArtifactPowers(uint8 artifactId, uint8 artifactTier);
+ uint32 GetTotalUnlockedArtifactPowers() const;
uint32 GetTotalPurchasedArtifactPowers() const;
void ApplyArtifactPowerEnchantmentBonuses(EnchantmentSlot slot, uint32 enchantId, bool apply, Player* owner);
void CopyArtifactDataFromParent(Item* parent);
diff --git a/src/server/game/Entities/Player/CollectionMgr.cpp b/src/server/game/Entities/Player/CollectionMgr.cpp
index 689965a33d1..bf1ed68072e 100644
--- a/src/server/game/Entities/Player/CollectionMgr.cpp
+++ b/src/server/game/Entities/Player/CollectionMgr.cpp
@@ -799,7 +799,7 @@ void CollectionMgr::AddItemAppearance(ItemModifiedAppearanceEntry const* itemMod
{
int32 transmogSlot = ItemTransmogrificationSlots[item->InventoryType];
if (transmogSlot >= 0)
- _owner->GetPlayer()->UpdateCriteria(CRITERIA_TYPE_APPEARANCE_UNLOCKED_BY_SLOT, transmogSlot, 1);
+ _owner->GetPlayer()->UpdateCriteria(CRITERIA_TYPE_APPEARANCE_UNLOCKED_BY_SLOT, transmogSlot, itemModifiedAppearance->ID);
}
if (std::vector<TransmogSetEntry const*> const* sets = sDB2Manager.GetTransmogSetsForItemModifiedAppearance(itemModifiedAppearance->ID))
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 89ddc54146c..a99c1af16fc 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -9969,6 +9969,50 @@ uint8 Player::FindEquipSlot(Item const* item, uint32 slot, bool swap) const
return NULL_SLOT;
}
+uint32 Player::GetFreeInventorySlotCount(EnumFlag<ItemSearchLocation> location /*= ItemSearchLocation::Inventory*/) const
+{
+ uint32 freeSlotCount = 0;
+
+ if (location.HasFlag(ItemSearchLocation::Equipment))
+ for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
+ if (!GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ ++freeSlotCount;
+
+ if (location.HasFlag(ItemSearchLocation::Inventory))
+ {
+ uint8 inventoryEnd = INVENTORY_SLOT_ITEM_START + GetInventorySlotCount();
+ for (uint8 i = INVENTORY_SLOT_BAG_START; i < inventoryEnd; ++i)
+ if (!GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ ++freeSlotCount;
+
+ for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i)
+ if (Bag* bag = GetBagByPos(i))
+ for (uint32 j = 0; j < GetBagSize(bag); ++j)
+ if (!GetItemInBag(bag, j))
+ ++freeSlotCount;
+ }
+
+ if (location.HasFlag(ItemSearchLocation::Bank))
+ {
+ for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
+ if (!GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ ++freeSlotCount;
+
+ for (uint8 i = BANK_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i)
+ if (Bag* bag = GetBagByPos(i))
+ for (uint32 j = 0; j < GetBagSize(bag); ++j)
+ if (!GetItemInBag(bag, j))
+ ++freeSlotCount;
+ }
+
+ if (location.HasFlag(ItemSearchLocation::ReagentBank))
+ for (uint8 i = REAGENT_SLOT_START; i < REAGENT_SLOT_END; ++i)
+ if (!GetItemByPos(INVENTORY_SLOT_BAG_0, i))
+ ++freeSlotCount;
+
+ return freeSlotCount;
+}
+
InventoryResult Player::CanUnequipItems(uint32 item, uint32 count) const
{
InventoryResult res = EQUIP_ERR_OK;
@@ -23226,19 +23270,13 @@ bool Player::BuyItemFromVendorSlot(ObjectGuid vendorguid, uint32 vendorslot, uin
uint32 Player::GetMaxPersonalArenaRatingRequirement(uint32 minarenaslot) const
{
// returns the maximal personal arena rating that can be used to purchase items requiring this condition
- // the personal rating of the arena team must match the required limit as well
- // so return max[in arenateams](min(personalrating[teamtype], teamrating[teamtype]))
+ // so return max[in arenateams](personalrating[teamtype])
uint32 max_personal_rating = 0;
for (uint8 i = minarenaslot; i < MAX_ARENA_SLOT; ++i)
{
- if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(GetArenaTeamId(i)))
- {
- uint32 p_rating = GetArenaPersonalRating(i);
- uint32 t_rating = at->GetRating();
- p_rating = p_rating < t_rating ? p_rating : t_rating;
- if (max_personal_rating < p_rating)
- max_personal_rating = p_rating;
- }
+ uint32 p_rating = GetArenaPersonalRating(i);
+ if (max_personal_rating < p_rating)
+ max_personal_rating = p_rating;
}
return max_personal_rating;
}
@@ -26514,6 +26552,11 @@ uint32 Player::GetAchievementPoints() const
return m_achievementMgr->GetAchievementPoints();
}
+std::vector<uint32> Player::GetCompletedAchievementIds() const
+{
+ return m_achievementMgr->GetCompletedAchievementIds();
+}
+
bool Player::HasAchieved(uint32 achievementId) const
{
return m_achievementMgr->HasAchieved(achievementId);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index e9cf9ed7fac..6298598605a 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1260,6 +1260,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void UpdateAverageItemLevelEquipped();
uint8 FindEquipSlot(Item const* item, uint32 slot, bool swap) const;
+ uint32 GetFreeInventorySlotCount(EnumFlag<ItemSearchLocation> location = ItemSearchLocation::Inventory) const;
uint32 GetItemCount(uint32 item, bool inBankAlso = false, Item* skipItem = nullptr) const;
uint32 GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipItem = nullptr) const;
Item* GetItemByGuid(ObjectGuid guid) const;
@@ -2490,6 +2491,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SendRespondInspectAchievements(Player* player) const;
uint32 GetAchievementPoints() const;
+ std::vector<uint32> GetCompletedAchievementIds() const;
bool HasAchieved(uint32 achievementId) const;
void ResetAchievements();
void ResetCriteria(CriteriaFailEvent condition, int32 failAsset, bool evenIfCriteriaComplete = false);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 4bb66052f90..1b8aef79de5 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -431,7 +431,7 @@ void WorldSession::HandleCharEnum(CharacterDatabaseQueryHolder* holder)
while (result->NextRow());
}
- charEnum.IsAlliedRacesCreationAllowed = GetAccountExpansion() >= EXPANSION_BATTLE_FOR_AZEROTH;
+ charEnum.IsAlliedRacesCreationAllowed = CanAccessAlliedRaces();
for (std::pair<uint8 const, RaceUnlockRequirement> const& requirement : sObjectMgr->GetRaceUnlockRequirements())
{
diff --git a/src/server/game/Scenarios/Scenario.cpp b/src/server/game/Scenarios/Scenario.cpp
index b669a59edfd..6e92b5625f4 100644
--- a/src/server/game/Scenarios/Scenario.cpp
+++ b/src/server/game/Scenarios/Scenario.cpp
@@ -28,8 +28,8 @@ Scenario::Scenario(ScenarioData const* scenarioData) : _data(scenarioData), _cur
{
ASSERT(_data);
- for (auto step : _data->Steps)
- SetStepState(step.second, SCENARIO_STEP_NOT_STARTED);
+ for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
+ SetStepState(scenarioStep.second, SCENARIO_STEP_NOT_STARTED);
if (ScenarioStepEntry const* step = GetFirstStep())
SetStep(step);
@@ -112,12 +112,12 @@ void Scenario::OnPlayerExit(Player* player)
bool Scenario::IsComplete()
{
- for (auto step : _data->Steps)
+ for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
{
- if (step.second->IsBonusObjective())
+ if (scenarioStep.second->IsBonusObjective())
continue;
- if (GetStepState(step.second) != SCENARIO_STEP_DONE)
+ if (GetStepState(scenarioStep.second) != SCENARIO_STEP_DONE)
return false;
}
@@ -222,7 +222,7 @@ void Scenario::BuildScenarioState(WorldPackets::Scenario::ScenarioState* scenari
scenarioState->CriteriaProgress = GetCriteriasProgress();
scenarioState->BonusObjectives = GetBonusObjectivesData();
// Don't know exactly what this is for, but seems to contain list of scenario steps that we're either on or that are completed
- for (auto state : _stepStates)
+ for (std::pair<ScenarioStepEntry const* const, ScenarioStepState> const& state : _stepStates)
{
if (state.first->IsBonusObjective())
continue;
@@ -246,7 +246,7 @@ ScenarioStepEntry const* Scenario::GetFirstStep() const
{
// Do it like this because we don't know what order they're in inside the container.
ScenarioStepEntry const* firstStep = nullptr;
- for (auto scenarioStep : _data->Steps)
+ for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
{
if (scenarioStep.second->IsBonusObjective())
continue;
@@ -258,6 +258,22 @@ ScenarioStepEntry const* Scenario::GetFirstStep() const
return firstStep;
}
+ScenarioStepEntry const* Scenario::GetLastStep() const
+{
+ // Do it like this because we don't know what order they're in inside the container.
+ ScenarioStepEntry const* lastStep = nullptr;
+ for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
+ {
+ if (scenarioStep.second->IsBonusObjective())
+ continue;
+
+ if (!lastStep || scenarioStep.second->OrderIndex > lastStep->OrderIndex)
+ lastStep = scenarioStep.second;
+ }
+
+ return lastStep;
+}
+
void Scenario::SendScenarioState(Player* player)
{
WorldPackets::Scenario::ScenarioState scenarioState;
@@ -268,16 +284,16 @@ void Scenario::SendScenarioState(Player* player)
std::vector<WorldPackets::Scenario::BonusObjectiveData> Scenario::GetBonusObjectivesData()
{
std::vector<WorldPackets::Scenario::BonusObjectiveData> bonusObjectivesData;
- for (auto itr = _data->Steps.begin(); itr != _data->Steps.end(); ++itr)
+ for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
{
- if (!itr->second->IsBonusObjective())
+ if (!scenarioStep.second->IsBonusObjective())
continue;
- if (sCriteriaMgr->GetCriteriaTree(itr->second->Criteriatreeid))
+ if (sCriteriaMgr->GetCriteriaTree(scenarioStep.second->Criteriatreeid))
{
WorldPackets::Scenario::BonusObjectiveData bonusObjectiveData;
- bonusObjectiveData.BonusObjectiveID = itr->second->ID;
- bonusObjectiveData.ObjectiveComplete = GetStepState(itr->second) == SCENARIO_STEP_DONE;
+ bonusObjectiveData.BonusObjectiveID = scenarioStep.second->ID;
+ bonusObjectiveData.ObjectiveComplete = GetStepState(scenarioStep.second) == SCENARIO_STEP_DONE;
bonusObjectivesData.push_back(bonusObjectiveData);
}
}
@@ -291,13 +307,13 @@ std::vector<WorldPackets::Achievement::CriteriaProgress> Scenario::GetCriteriasP
if (!_criteriaProgress.empty())
{
- for (auto critItr = _criteriaProgress.begin(); critItr != _criteriaProgress.end(); ++critItr)
+ for (std::pair<uint32 const, CriteriaProgress> const& progressPair : _criteriaProgress)
{
WorldPackets::Achievement::CriteriaProgress criteriaProgress;
- criteriaProgress.Id = critItr->first;
- criteriaProgress.Quantity = critItr->second.Counter;
- criteriaProgress.Date = critItr->second.Date;
- criteriaProgress.Player = critItr->second.PlayerGUID;
+ criteriaProgress.Id = progressPair.first;
+ criteriaProgress.Quantity = progressPair.second.Counter;
+ criteriaProgress.Date = progressPair.second.Date;
+ criteriaProgress.Player = progressPair.second.PlayerGUID;
criteriasProgress.push_back(criteriaProgress);
}
}
diff --git a/src/server/game/Scenarios/Scenario.h b/src/server/game/Scenarios/Scenario.h
index 49fd3726003..596eae06077 100644
--- a/src/server/game/Scenarios/Scenario.h
+++ b/src/server/game/Scenarios/Scenario.h
@@ -69,6 +69,7 @@ class TC_GAME_API Scenario : public CriteriaHandler
ScenarioStepState GetStepState(ScenarioStepEntry const* step);
ScenarioStepEntry const* GetStep() const { return _currentstep; }
ScenarioStepEntry const* GetFirstStep() const;
+ ScenarioStepEntry const* GetLastStep() const;
void SendScenarioState(Player* player);
void SendBootPlayer(Player* player);
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 9631b1c007e..628c455a0fc 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -911,6 +911,11 @@ TransactionCallback& WorldSession::AddTransactionCallback(TransactionCallback&&
return _transactionCallbacks.AddCallback(std::move(callback));
}
+bool WorldSession::CanAccessAlliedRaces() const
+{
+ return GetAccountExpansion() >= EXPANSION_BATTLE_FOR_AZEROTH;
+}
+
void WorldSession::InitWarden(SessionKey const& k)
{
if (_os == "Win")
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index eb0e22b3e05..ad8bba5a316 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -989,6 +989,8 @@ class TC_GAME_API WorldSession
uint8 GetExpansion() const { return m_expansion; }
std::string const& GetOS() const { return _os; }
+ bool CanAccessAlliedRaces() const;
+
void InitWarden(SessionKey const& k);
/// Session in auth.queue currently