diff --git a/Source/Framework/Constants/AchievementConst.cs b/Source/Framework/Constants/AchievementConst.cs index bf2d393a1..1b8df9d9a 100644 --- a/Source/Framework/Constants/AchievementConst.cs +++ b/Source/Framework/Constants/AchievementConst.cs @@ -118,8 +118,11 @@ namespace Framework.Constants SourceIsAlive = 16, SourceAreaOrZone = 17, TargetAreaOrZone = 18, + //Unk19 = 19, MapDifficultyOld = 20, - TargetCreatureYieldsXp = 21, + TargetCreatureYieldsXp = 21, // Nyi + SourceLevelAboveTarget = 22, + SourceLevelEqualTarget = 23, ArenaType = 24, SourceRace = 25, SourceClass = 26, @@ -127,57 +130,261 @@ namespace Framework.Constants TargetClass = 28, MaxGroupMembers = 29, TargetCreatureType = 30, + TargetCreatureFamily = 31, SourceMap = 32, - ItemClass = 33, - ItemSubclass = 34, - CompleteQuestNotInGroup = 35, - MinPersonalRating = 37, + ClientVersion = 33, + BattlePetTeamLevel = 34, + NotInGroup = 35, + InGroup = 36, + MinPersonalRating = 37, // Nyi TitleBitIndex = 38, SourceLevel = 39, TargetLevel = 40, - TargetZone = 41, - TargetHealthPercentBelow = 46, + SourceZone = 41, + TargetZone = 42, + SourceHealthPctLower = 43, + SourceHealthPctGreater = 44, + SourceHealthPctEqual = 45, + TargetHealthPctLower = 46, + TargetHealthPctGreater = 47, + TargetHealthPctEqual = 48, + SourceHealthLower = 49, + SourceHealthGreater = 50, + SourceHealthEqual = 51, + TargetHealthLower = 52, + TargetHealthGreater = 53, + TargetHealthEqual = 54, TargetPlayerCondition = 55, MinAchievementPoints = 56, - RequiresLfgGroup = 58, - Unk60 = 60, - RequiresGuildGroup = 61, + InLfgDungeon = 57, + InLfgRandomDungeon = 58, + InLfgFirstRandomDungeon = 59, + //Unk60 = 60, // Nyi + RequiresGuildGroup = 61, // Nyi GuildReputation = 62, - RatedBattleground = 63, + RatedBattleground = 63, // Nyi RatedBattlegroundRating = 64, ProjectRarity = 65, ProjectRace = 66, - WorldState = 67, // Nyi - MapDifficulty = 68, // Nyi - PlayerLevel = 69, // Nyi - TargetPlayerLevel = 70, // Nyi - //PlayerLevelOnAccount = 71, // Not Verified - //Unk73 = 73, // References Another Modifier Tree Id - ScenarioId = 74, // Nyi + WorldStateExpression = 67, + MapDifficulty = 68, + SourceLevelGreater = 69, + TargetLevelGreater = 70, + SourceLevelLower = 71, + TargetLevelLower = 72, + ModifierTree = 73, + ScenarioId = 74, + TheTillersReputation = 75, + PetBattleAchievementPoints = 76, // Nyi + //Unk77 = 77, // Nyi BattlePetFamily = 78, // Nyi BattlePetHealthPct = 79, // Nyi - //Unk80 = 80 // Something To Do With World Bosses + GuildGroupMembers = 80, // Nyi BattlePetEntry = 81, // Nyi - //BattlePetEntryId = 82, // Some Sort Of Data Id? - ChallengeModeMedal = 83, // NYI - //CRITERIA_ADDITIONAL_CONDITION_UNK84 = 84, // Quest id - //CRITERIA_ADDITIONAL_CONDITION_UNK86 = 86, // Some external event id - //CRITERIA_ADDITIONAL_CONDITION_UNK87 = 87, // Achievement id + ScenarioStepIndex = 82, + ChallengeModeMedal = 83, // Nyi + IsOnQuest = 84, + ExaltedWithFaction = 85, // Nyi + HasAchievement = 86, + HasAchievementOnCharacter = 87, // Nyi + CloudSerpentReputation = 88, + BattlePetBreedQualityId = 89, // Nyi + PetBattleIsPvp = 90, // Nyi BattlePetSpecies = 91, - Expansion = 92, + ActiveExpansion = 92, + //Unk93 = 93, // Nyi + FriendshipRepReaction = 94, // Nyi + FactionStanding = 95, + ItemClassAndSubclass = 96, // Nyi + SourceSex = 97, + SourceNativeSex = 98, + Skill = 99, + //Unk100 = 100, // Nyi + NormalPhaseShift = 101, + InPhase = 102, + NotInPhase = 103, + HasSpell = 104, + ItemCount = 105, + AccountExpansion = 106, + SourceHasAuraLabel = 107, // Nyi, Spelllabel + //Unk108 = 108, // Nyi + TimeInRange = 109, // Nyi, Packed Time Between Asset And Secondaryasset RewardedQuest = 110, CompletedQuest = 111, - CompletedQuestObjective = 112, // NYI, QuestObjectiveID - GarrisonFollowerEntry = 144, - GarrisonFollowerQuality = 145, - GarrisonFollowerLevel = 146, - GarrisonRareMission = 147, // NYI - GarrisonBuildingLevel = 149, // NYI - GarrisonMissionType = 167, // NYI - PlayerItemLevel = 169, // NYI - GarrisonFollowILvl = 184, + CompletedQuestObjective = 112, // Nyi, Questobjectiveid + ExploredArea = 113, + ItemCountIncludingBank = 114, + //Unk115 = 115, // Nyi + SourcePvpFactionIndex = 116, + LfgValueEqual = 117, + LfgValueGreater = 118, + CurrencyAmount = 119, + //Unk120 = 120, // Nyi + CurrencyTrackedAmount = 121, + MapInstanceType = 122, + Mentor = 123, + //Unk124 = 124, // Nyi + //Unk125 = 125, // Nyi + GarrisonLevelAbove = 126, // Asset: Garrlevel, Secondaryasset: Garrtype + GarrisonFollowersAboveLevel = 127, // Asset: Count, Secondaryasset: Followerlevel, Tertiaryasset: Garrtype + GarrisonFollowersAboveQuality = 128, // Asset: Count, Secondaryasset: Followerquality, Tertiaryasset: Garrtype + GarrisonFollowerAboveLevelWithAbility = 129, // Asset: Followerlevel, Secondaryasset: Ability, Tertiaryasset: Garrtype + GarrisonFollowerAboveLevelWithTrait = 130, // Asset: Followerlevel, Secondaryasset: Ability, Tertiaryasset: Garrtype (Same As Above But Ability Must Have GarrisonAbilityFlagTrait) + GarrisonFollowerWithAbilityInBuilding = 131, // Asset: Ability, Secondaryasset: Buildingtype, Tertiaryasset: Garrtype + GarrisonFollowerWithTraitInBuilding = 132, // Asset: Ability, Secondaryasset: Buildingtype, Tertiaryasset: Garrtype + GarrisonFollowerAboveLevelInBuilding = 133, // Asset: Followerlevel, Secondaryasset: Buildingtype, Tertiaryasset: Garrtype + GarrisonBuildingAboveLevel = 134, // Asset: Buildingtype, Secondaryasset: Buildinglevel, Tertiaryasset: Garrtype + GarrisonBlueprint = 135, // Nyi + //Unk136 = 136, // Nyi + //Unk137 = 137, // Nyi + //Unk138 = 138, // Nyi + //Unk139 = 139, // Nyi + GarrisonBuildingInactive = 140, + //Unk141 = 141, // Nyi + GarrisonBuildingEqualLevel = 142, // Asset: Buildingtype, Secondaryasset: Buildinglevel, Tertiaryasset: Garrtype + GarrisonFollowerWithAbility = 143, // Asset: Ability, Secondaryasset: Garrtype + GarrisonFollowerWithTrait = 144, // Asset: Ability, Secondaryasset: Garrtype + GarrisonFollowerAboveQualityWod = 145, // Asset: Followerquality + GarrisonFollowerEqualLevel = 146, // Asset: Followerlevel, Secondaryasset: Garrtype + GarrisonRareMission = 147, // Nyi + //Unk148 = 148, // Nyi + GarrisonBuildingLevel = 149, // Nyi + //Unk150 = 150, // Nyi + BattlePetSpeciesInTeam = 151, // Asset: Count, Secondaryasset: Battlepetspeciesid + BattlePetFamilyInTeam = 152, // Asset: Count, Secondaryasset: Battlepetfamily + //Unk153 = 153, // Nyi + //Unk154 = 154, // Nyi + //Unk155 = 155, // Nyi + //Unk156 = 156, // Nyi + GarrisonFollowerId = 157, // Follower With Id, In Any Garrison + QuestObjectiveProgressEqual = 158, // Nyi Asset: Questobjectiveid, Secondaryasset: Progress + QuestObjectiveProgressAbove = 159, // Nyi Asset: Questobjectiveid, Secondaryasset: Progress + //Unk160 = 160, // Nyi + //Unk161 = 161, // Nyi + //Unk162 = 162, // Nyi + //Unk163 = 163, // Nyi + //Unk164 = 164, // Nyi + //Unk165 = 165, // Nyi + //Unk166 = 166, // Nyi + GarrisonMissionType = 167, // Nyi + GarrisonFollowerAboveItemLevel = 168, // Asset: Followeritemlevel + GarrisonFollowersAboveItemLevel = 169, // Asset: Count, Secondaryasset: Followeritemlevel, Tertiaryasset: Garrtype + GarrisonLevelEqual = 170, // Asset: Count + GarrisonGroupSize = 171, // Nyi + //Unk172 = 172, // Nyi Something To Do With Currency But Only Used On Criterias That Require The Same Currency + TargetingCorpse = 173, + //Unk174 = 174, // Nyi + GarrisonFollowersLevelEqual = 175, // Asset: Count, Secondaryasset: Followerlevel, Tertiaryasset: Garrtype + GarrisonFollowerIdInBuilding = 176, // Asset: Followerid, Secondaryasset: Buildingtype + //Unk177 = 177, // Nyi + //Unk178 = 178, // Nyi + WorldPvpArea = 179, // Nyi + NonOwnGarrison = 180, // Nyi + //Unk181 = 181, // Nyi + //Unk182 = 183, // Nyi + //Unk183 = 183, // Nyi + GarrisonFollowersItemLevelAbove = 184, + //Unk185 = 185, // Nyi + //Unk186 = 186, // Nyi + GarrisonFollowerType = 187, // Nyi + //Unk188 = 188, // Nyi + //Unk189 = 189, // Nyi + //Unk190 = 190, // Nyi + //Unk191 = 191, // Nyi + //Unk192 = 192, // Nyi HonorLevel = 193, - PrestigeLevel = 194 + PrestigeLevel = 194, + //Unk195 = 195, // Nyi + //Unk196 = 196, // Nyi + //Unk197 = 197, // Nyi + //Unk198 = 198, // Nyi + //Unk198 = 199, // Nyi + ItemModifiedAppearance = 200, + GarrisonSelectedTalent = 201, // Nyi Asset: Garrtalentid (Talent Selected, Research Timer Doesn'T Matter) + GarrisonResearchedTalent = 202, // Nyi Asset: Garrtalentid (Talent Selected, Research Must Be Finished) + HasCharacterRestrictions = 203, + //Unk204 = 204, // Nyi + //Unk205 = 205, // Nyi + QuestInfoId = 206, + GarrisonResearchingTalent = 207, // Nyi Asset: Garrtalentid (Talent Selected, Research Must Be In Progress) + ArtifactAppearanceSetUsed = 208, + CurrencyAmountEqual = 209, + //Unk210 = 210, // Nyi + ScenarioType = 211, + AccountExpansionEqual = 212, + //Unk213 = 213, // Nyi + //Unk214 = 214, // Nyi + //Unk215 = 215, // Nyi + ChallengeModeMedal2 = 216, // Nyi Keystone Master, Asset = 3 + //Unk217 = 217, // Nyi + //Unk218 = 218, // Nyi + //Unk219 = 219, // Nyi + //Unk220 = 220, // Nyi + //Unk221 = 221, // Nyi + //Unk222 = 222, // Nyi + //Unk223 = 223, // Nyi + //Unk224 = 224, // Nyi + //Unk225 = 225, // Nyi + UsedLevelBoost = 226, // Nyi + UsedRaceChange = 227, // Nyi + UsedFactionChange = 228, // Nyi + //Unk229 = 229, // Nyi + //Unk230 = 230, // Nyi + AchievementGloballyIncompleted = 231, // Hall Of Fame Stuff, Asset: Unk, Secondaryasset: Achievementid + MainHandVisibleSubclass = 232, + OffHandVisibleSubclass = 233, + PvpTier = 234, // Nyi Asset: Pvptierid + AzeriteItemLevel = 235, + //Unk236 = 236, // Nyi + //Unk237 = 237, // Nyi + //Unk238 = 238, // Nyi + PvpTierGreater = 239, // Nyi Asset: Pvptierenum, Secondaryasset: Pvpbracket + //Unk240 = 240, // Nyi + //Unk241 = 241, // Nyi + //Unk242 = 242, // Nyi + //Unk243 = 243, // Nyi + //Unk244 = 244, // Nyi + InWarMode = 245, + //Unk246 = 246, // Nyi + KeystoneLevel = 247, // Nyi + //Unk248 = 248, // Nyi + KeystoneDungeon = 249, // Nyi Asset: Mapchallengemodeid + //Unk250 = 250, // Nyi + PvpSeason = 251, // Nyi Asset: That Unknown Column In Pvpseason.Db2 + SourceDisplayRace = 252, + TargetDisplayRace = 253, + FriendshipRepReactionExact = 254, // Nyi + SourceAuraCountEqual = 255, + TargetAuraCountEqual = 256, + SourceAuraCountGreater = 257, + TargetAuraCountGreater = 258, + UnlockedAzeriteEssenceRankLower = 259, + UnlockedAzeriteEssenceRankEqual = 260, + UnlockedAzeriteEssenceRankGreater = 261, + SourceHasAuraEffectIndex = 262, // Asset: Spellid, Secondaryasset: Index + SourceSpecializationRole = 263, + SourceLevel120 = 264, + //Unk265 = 265, + SelectedAzeriteEssenceRankLower = 266, + SelectedAzeriteEssenceRankGreater = 267, + //Unk268 = 268, + //Unk269 = 269, + //Unk270 = 270, + //Unk271 = 271, + //Unk272 = 272, + //Unk273 = 273, + //Unk274 = 274, + //Unk275 = 275, + //Unk276 = 276, + //Unk277 = 277, + //Unk278 = 278, + //Unk279 = 279, + MapOrCosmeticMap = 280, + //Unk281 = 281, + HasEntitlement = 282, + HasQuestSession = 283, + //Unk284 = 284, + //Unk285 = 285, } public enum CriteriaFlags diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index e23adc874..d3ff40ff5 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -1393,6 +1393,14 @@ namespace Framework.Constants UnderwaterAllowed = 0x8 } + public enum ModifierTreeOperator + { + SingleTrue = 2, + SingleFalse = 3, + All = 4, + Some = 8 + } + public enum MountCapabilityFlags : byte { Ground = 0x1, diff --git a/Source/Game/Achievements/AchievementManager.cs b/Source/Game/Achievements/AchievementManager.cs index 3ffa51af9..f406c825d 100644 --- a/Source/Game/Achievements/AchievementManager.cs +++ b/Source/Game/Achievements/AchievementManager.cs @@ -566,7 +566,11 @@ namespace Game.Achievements public bool ModifierTreeSatisfied(uint modifierTreeId) { - return AdditionalRequirementsSatisfied(Global.CriteriaMgr.GetModifierTree(modifierTreeId), 0, 0, null, _owner); + ModifierTreeNode modifierTree = Global.CriteriaMgr.GetModifierTree(modifierTreeId); + if (modifierTree != null) + return ModifierTreeSatisfied(modifierTree, 0, 0, null, _owner); + + return false; } public override void SendCriteriaUpdate(Criteria criteria, CriteriaProgress progress, uint timeElapsed, bool timedCompleted) diff --git a/Source/Game/Achievements/CriteriaHandler.cs b/Source/Game/Achievements/CriteriaHandler.cs index 634f0e7be..03a58106b 100644 --- a/Source/Game/Achievements/CriteriaHandler.cs +++ b/Source/Game/Achievements/CriteriaHandler.cs @@ -18,12 +18,15 @@ using Framework.Constants; using Framework.Database; using Game.Arenas; +using Game.BattleFields; using Game.BattleGrounds; using Game.DataStorage; using Game.Entities; using Game.Garrisons; using Game.Maps; using Game.Network; +using Game.Network.Packets; +using Game.Scenarios; using Game.Spells; using System; using System.Collections.Generic; @@ -220,16 +223,23 @@ namespace Game.Achievements } case CriteriaTypes.CompleteQuestsInZone: { - uint counter = 0; - - var rewQuests = referencePlayer.GetRewardedQuests(); - foreach (var id in rewQuests) + if (miscValue1 != 0) { - Quest quest = Global.ObjectMgr.GetQuestTemplate(id); - if (quest != null && quest.QuestSortID >= 0 && quest.QuestSortID == criteria.Entry.Asset) - ++counter; + SetCriteriaProgress(criteria, 1, referencePlayer, ProgressType.Accumulate); + } + else // login case + { + uint counter = 0; + + var rewQuests = referencePlayer.GetRewardedQuests(); + foreach (var id in rewQuests) + { + Quest quest = Global.ObjectMgr.GetQuestTemplate(id); + if (quest != null && quest.QuestSortID >= 0 && quest.QuestSortID == criteria.Entry.Asset) + ++counter; + } + SetCriteriaProgress(criteria, counter, referencePlayer); } - SetCriteriaProgress(criteria, counter, referencePlayer); break; } case CriteriaTypes.FallWithoutDying: @@ -856,7 +866,7 @@ namespace Game.Achievements return false; } - if (criteria.Modifier != null && !AdditionalRequirementsSatisfied(criteria.Modifier, miscValue1, miscValue2, unit, referencePlayer)) + if (criteria.Modifier != null && !ModifierTreeSatisfied(criteria.Modifier, miscValue1, miscValue2, unit, referencePlayer)) { Log.outTrace(LogFilter.Achievement, "CanUpdateCriteria: (Id: {0} Type {1}) Requirements have not been satisfied", criteria.ID, criteria.Entry.Type); return false; @@ -970,8 +980,12 @@ namespace Game.Achievements return false; break; case CriteriaTypes.CompleteQuestsInZone: - if (miscValue1 != 0 && miscValue1 != criteria.Entry.Asset) - return false; + if (miscValue1 != 0) + { + Quest quest = Global.ObjectMgr.GetQuestTemplate((uint)miscValue1); + if (quest == null || quest.QuestSortID != criteria.Entry.Asset) + return false; + } break; case CriteriaTypes.Death: { @@ -1180,19 +1194,51 @@ namespace Game.Achievements return true; } - public bool AdditionalRequirementsSatisfied(ModifierTreeNode tree, ulong miscValue1, ulong miscValue2, Unit unit, Player referencePlayer) + public bool ModifierTreeSatisfied(ModifierTreeNode tree, ulong miscValue1, ulong miscValue2, Unit unit, Player referencePlayer) { - foreach (ModifierTreeNode node in tree.Children) - if (!AdditionalRequirementsSatisfied(node, miscValue1, miscValue2, unit, referencePlayer)) - return false; - - uint reqType = tree.Entry.Type; - if (reqType == 0) - return true; - - uint reqValue = tree.Entry.Asset; - switch ((CriteriaAdditionalCondition)reqType) + switch ((ModifierTreeOperator)tree.Entry.Operator) { + case ModifierTreeOperator.SingleTrue: + return tree.Entry.Type != 0 && ModifierSatisfied(tree.Entry, miscValue1, miscValue2, unit, referencePlayer); + case ModifierTreeOperator.SingleFalse: + return tree.Entry.Type != 0 && !ModifierSatisfied(tree.Entry, miscValue1, miscValue2, unit, referencePlayer); + case ModifierTreeOperator.All: + foreach (ModifierTreeNode node in tree.Children) + if (!ModifierTreeSatisfied(node, miscValue1, miscValue2, unit, referencePlayer)) + return false; + return true; + case ModifierTreeOperator.Some: + { + sbyte requiredAmount = Math.Max(tree.Entry.Amount, (sbyte)1); + foreach (ModifierTreeNode node in tree.Children) + if (ModifierTreeSatisfied(node, miscValue1, miscValue2, unit, referencePlayer)) + if (--requiredAmount == 0) + return true; + + return false; + } + default: + break; + } + + return false; + } + + bool ModifierSatisfied(ModifierTreeRecord modifier, ulong miscValue1, ulong miscValue2, Unit unit, Player referencePlayer) + { + uint reqValue = modifier.Asset; + int secondaryAsset = modifier.SecondaryAsset; + int tertiaryAsset = modifier.TertiaryAsset; + + switch ((CriteriaAdditionalCondition)modifier.Type) + { + case CriteriaAdditionalCondition.SourceDrunkValue: // 1 + { + uint inebriation = (uint)Math.Min(Math.Max(referencePlayer.GetDrunkValue(), referencePlayer.m_playerData.FakeInebriation), 100); + if (inebriation < reqValue) + return false; + break; + } case CriteriaAdditionalCondition.SourcePlayerCondition: // 2 { PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(reqValue); @@ -1264,6 +1310,10 @@ namespace Game.Achievements return false; break; } + case CriteriaAdditionalCondition.SourceIsAlive: // 16 + if (referencePlayer.IsDead()) + return false; + break; case CriteriaAdditionalCondition.SourceAreaOrZone: // 17 { uint zoneId, areaId; @@ -1289,6 +1339,14 @@ namespace Game.Achievements return false; break; } + case CriteriaAdditionalCondition.SourceLevelAboveTarget: // 22 + if (!unit || referencePlayer.GetLevel() + reqValue < unit.GetLevel()) + return false; + break; + case CriteriaAdditionalCondition.SourceLevelEqualTarget: // 23 + if (!unit || referencePlayer.GetLevel() != unit.GetLevel()) + return false; + break; case CriteriaAdditionalCondition.ArenaType: // 24 { Battleground bg = referencePlayer.GetBattleground(); @@ -1325,10 +1383,35 @@ namespace Game.Achievements return false; break; } + case CriteriaAdditionalCondition.TargetCreatureFamily: // 31 + { + if (!unit) + return false; + if (unit.GetTypeId() != TypeId.Unit || unit.ToCreature().GetCreatureTemplate().Family != (CreatureFamily)reqValue) + return false; + break; + } case CriteriaAdditionalCondition.SourceMap: // 32 if (referencePlayer.GetMapId() != reqValue) return false; break; + case CriteriaAdditionalCondition.ClientVersion: // 33 + if (reqValue < Global.RealmMgr.GetMinorMajorBugfixVersionForBuild(Global.WorldMgr.GetRealm().Build)) + return false; + break; + case CriteriaAdditionalCondition.BattlePetTeamLevel: // 34 + foreach (BattlePetSlot slot in referencePlayer.GetSession().GetBattlePetMgr().GetSlots()) + if (slot.Pet.Level != reqValue) + return false; + break; + case CriteriaAdditionalCondition.NotInGroup: // 35 + if (referencePlayer.GetGroup()) + return false; + break; + case CriteriaAdditionalCondition.InGroup: // 36 + if (!referencePlayer.GetGroup()) + return false; + break; case CriteriaAdditionalCondition.TitleBitIndex: // 38 // miscValue1 is title's bit index if (miscValue1 != reqValue) return false; @@ -1341,12 +1424,76 @@ namespace Game.Achievements if (unit == null || unit.GetLevelForTarget(referencePlayer) != reqValue) return false; break; - case CriteriaAdditionalCondition.TargetZone: // 41 - if (unit == null || unit.GetZoneId() != reqValue) + case CriteriaAdditionalCondition.SourceZone: // 41 + { + uint zoneId = referencePlayer.GetAreaId(); + AreaTableRecord areaEntry = CliDB.AreaTableStorage.LookupByKey(zoneId); + if (areaEntry != null) + if (areaEntry.Flags[0].HasAnyFlag(AreaFlags.Unk9)) + zoneId = areaEntry.ParentAreaID; + if (zoneId != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.TargetZone: // 42 + { + if (!unit) + return false; + uint zoneId = unit.GetAreaId(); + AreaTableRecord areaEntry = CliDB.AreaTableStorage.LookupByKey(zoneId); + if (areaEntry != null) + if (areaEntry.Flags[0].HasAnyFlag(AreaFlags.Unk9)) + zoneId = areaEntry.ParentAreaID; + if (zoneId != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.SourceHealthPctLower: // 43 + if (referencePlayer.GetHealthPct() > (float)reqValue) return false; break; - case CriteriaAdditionalCondition.TargetHealthPercentBelow: // 46 - if (unit == null || unit.GetHealthPct() >= reqValue) + case CriteriaAdditionalCondition.SourceHealthPctGreater: // 44 + if (referencePlayer.GetHealthPct() < (float)reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceHealthPctEqual: // 45 + if (referencePlayer.GetHealthPct() != (float)reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetHealthPctLower: // 46 + if (unit == null || unit.GetHealthPct() >= (float)reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetHealthPctGreater: // 47 + if (!unit || unit.GetHealthPct() < (float)reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetHealthPctEqual: // 48 + if (!unit || unit.GetHealthPct() != (float)reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceHealthLower: // 49 + if (referencePlayer.GetHealth() > reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceHealthGreater: // 50 + if (referencePlayer.GetHealth() < reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceHealthEqual: // 51 + if (referencePlayer.GetHealth() != reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetHealthLower: // 52 + if (!unit || unit.GetHealth() > reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetHealthGreater: // 53 + if (!unit || unit.GetHealth() < reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetHealthEqual: // 54 + if (!unit || unit.GetHealth() != reqValue) return false; break; case CriteriaAdditionalCondition.TargetPlayerCondition: // 55 @@ -1359,10 +1506,35 @@ namespace Game.Achievements return false; break; } + case CriteriaAdditionalCondition.MinAchievementPoints: // 56 + if (referencePlayer.GetAchievementPoints() <= reqValue) + return false; + break; + case CriteriaAdditionalCondition.InLfgDungeon: // 57 + if (ConditionManager.GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus.InLFGDungeon) == 0) + return false; + break; + case CriteriaAdditionalCondition.InLfgRandomDungeon: // 58 + if (ConditionManager.GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus.InLFGRandomDungeon) == 0) + return false; + break; + case CriteriaAdditionalCondition.InLfgFirstRandomDungeon: // 59 + if (ConditionManager.GetPlayerConditionLfgValue(referencePlayer, PlayerConditionLfgStatus.InLFGFirstRandomDungeon) == 0) + return false; + break; + case CriteriaAdditionalCondition.GuildReputation: // 62 + if (referencePlayer.GetReputationMgr().GetReputation(1168) < reqValue) + return false; + break; case CriteriaAdditionalCondition.RatedBattlegroundRating: // 64 if (referencePlayer.GetRBGPersonalRating() < reqValue) return false; break; + case CriteriaAdditionalCondition.WorldStateExpression: // 67 + WorldStateExpressionRecord worldStateExpression = CliDB.WorldStateExpressionStorage.LookupByKey(reqValue); + if (worldStateExpression != null) + return ConditionManager.IsPlayerMeetingExpression(referencePlayer, worldStateExpression); + return false; case CriteriaAdditionalCondition.MapDifficulty: // 68 { DifficultyRecord difficulty = CliDB.DifficultyStorage.LookupByKey(referencePlayer.GetMap().GetDifficultyID()); @@ -1370,74 +1542,912 @@ namespace Game.Achievements return false; break; } + case CriteriaAdditionalCondition.SourceLevelGreater: // 69 + if (referencePlayer.GetLevel() < reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetLevelGreater: // 70 + if (!unit || unit.GetLevel() < reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceLevelLower: // 71 + if (referencePlayer.GetLevel() > reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetLevelLower: // 72 + if (!unit || unit.GetLevel() > reqValue) + return false; + break; + case CriteriaAdditionalCondition.ModifierTree: // 73 + ModifierTreeNode nextModifierTree = Global.CriteriaMgr.GetModifierTree(reqValue); + if (nextModifierTree != null) + return ModifierTreeSatisfied(nextModifierTree, miscValue1, miscValue2, unit, referencePlayer); + return false; + case CriteriaAdditionalCondition.ScenarioId: // 74 + { + Scenario scenario = referencePlayer.GetScenario(); + if (scenario == null) + return false; + + if (scenario.GetEntry().Id != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.TheTillersReputation: // 75 + if (referencePlayer.GetReputationMgr().GetReputation(1272) < reqValue) + return false; + break; + case CriteriaAdditionalCondition.ScenarioStepIndex: // 82 + { + Scenario scenario = referencePlayer.GetScenario(); + if (scenario == null) + return false; + + if (scenario.GetStep().OrderIndex != (reqValue - 1)) + return false; + break; + } + case CriteriaAdditionalCondition.IsOnQuest: // 84 + if (referencePlayer.FindQuestSlot(reqValue) == SharedConst.MaxQuestLogSize) + return false; + break; + case CriteriaAdditionalCondition.ExaltedWithFaction: // 85 + if (referencePlayer.GetReputationMgr().GetReputation(reqValue) < 42000) + return false; + break; + case CriteriaAdditionalCondition.HasAchievement: // 86 + if (!referencePlayer.HasAchieved(reqValue)) + return false; + break; + case CriteriaAdditionalCondition.CloudSerpentReputation: // 88 + if (referencePlayer.GetReputationMgr().GetReputation(1271) < reqValue) + return false; + break; case CriteriaAdditionalCondition.BattlePetSpecies: // 91 if (miscValue1 != reqValue) return false; break; + case CriteriaAdditionalCondition.ActiveExpansion: // 92 + if ((int)referencePlayer.GetSession().GetExpansion() < reqValue) + return false; + break; + case CriteriaAdditionalCondition.FactionStanding: // 95 + if (referencePlayer.GetReputationMgr().GetReputation(reqValue) < reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceSex: // 97 + if ((int)referencePlayer.GetGender() != reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceNativeSex: // 98 + if (referencePlayer.m_playerData.NativeSex != reqValue) + return false; + break; + case CriteriaAdditionalCondition.Skill: // 99 + if (referencePlayer.GetPureSkillValue((SkillType)reqValue) < secondaryAsset) + return false; + break; + case CriteriaAdditionalCondition.NormalPhaseShift: // 101 + if (!PhasingHandler.InDbPhaseShift(referencePlayer, 0, 0, 0)) + return false; + break; + case CriteriaAdditionalCondition.InPhase: // 102 + if (!PhasingHandler.InDbPhaseShift(referencePlayer, 0, (ushort)reqValue, 0)) + return false; + break; + case CriteriaAdditionalCondition.NotInPhase: // 103 + if (PhasingHandler.InDbPhaseShift(referencePlayer, 0, (ushort)reqValue, 0)) + return false; + break; + case CriteriaAdditionalCondition.HasSpell: // 104 + if (!referencePlayer.HasSpell(reqValue)) + return false; + break; + case CriteriaAdditionalCondition.ItemCount: // 105 + if (referencePlayer.GetItemCount(reqValue, false) < secondaryAsset) + return false; + break; + case CriteriaAdditionalCondition.AccountExpansion: // 106 + if ((int)referencePlayer.GetSession().GetAccountExpansion() < reqValue) + return false; + break; case CriteriaAdditionalCondition.RewardedQuest: // 110 if (!referencePlayer.GetQuestRewardStatus(reqValue)) return false; break; + case CriteriaAdditionalCondition.CompletedQuest: // 111 if (referencePlayer.GetQuestStatus(reqValue) != QuestStatus.Complete) return false; break; - case CriteriaAdditionalCondition.GarrisonFollowerEntry: // 144 + case CriteriaAdditionalCondition.ExploredArea: // 113 { - if (!referencePlayer) + AreaTableRecord areaTable = CliDB.AreaTableStorage.LookupByKey(reqValue); + if (areaTable == null) return false; - Garrison garrison = referencePlayer.GetGarrison(); - if (garrison == null) - return false; - Garrison.Follower follower = garrison.GetFollower(miscValue1); - if (follower == null || follower.PacketInfo.GarrFollowerID != reqValue) + + if (areaTable.AreaBit <= 0) + break; // success + + int playerIndexOffset = areaTable.AreaBit / 64; + if (playerIndexOffset >= PlayerConst.ExploredZonesSize) + break; + + if ((referencePlayer.m_activePlayerData.ExploredZones[playerIndexOffset] & (1ul << (areaTable.AreaBit % 64))) == 0) return false; break; } - case CriteriaAdditionalCondition.GarrisonFollowerQuality: // 145 + case CriteriaAdditionalCondition.ItemCountIncludingBank: // 114 + if (referencePlayer.GetItemCount(reqValue, true) < secondaryAsset) + return false; + break; + case CriteriaAdditionalCondition.SourcePvpFactionIndex: // 116 { - if (!referencePlayer) + ChrRacesRecord race = CliDB.ChrRacesStorage.LookupByKey(referencePlayer.GetRace()); + if (race == null) return false; + + FactionTemplateRecord faction = CliDB.FactionTemplateStorage.LookupByKey(race.FactionID); + if (faction == null) + return false; + + int factionIndex = -1; + if (faction.FactionGroup.HasAnyFlag((byte)FactionMasks.Horde)) + factionIndex = 0; + else if (faction.FactionGroup.HasAnyFlag((byte)FactionMasks.Alliance)) + factionIndex = 1; + else if (faction.FactionGroup.HasAnyFlag((byte)FactionMasks.Player)) + factionIndex = 0; + if (factionIndex != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.LfgValueEqual: // 117 + if (ConditionManager.GetPlayerConditionLfgValue(referencePlayer, (PlayerConditionLfgStatus)reqValue) != secondaryAsset) + return false; + break; + case CriteriaAdditionalCondition.LfgValueGreater: // 118 + if (ConditionManager.GetPlayerConditionLfgValue(referencePlayer, (PlayerConditionLfgStatus)reqValue) < secondaryAsset) + return false; + break; + case CriteriaAdditionalCondition.CurrencyAmount: // 119 + if (!referencePlayer.HasCurrency(reqValue, (uint)secondaryAsset)) + return false; + break; + case CriteriaAdditionalCondition.CurrencyTrackedAmount: // 121 + if (referencePlayer.GetTrackedCurrencyCount(reqValue) < secondaryAsset) + return false; + break; + case CriteriaAdditionalCondition.MapInstanceType: // 122 + if ((uint)referencePlayer.GetMap().GetEntry().InstanceType != reqValue) + return false; + break; + case CriteriaAdditionalCondition.Mentor: // 123 + if (!referencePlayer.HasPlayerFlag(PlayerFlags.Mentor)) + return false; + break; + case CriteriaAdditionalCondition.GarrisonLevelAbove: // 126 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)secondaryAsset || garrison.GetSiteLevel().GarrLevel < reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowersAboveLevel: // 127 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.FollowerLevel >= secondaryAsset; + }); + + if (followerCount < reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowersAboveQuality: // 128 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.Quality >= secondaryAsset; + }); + + if (followerCount < reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerAboveLevelWithAbility: // 129 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility((uint)secondaryAsset); + }); + + if (followerCount < 1) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerAboveLevelWithTrait: // 130 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + GarrAbilityRecord traitEntry = CliDB.GarrAbilityStorage.LookupByKey(secondaryAsset); + if (traitEntry == null || !traitEntry.Flags.HasAnyFlag(GarrisonAbilityFlags.Trait)) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.FollowerLevel >= reqValue && follower.HasAbility((uint)secondaryAsset); + }); + + if (followerCount < 1) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerWithAbilityInBuilding: // 131 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + GarrBuildingRecord followerBuilding = CliDB.GarrBuildingStorage.LookupByKey(follower.PacketInfo.CurrentBuildingID); + if (followerBuilding == null) + return false; + + return followerBuilding.BuildingType == secondaryAsset && follower.HasAbility(reqValue); ; + }); + + if (followerCount < 1) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerWithTraitInBuilding: // 132 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + GarrAbilityRecord traitEntry = CliDB.GarrAbilityStorage.LookupByKey(reqValue); + if (traitEntry == null || !traitEntry.Flags.HasAnyFlag(GarrisonAbilityFlags.Trait)) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + GarrBuildingRecord followerBuilding = CliDB.GarrBuildingStorage.LookupByKey(follower.PacketInfo.CurrentBuildingID); + if (followerBuilding == null) + return false; + + return followerBuilding.BuildingType == secondaryAsset && follower.HasAbility(reqValue); ; + }); + + if (followerCount < 1) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerAboveLevelInBuilding: // 133 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + if (follower.PacketInfo.FollowerLevel < reqValue) + return false; + + GarrBuildingRecord followerBuilding = CliDB.GarrBuildingStorage.LookupByKey(follower.PacketInfo.CurrentBuildingID); + if (followerBuilding == null) + return false; + + return followerBuilding.BuildingType == secondaryAsset; + }); + if (followerCount < 1) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonBuildingAboveLevel: // 134 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + foreach (Garrison.Plot plot in garrison.GetPlots()) + { + if (!plot.BuildingInfo.PacketInfo.HasValue) + continue; + + GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(plot.BuildingInfo.PacketInfo.Value.GarrBuildingID); + if (building == null || building.UpgradeLevel < reqValue || building.BuildingType != secondaryAsset) + continue; + + return true; + } + return false; + } + case CriteriaAdditionalCondition.GarrisonBlueprint: // 135 + { + GarrBuildingRecord blueprintBuilding = CliDB.GarrBuildingStorage.LookupByKey(reqValue); + if (blueprintBuilding == null) + return false; + + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)blueprintBuilding.GarrTypeID) + return false; + + if (!garrison.HasBlueprint(reqValue)) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonBuildingInactive: // 140 + { + GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(reqValue); + if (building == null) + return false; + + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + foreach (Garrison.Plot plot in garrison.GetPlots()) + { + if (!plot.BuildingInfo.PacketInfo.HasValue || plot.BuildingInfo.PacketInfo.Value.GarrBuildingID != reqValue) + continue; + + return !plot.BuildingInfo.PacketInfo.Value.Active; + } + return false; + } + case CriteriaAdditionalCondition.GarrisonBuildingEqualLevel: // 142 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + foreach (Garrison.Plot plot in garrison.GetPlots()) + { + if (!plot.BuildingInfo.PacketInfo.HasValue) + continue; + + GarrBuildingRecord building = CliDB.GarrBuildingStorage.LookupByKey(plot.BuildingInfo.PacketInfo.Value.GarrBuildingID); + if (building == null || building.UpgradeLevel != reqValue || building.BuildingType != secondaryAsset) + continue; + + return true; + } + return false; + } + case CriteriaAdditionalCondition.GarrisonFollowerWithAbility: // 143 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)secondaryAsset) + return false; + + if (miscValue1 != 0) + { + Garrison.Follower follower = garrison.GetFollower(miscValue1); + if (follower == null) + return false; + + if (!follower.HasAbility(reqValue)) + return false; + } + else + { + uint followerCount = garrison.CountFollowers(follower => + { + return follower.HasAbility(reqValue); + }); + + if (followerCount < 1) + return false; + } + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerWithTrait: // 144 + { + GarrAbilityRecord traitEntry = CliDB.GarrAbilityStorage.LookupByKey(reqValue); + if (traitEntry == null || !traitEntry.Flags.HasAnyFlag(GarrisonAbilityFlags.Trait)) + return false; + + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)secondaryAsset) + return false; + + if (miscValue1 != 0) + { + Garrison.Follower follower = garrison.GetFollower(miscValue1); + if (follower == null || !follower.HasAbility(reqValue)) + return false; + } + else + { + uint followerCount = garrison.CountFollowers(follower => + { + return follower.HasAbility(reqValue); + }); + + if (followerCount < 1) + return false; + } + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerAboveQualityWod: // 145 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != GarrisonType.Garrison) + return false; + + if (miscValue1 != 0) + { + Garrison.Follower follower = garrison.GetFollower(miscValue1); + if (follower == null || follower.PacketInfo.Quality < reqValue) + return false; + } + else + { + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.Quality >= reqValue; + }); + + if (followerCount < 1) + return false; + } + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerEqualLevel: // 146 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)secondaryAsset) + return false; + + if (miscValue1 != 0) + { + Garrison.Follower follower = garrison.GetFollower(miscValue1); + if (follower == null || follower.PacketInfo.FollowerLevel < reqValue) + return false; + } + else + { + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.FollowerLevel >= reqValue; + }); + + if (followerCount < 1) + return false; + } + break; + } + case CriteriaAdditionalCondition.BattlePetSpeciesInTeam: // 151 + { + uint count = 0; + foreach (BattlePetSlot slot in referencePlayer.GetSession().GetBattlePetMgr().GetSlots()) + if (slot.Pet.Species == secondaryAsset) + ++count; + + if (count < reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.BattlePetFamilyInTeam: // 152 + { + uint count = 0; + foreach (BattlePetSlot slot in referencePlayer.GetSession().GetBattlePetMgr().GetSlots()) + { + BattlePetSpeciesRecord species = CliDB.BattlePetSpeciesStorage.LookupByKey(slot.Pet.Species); + if (species != null) + if (species.PetTypeEnum == secondaryAsset) + ++count; + } + + if (count < reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerId: // 157 + { Garrison garrison = referencePlayer.GetGarrison(); if (garrison == null) return false; - Garrison.Follower follower = garrison.GetFollower(miscValue1); - if (follower == null || follower.PacketInfo.Quality != reqValue) + + if (miscValue1 != 0) + { + Garrison.Follower follower = garrison.GetFollower(miscValue1); + if (follower == null || follower.PacketInfo.GarrFollowerID != reqValue) + return false; + } + else + { + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.GarrFollowerID == reqValue; + }); + + if (followerCount < 1) + return false; + } + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerAboveItemLevel: // 168 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null) + return false; + + if (miscValue1 != 0) + { + Garrison.Follower follower = garrison.GetFollower(miscValue1); + if (follower == null || follower.PacketInfo.GarrFollowerID != reqValue) + return false; + } + else + { + uint followerCount = garrison.CountFollowers(follower => + { + return follower.GetItemLevel() >= reqValue; + }); + + if (followerCount < 1) + return false; + } + break; + } + case CriteriaAdditionalCondition.GarrisonFollowersAboveItemLevel: // 169 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + return follower.GetItemLevel() >= secondaryAsset; + }); + + if (followerCount < reqValue) return false; break; } - case CriteriaAdditionalCondition.GarrisonFollowerLevel: // 146 - { - if (!referencePlayer) - return false; - Garrison garrison = referencePlayer.GetGarrison(); - if (garrison == null) - return false; - Garrison.Follower follower = garrison.GetFollower(miscValue1); - if (follower == null || follower.PacketInfo.FollowerLevel < reqValue) - return false; + + case CriteriaAdditionalCondition.GarrisonLevelEqual: // 170 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != GarrisonType.Garrison || garrison.GetSiteLevel().GarrLevel != reqValue) + return false; break; } - case CriteriaAdditionalCondition.GarrisonFollowILvl: // 184 + case CriteriaAdditionalCondition.TargetingCorpse: // 173 + if (referencePlayer.GetTarget().GetHigh() != HighGuid.Corpse) + return false; + break; + case CriteriaAdditionalCondition.GarrisonFollowersLevelEqual: // 175 { - if (!referencePlayer) + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != (GarrisonType)tertiaryAsset) return false; + + uint followerCount = garrison.CountFollowers(follower => + { + return follower.PacketInfo.FollowerLevel >= secondaryAsset; + }); + + if (followerCount < reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.GarrisonFollowerIdInBuilding: // 176 + { + Garrison garrison = referencePlayer.GetGarrison(); + if (garrison == null || garrison.GetGarrisonType() != GarrisonType.Garrison) + return false; + + uint followerCount = garrison.CountFollowers(follower => + { + if (follower.PacketInfo.GarrFollowerID != reqValue) + return false; + + GarrBuildingRecord followerBuilding = CliDB.GarrBuildingStorage.LookupByKey(follower.PacketInfo.CurrentBuildingID); + if (followerBuilding == null) + return false; + + return followerBuilding.BuildingType == secondaryAsset; + }); + + if (followerCount < 1) + return false; + break; + } + case CriteriaAdditionalCondition.WorldPvpArea: // 179 + { + BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(referencePlayer.GetZoneId()); + if (bf == null || bf.GetBattleId() != reqValue) + return false; + break; + } + + case CriteriaAdditionalCondition.GarrisonFollowersItemLevelAbove: // 184 + { Garrison garrison = referencePlayer.GetGarrison(); if (garrison == null) return false; - Garrison.Follower follower = garrison.GetFollower(miscValue1); - if (follower == null || follower.GetItemLevel() < reqValue) + + uint followerCount = garrison.CountFollowers(follower => + { + GarrFollowerRecord garrFollower = CliDB.GarrFollowerStorage.LookupByKey(follower.PacketInfo.GarrFollowerID); + if (garrFollower == null) + return false; + + return follower.GetItemLevel() >= secondaryAsset && garrFollower.GarrFollowerTypeID == tertiaryAsset; + }); + + if (followerCount < reqValue) return false; break; } case CriteriaAdditionalCondition.HonorLevel: // 193 - if (!referencePlayer || referencePlayer.GetHonorLevel() != reqValue) + if (referencePlayer.GetHonorLevel() != reqValue) return false; break; case CriteriaAdditionalCondition.PrestigeLevel: // 194 return false; + case CriteriaAdditionalCondition.ItemModifiedAppearance: // 200 + { + Tuple hasAppearance = referencePlayer.GetSession().GetCollectionMgr().HasItemAppearance(reqValue); + if (!hasAppearance.Item1 || hasAppearance.Item2) + return false; + break; + } + case CriteriaAdditionalCondition.HasCharacterRestrictions: // 203 + { + if (referencePlayer.m_activePlayerData.CharacterRestrictions.Empty()) + return false; + break; + } + case CriteriaAdditionalCondition.QuestInfoId: // 206 + { + Quest quest = Global.ObjectMgr.GetQuestTemplate((uint)miscValue1); + if (quest == null || quest.Id != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.ArtifactAppearanceSetUsed: // 208 + { + for (byte slot = EquipmentSlot.MainHand; slot <= EquipmentSlot.Ranged; ++slot) + { + Item artifact = referencePlayer.GetItemByPos(InventorySlots.Bag0, slot); + if (artifact != null) + { + ArtifactAppearanceRecord artifactAppearance = CliDB.ArtifactAppearanceStorage.LookupByKey(artifact.GetModifier(ItemModifier.ArtifactAppearanceId)); + if (artifactAppearance != null) + if (artifactAppearance.ArtifactAppearanceSetID == reqValue) + return true; + } + } + return false; + } + case CriteriaAdditionalCondition.CurrencyAmountEqual: // 209 + if (referencePlayer.GetCurrency(reqValue) != secondaryAsset) + return false; + break; + case CriteriaAdditionalCondition.ScenarioType: // 211 + { + Scenario scenario = referencePlayer.GetScenario(); + if (scenario == null) + return false; + + if (scenario.GetEntry().Type != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.AccountExpansionEqual: // 212 + if ((uint)referencePlayer.GetSession().GetAccountExpansion() != reqValue) + return false; + break; + case CriteriaAdditionalCondition.AchievementGloballyIncompleted: // 231 + { + AchievementRecord achievement = CliDB.AchievementStorage.LookupByKey(secondaryAsset); + if (achievement == null) + return false; + + if (Global.AchievementMgr.IsRealmCompleted(achievement)) + return false; + break; + } + case CriteriaAdditionalCondition.MainHandVisibleSubclass: // 232 + { + uint itemSubclass = (uint)ItemSubClassWeapon.Fist; + ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(referencePlayer.m_playerData.VisibleItems[EquipmentSlot.MainHand].ItemID); + if (itemTemplate != null) + itemSubclass = itemTemplate.GetSubClass(); + if (itemSubclass != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.OffHandVisibleSubclass: // 233 + { + uint itemSubclass = (uint)ItemSubClassWeapon.Fist; + ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(referencePlayer.m_playerData.VisibleItems[EquipmentSlot.OffHand].ItemID); + if (itemTemplate != null) + itemSubclass = itemTemplate.GetSubClass(); + if (itemSubclass != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.AzeriteItemLevel: // 235 + { + Item heartOfAzeroth = referencePlayer.GetItemByEntry(PlayerConst.ItemIdHeartOfAzeroth); + if (!heartOfAzeroth || heartOfAzeroth.ToAzeriteItem().m_azeriteItemData.Level < reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.SourceDisplayRace: // 252 + { + CreatureDisplayInfoRecord creatureDisplayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(referencePlayer.GetDisplayId()); + if (creatureDisplayInfo == null) + return false; + + CreatureDisplayInfoExtraRecord creatureDisplayInfoExtra = CliDB.CreatureDisplayInfoExtraStorage.LookupByKey(creatureDisplayInfo.ExtendedDisplayInfoID); + if (creatureDisplayInfoExtra == null) + return false; + + if (creatureDisplayInfoExtra.DisplayRaceID != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.TargetDisplayRace: // 253 + { + if (!unit) + return false; + CreatureDisplayInfoRecord creatureDisplayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(unit.GetDisplayId()); + if (creatureDisplayInfo == null) + return false; + + CreatureDisplayInfoExtraRecord creatureDisplayInfoExtra = CliDB.CreatureDisplayInfoExtraStorage.LookupByKey(creatureDisplayInfo.ExtendedDisplayInfoID); + if (creatureDisplayInfoExtra == null) + return false; + + if (creatureDisplayInfoExtra.DisplayRaceID != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.SourceAuraCountEqual: // 255 + if (referencePlayer.GetAuraCount((uint)secondaryAsset) != reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetAuraCountEqual: // 256 + if (!unit || unit.GetAuraCount((uint)secondaryAsset) != reqValue) + return false; + break; + case CriteriaAdditionalCondition.SourceAuraCountGreater: // 257 + if (referencePlayer.GetAuraCount((uint)secondaryAsset) < reqValue) + return false; + break; + case CriteriaAdditionalCondition.TargetAuraCountGreater: // 258 + if (!unit || unit.GetAuraCount((uint)secondaryAsset) < reqValue) + return false; + break; + case CriteriaAdditionalCondition.UnlockedAzeriteEssenceRankLower: // 259 + { + Item heartOfAzeroth = referencePlayer.GetItemByEntry(PlayerConst.ItemIdHeartOfAzeroth); + if (heartOfAzeroth != null) + { + AzeriteItem azeriteItem = heartOfAzeroth.ToAzeriteItem(); + if (azeriteItem != null) + { + foreach (UnlockedAzeriteEssence essence in azeriteItem.m_azeriteItemData.UnlockedEssences) + if (essence.AzeriteEssenceID == reqValue && essence.Rank < secondaryAsset) + return true; + } + } + return false; + } + case CriteriaAdditionalCondition.UnlockedAzeriteEssenceRankEqual: // 260 + { + Item heartOfAzeroth = referencePlayer.GetItemByEntry(PlayerConst.ItemIdHeartOfAzeroth); + if (heartOfAzeroth != null) + { + AzeriteItem azeriteItem = heartOfAzeroth.ToAzeriteItem(); + if (azeriteItem != null) + { + foreach (UnlockedAzeriteEssence essence in azeriteItem.m_azeriteItemData.UnlockedEssences) + if (essence.AzeriteEssenceID == reqValue && essence.Rank == secondaryAsset) + return true; + } + } + return false; + } + case CriteriaAdditionalCondition.UnlockedAzeriteEssenceRankGreater: // 261 + { + Item heartOfAzeroth = referencePlayer.GetItemByEntry(PlayerConst.ItemIdHeartOfAzeroth); + if (heartOfAzeroth != null) + { + AzeriteItem azeriteItem = heartOfAzeroth.ToAzeriteItem(); + if (azeriteItem != null) + { + foreach (UnlockedAzeriteEssence essence in azeriteItem.m_azeriteItemData.UnlockedEssences) + if (essence.AzeriteEssenceID == reqValue && essence.Rank > secondaryAsset) + return true; + } + } + return false; + } + case CriteriaAdditionalCondition.SourceHasAuraEffectIndex: // 262 + if (referencePlayer.GetAuraEffect(reqValue, (uint)secondaryAsset) == null) + return false; + break; + case CriteriaAdditionalCondition.SourceSpecializationRole: // 263 + { + ChrSpecializationRecord spec = CliDB.ChrSpecializationStorage.LookupByKey(referencePlayer.GetPrimarySpecialization()); + if (spec == null || spec.Role != reqValue) + return false; + break; + } + case CriteriaAdditionalCondition.SourceLevel120: // 264 + if (referencePlayer.GetLevel() != 120) + return false; + break; + case CriteriaAdditionalCondition.SelectedAzeriteEssenceRankLower: // 266 + { + Item heartOfAzeroth = referencePlayer.GetItemByEntry(PlayerConst.ItemIdHeartOfAzeroth); + if (heartOfAzeroth != null) + { + AzeriteItem azeriteItem = heartOfAzeroth.ToAzeriteItem(); + if (azeriteItem != null) + { + SelectedAzeriteEssences selectedEssences = azeriteItem.GetSelectedAzeriteEssences(); + if (selectedEssences != null) + { + foreach (UnlockedAzeriteEssence essence in azeriteItem.m_azeriteItemData.UnlockedEssences) + if (essence.AzeriteEssenceID == selectedEssences.AzeriteEssenceID[(int)reqValue] && essence.Rank < secondaryAsset) + return true; + } + } + } + return false; + } + case CriteriaAdditionalCondition.SelectedAzeriteEssenceRankGreater: // 267 + { + Item heartOfAzeroth = referencePlayer.GetItemByEntry(PlayerConst.ItemIdHeartOfAzeroth); + if (heartOfAzeroth != null) + { + AzeriteItem azeriteItem = heartOfAzeroth.ToAzeriteItem(); + if (azeriteItem != null) + { + SelectedAzeriteEssences selectedEssences = azeriteItem.GetSelectedAzeriteEssences(); + if (selectedEssences != null) + { + foreach (UnlockedAzeriteEssence essence in azeriteItem.m_azeriteItemData.UnlockedEssences) + if (essence.AzeriteEssenceID == selectedEssences.AzeriteEssenceID[(int)reqValue] && essence.Rank > secondaryAsset) + return true; + } + } + } + } + return false; + case CriteriaAdditionalCondition.MapOrCosmeticMap: // 280 + { + MapRecord map = referencePlayer.GetMap().GetEntry(); + if (map.Id != reqValue && map.CosmeticParentMapID != reqValue) + return false; + break; + } default: break; } diff --git a/Source/Game/Conditions/ConditionManager.cs b/Source/Game/Conditions/ConditionManager.cs index 7bf3d4d3f..598b57df1 100644 --- a/Source/Game/Conditions/ConditionManager.cs +++ b/Source/Game/Conditions/ConditionManager.cs @@ -1674,7 +1674,7 @@ namespace Game return result; } - static uint GetPlayerConditionLfgValue(Player player, PlayerConditionLfgStatus status) + public static uint GetPlayerConditionLfgValue(Player player, PlayerConditionLfgStatus status) { Group group = player.GetGroup(); if (group = null) diff --git a/Source/Game/Entities/Item/AzeriteItem.cs b/Source/Game/Entities/Item/AzeriteItem.cs index d412ee122..555146a54 100644 --- a/Source/Game/Entities/Item/AzeriteItem.cs +++ b/Source/Game/Entities/Item/AzeriteItem.cs @@ -28,7 +28,7 @@ namespace Game.Entities { public class AzeriteItem : Item { - AzeriteItemData m_azeriteItemData; + public AzeriteItemData m_azeriteItemData; public AzeriteItem() { @@ -208,6 +208,15 @@ namespace Game.Entities owner.SendPacket(xpGain); } + public SelectedAzeriteEssences GetSelectedAzeriteEssences() + { + foreach (SelectedAzeriteEssences essences in m_azeriteItemData.SelectedEssences) + if (essences.Enabled != 0) + return essences; + + return null; + } + public override void BuildValuesCreate(WorldPacket data, Player target) { UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target); diff --git a/Source/Game/Entities/Object/Update/UpdateField.cs b/Source/Game/Entities/Object/Update/UpdateField.cs index ed24db394..7611a2ccc 100644 --- a/Source/Game/Entities/Object/Update/UpdateField.cs +++ b/Source/Game/Entities/Object/Update/UpdateField.cs @@ -263,6 +263,11 @@ namespace Game.Entities _updateMask[block] &= ~(uint)UpdateMask.GetBlockFlag(index); } + public bool Empty() + { + return _values.Empty(); + } + public int Size() { return _values.Count; diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index 1a15aadc5..c09a3903a 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -656,9 +656,9 @@ namespace Game.Entities public class SelectedAzeriteEssences : BaseUpdateData { - UpdateField SpecializationID = new UpdateField(0, 1); - UpdateField Enabled = new UpdateField(0, 2); - UpdateFieldArray AzeriteEssenceID = new UpdateFieldArray(3, 3, 4); + public UpdateField SpecializationID = new UpdateField(0, 1); + public UpdateField Enabled = new UpdateField(0, 2); + public UpdateFieldArray AzeriteEssenceID = new UpdateFieldArray(3, 3, 4); public SelectedAzeriteEssences() : base(7) { } diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index aab9d84eb..b0f92459b 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -585,6 +585,7 @@ namespace Game.Entities case TypeId.Item: case TypeId.Container: case TypeId.AzeriteItem: + case TypeId.AzeriteEmpoweredItem: { Item item = (Item)questGiver; Global.ScriptMgr.OnQuestAccept(this, item, quest); @@ -1122,7 +1123,7 @@ namespace Game.Entities } if (quest.QuestSortID > 0) - UpdateCriteria(CriteriaTypes.CompleteQuestsInZone, (ulong)quest.QuestSortID); + UpdateCriteria(CriteriaTypes.CompleteQuestsInZone, quest.Id); UpdateCriteria(CriteriaTypes.CompleteQuestCount); UpdateCriteria(CriteriaTypes.CompleteQuest, quest.Id); diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index b8b114118..3c3f6e346 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -1392,6 +1392,13 @@ namespace Game.Entities return playerCurrency.WeeklyQuantity; } + public uint GetTrackedCurrencyCount(uint id) + { + if (!_currencyStorage.ContainsKey(id)) + return 0; + + return _currencyStorage[id].TrackedQuantity; + } //Action Buttons - CUF Profile public void SaveCUFProfile(byte id, CUFProfile profile) { _CUFProfiles[id] = profile; } diff --git a/Source/Game/Garrisons/Garrisons.cs b/Source/Game/Garrisons/Garrisons.cs index df69a21c0..0b285c691 100644 --- a/Source/Game/Garrisons/Garrisons.cs +++ b/Source/Game/Garrisons/Garrisons.cs @@ -25,6 +25,7 @@ using Game.Maps; using Game.Network.Packets; using System; using System.Collections.Generic; +using System.Linq; namespace Game.Garrisons { @@ -301,8 +302,8 @@ namespace Game.Garrisons return _owner.GetTeam() == Team.Horde ? GarrisonFactionIndex.Horde : GarrisonFactionIndex.Alliance; } - GarrisonType GetGarrisonType() { return GarrisonType.Garrison; } - GarrSiteLevelRecord GetSiteLevel() { return _siteLevel; } + public GarrisonType GetGarrisonType() { return GarrisonType.Garrison; } + public GarrSiteLevelRecord GetSiteLevel() { return _siteLevel; } public ICollection GetPlots() { @@ -314,7 +315,7 @@ namespace Game.Garrisons return _plots.LookupByKey(garrPlotInstanceId); } - bool HasBlueprint(uint garrBuildingId) { return _knownBuildings.Contains(garrBuildingId); } + public bool HasBlueprint(uint garrBuildingId) { return _knownBuildings.Contains(garrBuildingId); } public void LearnBlueprint(uint garrBuildingId) { @@ -519,7 +520,7 @@ namespace Game.Garrisons return _followers.LookupByKey(dbId); } - uint CountFollowers(Predicate predicate) + public uint CountFollowers(Predicate predicate) { uint count = 0; foreach (var pair in _followers) @@ -868,12 +869,20 @@ namespace Game.Garrisons public class Follower { + public GarrisonFollower PacketInfo = new GarrisonFollower(); + public uint GetItemLevel() { return (PacketInfo.ItemLevelWeapon + PacketInfo.ItemLevelArmor) / 2; } - public GarrisonFollower PacketInfo = new GarrisonFollower(); + public bool HasAbility(uint garrAbilityId) + { + return PacketInfo.AbilityID.Any(garrAbility => + { + return garrAbility.Id == garrAbilityId; + }); + } } } } diff --git a/Source/Game/Scenarios/Scenario.cs b/Source/Game/Scenarios/Scenario.cs index a6ae549f0..a08efa780 100644 --- a/Source/Game/Scenarios/Scenario.cs +++ b/Source/Game/Scenarios/Scenario.cs @@ -140,6 +140,11 @@ namespace Game.Scenarios return true; } + public ScenarioRecord GetEntry() + { + return _data.Entry; + } + ScenarioStepState GetStepState(ScenarioStepRecord step) { if (!_stepStates.ContainsKey(step)) @@ -334,7 +339,7 @@ namespace Game.Scenarios public virtual void Update(uint diff) { } public void SetStepState(ScenarioStepRecord step, ScenarioStepState state) { _stepStates[step] = state; } - ScenarioStepRecord GetStep() + public ScenarioStepRecord GetStep() { return _currentstep; }