From 3a890782b5d29bf7073ce2eb4eb178ae208edc08 Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Tue, 16 Dec 2025 13:57:09 -0500 Subject: [PATCH] Core: Updated to 11.2.5.63704 Port From (https://github.com/TrinityCore/TrinityCore/commit/53068a94e88991ae7196fb247df4b7ca2e47e554) --- .../Networking/Services/Authentication.cs | 12 +- Source/Framework/Constants/AccountConst.cs | 11 +- Source/Framework/Constants/CliDBConst.cs | 12 +- Source/Framework/Constants/ItemConst.cs | 28 + Source/Framework/Constants/Network/Opcodes.cs | 889 +++---- Source/Framework/Constants/SharedConst.cs | 1193 +++++----- .../Framework/Constants/SupportSystemConst.cs | 4 + .../Database/Databases/CharacterDatabase.cs | 12 +- .../Database/Databases/HotfixDatabase.cs | 60 +- Source/Framework/IO/ByteBuffer.cs | 23 + Source/Game/Achievements/CriteriaHandler.cs | 2106 ++++++++--------- Source/Game/Calendar/CalendarManager.cs | 2 +- Source/Game/Conditions/ConditionManager.cs | 2 +- Source/Game/DataStorage/CliDB.cs | 8 + Source/Game/DataStorage/Structs/A_Records.cs | 2 +- Source/Game/DataStorage/Structs/B_Records.cs | 2 +- Source/Game/DataStorage/Structs/C_Records.cs | 10 +- Source/Game/DataStorage/Structs/I_Records.cs | 29 +- Source/Game/DataStorage/Structs/P_Records.cs | 6 +- Source/Game/DataStorage/Structs/S_Records.cs | 10 +- Source/Game/DataStorage/Structs/T_Records.cs | 17 +- Source/Game/DataStorage/Structs/U_Records.cs | 1 + .../Game/Entities/AreaTrigger/AreaTrigger.cs | 2 +- Source/Game/Entities/Creature/Trainer.cs | 2 +- .../Entities/Object/Update/UpdateField.cs | 193 +- .../Entities/Object/Update/UpdateFields.cs | 518 ++-- Source/Game/Entities/Object/WorldObject.cs | 6 + Source/Game/Entities/Player/Player.DB.cs | 39 +- Source/Game/Entities/Player/Player.Quest.cs | 6 +- Source/Game/Entities/Player/Player.Talents.cs | 162 +- Source/Game/Entities/Unit/Unit.cs | 4 +- Source/Game/Guilds/Guild.cs | 3 +- Source/Game/Handlers/AuthenticationHandler.cs | 14 + Source/Game/Handlers/CharacterHandler.cs | 10 +- Source/Game/Handlers/TraitHandler.cs | 14 +- .../Networking/Packets/CalendarPackets.cs | 12 +- .../Networking/Packets/CharacterPackets.cs | 33 +- .../Networking/Packets/CombatLogPackets.cs | 4 +- .../Game/Networking/Packets/GuildPackets.cs | 8 +- Source/Game/Networking/Packets/ItemPackets.cs | 4 +- Source/Game/Networking/Packets/LFGPackets.cs | 4 +- Source/Game/Networking/Packets/MailPackets.cs | 15 +- Source/Game/Networking/Packets/MiscPackets.cs | 6 +- .../Networking/Packets/MovementPackets.cs | 31 +- Source/Game/Networking/Packets/NPCPackets.cs | 8 +- .../Game/Networking/Packets/PartyPackets.cs | 4 +- Source/Game/Networking/Packets/PetPackets.cs | 8 +- .../Networking/Packets/PetitionPackets.cs | 4 +- .../Game/Networking/Packets/QuestPackets.cs | 10 +- .../Game/Networking/Packets/SpellPackets.cs | 47 +- .../Game/Networking/Packets/SystemPackets.cs | 51 +- .../Game/Networking/Packets/TalentPackets.cs | 4 + .../Game/Networking/Packets/TokenPackets.cs | 6 +- .../Game/Networking/Packets/TraitPackets.cs | 5 + Source/Game/Spells/Auras/Aura.cs | 3 + Source/Game/Spells/SpellEffects.cs | 22 +- Source/Game/Spells/TraitManager.cs | 8 +- 57 files changed, 3079 insertions(+), 2630 deletions(-) diff --git a/Source/BNetServer/Networking/Services/Authentication.cs b/Source/BNetServer/Networking/Services/Authentication.cs index a42bb0b3d..568ab1854 100644 --- a/Source/BNetServer/Networking/Services/Authentication.cs +++ b/Source/BNetServer/Networking/Services/Authentication.cs @@ -186,10 +186,16 @@ namespace BNetServer.Networking if (!authed) return BattlenetRpcErrorCode.Denied; - if (request.Program != 0x576F57) + switch (request.Program) { - Log.outDebug(LogFilter.Session, $"[Battlenet::HandleGenerateWebCredentials] {GetClientInfo()} attempted to generate web cretentials with game other than WoW (using {(request.Program >> 24) & 0xFF}{(request.Program >> 16) & 0xFF}{(request.Program >> 8) & 0xFF}{request.Program & 0xFF})!"); - return BattlenetRpcErrorCode.BadProgram; + case 0x417070: // App + case 0x576F57: // WoW + break; + default: + { + Log.outDebug(LogFilter.Session, $"[Battlenet::HandleGenerateWebCredentials] {GetClientInfo()} attempted to generate web cretentials with game other than WoW (using {(request.Program >> 24) & 0xFF}{(request.Program >> 16) & 0xFF}{(request.Program >> 8) & 0xFF}{request.Program & 0xFF})!"); + return BattlenetRpcErrorCode.BadProgram; + } } PreparedStatement stmt = LoginDatabase.GetPreparedStatement(LoginStatements.SEL_BNET_EXISTING_AUTHENTICATION_BY_ID); diff --git a/Source/Framework/Constants/AccountConst.cs b/Source/Framework/Constants/AccountConst.cs index 9b320445d..40ea0e66a 100644 --- a/Source/Framework/Constants/AccountConst.cs +++ b/Source/Framework/Constants/AccountConst.cs @@ -22,12 +22,15 @@ namespace Framework.Constants PerCharacterEditModeCache = 14, GlobalFrontendChatSettings = 15, GlobalCharacterListOrder = 16, + GlobalCooldownManager = 17, + PerCharacterCooldownManager2 = 18, + GlobalShop2PendingOrders = 19, - Max = 17, + Max = 20, - AllAccountDataCacheMask = 0x0001FFFFu, - GlobalCacheMask = 0x0001A515u, - PerCharacterCacheMask = 0x00005AEAu + AllAccountDataCacheMask = 0x000FFFFFu, + GlobalCacheMask = 0x000BA515u, + PerCharacterCacheMask = 0x00045AEAu } public enum TutorialAction diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index 22d2caffd..fd64b5a7d 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -2609,7 +2609,8 @@ namespace Framework.Constants { Gold = 0, CurrencyTypesBased = 1, - TraitSourced = 2 + TraitSourced = 2, + TraitSourcedPlayerDataElement = 3, } public enum TraitEdgeType @@ -2633,7 +2634,8 @@ namespace Framework.Constants SpendDiamond = 6, ProfPath = 7, ProfPerk = 8, - ProfPathUnlock = 9 + ProfPathUnlock = 9, + SpendInfinite = 10 } [Flags] @@ -2658,6 +2660,12 @@ namespace Framework.Constants Multiply = 1 } + public enum TraitSystemVariationType + { + None = 0, + Spec = 1 + } + [Flags] public enum TraitTreeFlag { diff --git a/Source/Framework/Constants/ItemConst.cs b/Source/Framework/Constants/ItemConst.cs index e6a4e63a1..7a3546876 100644 --- a/Source/Framework/Constants/ItemConst.cs +++ b/Source/Framework/Constants/ItemConst.cs @@ -477,6 +477,9 @@ namespace Framework.Constants OverrideDescriptionColor = 45, // Overrides color of item description and upgrade track if TimeEvent from value[1] has passed OverrideCannotTradeBop = 46, BondingWithPriority = 47, + ItemOffsetCurve = 48, + ScalingConfigAndReqLevel = 49, + ScalingConfig = 51, } public enum ItemCollectionType : byte @@ -489,6 +492,10 @@ namespace Framework.Constants RuneforgeLegendaryAbility = 5, TransmogIllusion = 6, WarbandScene = 7, + Room = 8, + ExteriorFixture = 9, + RoomTheme = 10, + RoomMaterial = 11 } public enum ItemContext : byte @@ -658,6 +665,27 @@ namespace Framework.Constants TournamentRealm2 = 162, TournamentRealm3 = 163, TournamentRealm4 = 164, + Warbound1 = 165, + Warbound2 = 166, + Warbound3 = 167, + Warbound4 = 168, + Warbound5 = 169, + Warbound6 = 170, + Warbound7 = 171, + Warbound8 = 172, + Warbound9 = 173, + Warbound10 = 174, + Warbound11 = 175, + Warbound12 = 176, + Warbound13 = 177, + Warbound14 = 178, + Warbound15 = 179, + Warbound16 = 180, + Warbound17 = 181, + Warbound18 = 182, + Warbound19 = 183, + Warbound20 = 184, + Endeavors = 185, Max } diff --git a/Source/Framework/Constants/Network/Opcodes.cs b/Source/Framework/Constants/Network/Opcodes.cs index a5c84f05a..1a52c5551 100644 --- a/Source/Framework/Constants/Network/Opcodes.cs +++ b/Source/Framework/Constants/Network/Opcodes.cs @@ -5,38 +5,38 @@ namespace Framework.Constants { public enum ClientOpcodes : uint { - AbandonNpeResponse = 0x2f0299, + AbandonNpeResponse = 0x2f029a, AcceptGuildInvite = 0x340029, - AcceptReturningPlayerPrompt = 0x2f025a, - AcceptSocialContract = 0x340174, + AcceptReturningPlayerPrompt = 0x2f025b, + AcceptSocialContract = 0x340176, AcceptTrade = 0x2f0004, AcceptWargameInvite = 0x34000c, - AccountBankDepositMoney = 0x2f02dc, - AccountBankWithdrawMoney = 0x2f02dd, - AccountNotificationAcknowledged = 0x340160, + AccountBankDepositMoney = 0x2f02dd, + AccountBankWithdrawMoney = 0x2f02de, + AccountNotificationAcknowledged = 0x340162, AccountStoreBeginPurchaseOrRefund = 0x3400c0, - ActivateSoulbind = 0x2f0288, + ActivateSoulbind = 0x2f0289, ActivateTaxi = 0x30003e, AddonList = 0x340004, - AddAccountCosmetic = 0x2f0171, + AddAccountCosmetic = 0x2f0172, AddBattlenetFriend = 0x340086, - AddFriend = 0x3400fe, - AddIgnore = 0x340102, - AddToy = 0x2f0170, - AdventureJournalOpenQuest = 0x2f00b3, - AdventureJournalUpdateSuggestions = 0x2f028b, - AdventureMapStartQuest = 0x2f022b, + AddFriend = 0x3400ff, + AddIgnore = 0x340103, + AddToy = 0x2f0171, + AdventureJournalOpenQuest = 0x2f00b4, + AdventureJournalUpdateSuggestions = 0x2f028c, + AdventureMapStartQuest = 0x2f022c, AlterAppearance = 0x30008d, AreaSpiritHealerQuery = 0x300043, AreaSpiritHealerQueue = 0x300044, - AreaTrigger = 0x2f0086, + AreaTrigger = 0x2f0087, ArtifactAddPower = 0x2f0056, ArtifactSetAppearance = 0x2f0058, - AssignEquipmentSetSpec = 0x2f00bf, - AttackStop = 0x2f011d, - AttackSwing = 0x2f011c, - AuctionableTokenSell = 0x340114, - AuctionableTokenSellAtMarketPrice = 0x340115, + AssignEquipmentSetSpec = 0x2f00c0, + AttackStop = 0x2f011e, + AttackSwing = 0x2f011d, + AuctionableTokenSell = 0x340115, + AuctionableTokenSellAtMarketPrice = 0x340116, AuctionBrowseQuery = 0x300061, AuctionCancelCommoditiesPurchase = 0x300069, AuctionConfirmCommoditiesPurchase = 0x300068, @@ -52,46 +52,46 @@ namespace Framework.Constants AuctionReplicateItems = 0x30005f, AuctionSellCommodity = 0x30006a, AuctionSellItem = 0x30005d, - AuctionSetFavoriteItem = 0x340161, + AuctionSetFavoriteItem = 0x340163, AuthContinuedSession = 0x350002, AuthSession = 0x350001, AutobankItem = 0x310003, AutostoreBankItem = 0x310002, - AutoDepositAccountBank = 0x2f02e6, - AutoDepositCharacterBank = 0x2f02ee, + AutoDepositAccountBank = 0x2f02e7, + AutoDepositCharacterBank = 0x2f02ef, AutoEquipItem = 0x310004, AutoEquipItemSlot = 0x310009, AutoGuildBankItem = 0x300048, AutoStoreBagItem = 0x310005, AutoStoreGuildBankItem = 0x300051, - AzeriteEmpoweredItemSelectPower = 0x2f0256, - AzeriteEmpoweredItemViewed = 0x2f0237, - AzeriteEssenceActivateEssence = 0x2f0258, - AzeriteEssenceUnlockMilestone = 0x2f0257, + AzeriteEmpoweredItemSelectPower = 0x2f0257, + AzeriteEmpoweredItemViewed = 0x2f0238, + AzeriteEssenceActivateEssence = 0x2f0259, + AzeriteEssenceUnlockMilestone = 0x2f0258, BankerActivate = 0x300046, BattlefieldLeave = 0x2f001f, BattlefieldList = 0x2f002a, BattlefieldPort = 0x3000c3, - BattlemasterHello = 0x2f018f, + BattlemasterHello = 0x2f0190, BattlemasterJoin = 0x3000ba, BattlemasterJoinArena = 0x3000bb, BattlemasterJoinBrawl = 0x3000c1, BattlemasterJoinRatedBgBlitz = 0x3000bd, BattlemasterJoinRatedSoloShuffle = 0x3000bc, BattlemasterJoinSkirmish = 0x3000be, - BattlenetChallengeResponse = 0x340101, - BattlenetRequest = 0x340122, + BattlenetChallengeResponse = 0x340102, + BattlenetRequest = 0x340123, BattlePayAckFailedResponse = 0x3400fb, - BattlePayCancelOpenCheckout = 0x34013e, + BattlePayCancelOpenCheckout = 0x340140, BattlePayConfirmPurchaseResponse = 0x3400fa, BattlePayDistributionAssignToTarget = 0x3400f1, - BattlePayDistributionAssignVas = 0x340164, + BattlePayDistributionAssignVas = 0x340166, BattlePayGetProductList = 0x3400e8, BattlePayGetPurchaseList = 0x3400e9, - BattlePayOpenCheckout = 0x340137, - BattlePayRequestPriceInfo = 0x340133, + BattlePayOpenCheckout = 0x340139, + BattlePayRequestPriceInfo = 0x340134, BattlePayStartPurchase = 0x3400f9, - BattlePayStartVasPurchase = 0x340120, + BattlePayStartVasPurchase = 0x340121, BattlePetClearFanfare = 0x290002, BattlePetDeletePet = 0x34004f, BattlePetDeletePetCheat = 0x340050, @@ -101,20 +101,20 @@ namespace Framework.Constants BattlePetSetBattleSlot = 0x340057, BattlePetSetFlags = 0x34005a, BattlePetSummon = 0x340053, - BattlePetUpdateDisplayNotify = 0x2f0090, - BattlePetUpdateNotify = 0x2f008f, + BattlePetUpdateDisplayNotify = 0x2f0091, + BattlePetUpdateNotify = 0x2f0090, BeginTrade = 0x2f0001, BinderActivate = 0x300045, BlackMarketBidOnItem = 0x3000cb, BlackMarketOpen = 0x3000c9, BlackMarketRequestItems = 0x3000ca, - BonusRoll = 0x2f0259, + BonusRoll = 0x2f025a, BugReport = 0x3400b1, BusyTrade = 0x2f0002, BuyAccountBankTab = 0x300123, BuyBackItem = 0x300037, BuyItem = 0x300036, - CageBattlePet = 0x2f00a3, + CageBattlePet = 0x2f00a4, CalendarAddEvent = 0x3400a9, CalendarCommunityInvite = 0x34009d, CalendarComplain = 0x3400a5, @@ -132,23 +132,23 @@ namespace Framework.Constants CalendarUpdateEvent = 0x3400aa, CancelAura = 0x2f005a, CancelAutoRepeatSpell = 0x30007f, - CancelCast = 0x2f0177, - CancelChannelling = 0x2f0138, - CancelGrowthAura = 0x2f0140, - CancelMasterLootRoll = 0x2f00cc, + CancelCast = 0x2f0178, + CancelChannelling = 0x2f0139, + CancelGrowthAura = 0x2f0141, + CancelMasterLootRoll = 0x2f00cd, CancelModSpeedNoControlAuras = 0x2f0059, - CancelMountAura = 0x2f0153, + CancelMountAura = 0x2f0154, CancelQueuedSpell = 0x2f002b, CancelTempEnchantment = 0x30008a, CancelTrade = 0x2f0006, CanDuel = 0x34008e, - CanRedeemTokenForBalance = 0x340132, - CastSpell = 0x2f0174, + CanRedeemTokenForBalance = 0x340133, + CastSpell = 0x2f0175, ChallengeModeRequestLeaders = 0x2c0002, - ChangeBagSlotFlag = 0x2f0211, - ChangeBankBagSlotFlag = 0x2f0212, - ChangeMonumentAppearance = 0x2f01f2, - ChangeRealmTicket = 0x340127, + ChangeBagSlotFlag = 0x2f0212, + ChangeBankBagSlotFlag = 0x2f0213, + ChangeMonumentAppearance = 0x2f01f3, + ChangeRealmTicket = 0x340128, ChangeSubGroup = 0x340078, CharacterCheckUpgrade = 0x3400f4, CharacterRenameRequest = 0x3400ef, @@ -201,36 +201,36 @@ namespace Framework.Constants ChatSendCautionaryChatMessage = 0x2b0009, ChatUnregisterAllAddonPrefixes = 0x2b0006, CheckCharacterNameAvailability = 0x340071, - CheckIsAdventureMapPoiValid = 0x2f010e, - ChoiceResponse = 0x2f017c, - ChromieTimeSelectExpansion = 0x2f0287, - ClaimWeeklyReward = 0x2f0264, - ClassTalentsDeleteConfig = 0x2f02c1, - ClassTalentsNotifyEmptyConfig = 0x2f00c3, - ClassTalentsNotifyValidationFailed = 0x2f02c3, - ClassTalentsRenameConfig = 0x2f02c0, - ClassTalentsRequestNewConfig = 0x2f02bf, - ClassTalentsSetStarterBuildActive = 0x2f02c4, - ClassTalentsSetUsesSharedActionBars = 0x2f00c2, + CheckIsAdventureMapPoiValid = 0x2f010f, + ChoiceResponse = 0x2f017d, + ChromieTimeSelectExpansion = 0x2f0288, + ClaimWeeklyReward = 0x2f0265, + ClassTalentsDeleteConfig = 0x2f02c2, + ClassTalentsNotifyEmptyConfig = 0x2f00c4, + ClassTalentsNotifyValidationFailed = 0x2f02c4, + ClassTalentsRenameConfig = 0x2f02c1, + ClassTalentsRequestNewConfig = 0x2f02c0, + ClassTalentsSetStarterBuildActive = 0x2f02c5, + ClassTalentsSetUsesSharedActionBars = 0x2f00c3, ClearNewAppearance = 0x290005, ClearRaidMarker = 0x2f0052, ClearTradeItem = 0x2f0008, ClientPortGraveyard = 0x3000c5, CloseInteraction = 0x300025, - CloseQuestChoice = 0x2f017d, - CloseRuneforgeInteraction = 0x2f028f, - CloseTraitSystemInteraction = 0x2f02c5, - ClubFinderApplicationResponse = 0x340149, - ClubFinderGetApplicantsList = 0x340147, - ClubFinderPost = 0x340144, - ClubFinderRequestClubsData = 0x34014b, - ClubFinderRequestClubsList = 0x340145, - ClubFinderRequestMembershipToClub = 0x340146, - ClubFinderRequestPendingClubsList = 0x34014a, - ClubFinderRequestSubscribedClubPostingIds = 0x34014c, - ClubFinderRespondToApplicant = 0x340148, - ClubFinderWhisperApplicantRequest = 0x340167, - ClubPresenceSubscribe = 0x340124, + CloseQuestChoice = 0x2f017e, + CloseRuneforgeInteraction = 0x2f0290, + CloseTraitSystemInteraction = 0x2f02c6, + ClubFinderApplicationResponse = 0x34014b, + ClubFinderGetApplicantsList = 0x340149, + ClubFinderPost = 0x340146, + ClubFinderRequestClubsData = 0x34014d, + ClubFinderRequestClubsList = 0x340147, + ClubFinderRequestMembershipToClub = 0x340148, + ClubFinderRequestPendingClubsList = 0x34014c, + ClubFinderRequestSubscribedClubPostingIds = 0x34014e, + ClubFinderRespondToApplicant = 0x34014a, + ClubFinderWhisperApplicantRequest = 0x340169, + ClubPresenceSubscribe = 0x340125, CollectionItemSetFavorite = 0x34005d, CommentatorEnable = 0x34001c, CommentatorEnterInstance = 0x340020, @@ -238,31 +238,32 @@ namespace Framework.Constants CommentatorGetMapInfo = 0x34001d, CommentatorGetPlayerCooldowns = 0x34001f, CommentatorGetPlayerInfo = 0x34001e, - CommentatorSpectate = 0x340165, + CommentatorSpectate = 0x340167, CommentatorStartWargame = 0x34001b, - CommerceTokenGetCount = 0x340112, - CommerceTokenGetLog = 0x34011c, - CommerceTokenGetMarketPrice = 0x340113, + CommerceTokenGetCount = 0x340113, + CommerceTokenGetLog = 0x34011d, + CommerceTokenGetMarketPrice = 0x340114, Complaint = 0x340098, CompleteCinematic = 0x3000e3, CompleteMovie = 0x300075, ConfirmArtifactRespec = 0x2f0057, - ConfirmProfessionRespec = 0x2f00c6, - ConfirmRespecWipe = 0x2f00c5, + ConfirmProfessionRespec = 0x2f00c7, + ConfirmRespecWipe = 0x2f00c6, ConnectToFailed = 0x340000, - ConsumableTokenBuy = 0x340117, - ConsumableTokenBuyAtMarketPrice = 0x340118, - ConsumableTokenCanVeteranBuy = 0x340116, - ConsumableTokenRedeem = 0x34011a, - ConsumableTokenRedeemConfirmation = 0x34011b, - ContentTrackingStartTracking = 0x2f02d5, - ContentTrackingStopTracking = 0x2f02d6, + ConsumableTokenBuy = 0x340118, + ConsumableTokenBuyAtMarketPrice = 0x340119, + ConsumableTokenCanVeteranBuy = 0x340117, + ConsumableTokenRedeem = 0x34011b, + ConsumableTokenRedeemConfirmation = 0x34011c, + ContentTrackingStartTracking = 0x2f02d6, + ContentTrackingStopTracking = 0x2f02d7, ContributionContribute = 0x3000fb, ContributionLastUpdateRequest = 0x3000fc, ConversationCinematicReady = 0x3000e5, ConversationLineStarted = 0x3000e4, - ConvertItemToBindToAccount = 0x2f02e5, + ConvertItemToBindToAccount = 0x2f02e6, ConvertRaid = 0x34007a, + ConvertTimerunningCharacter = 0x34018c, CovenantRenownRequestCatchupState = 0x30010f, CraftingOrderCancel = 0x30011b, CraftingOrderClaim = 0x300118, @@ -276,15 +277,15 @@ namespace Framework.Constants CraftingOrderReportPlayer = 0x30011d, CraftingOrderUpdateIgnoreList = 0x30011e, CreateCharacter = 0x340070, - CreateShipment = 0x2f01db, + CreateShipment = 0x2f01dc, DbQueryBulk = 0x340010, DeclineGuildInvites = 0x3000b7, DeclinePetition = 0x3000d2, DeleteEquipmentSet = 0x3000a3, DelveTeleportOut = 0x30012b, - DelFriend = 0x3400ff, - DelIgnore = 0x340103, - DestroyItem = 0x2f016a, + DelFriend = 0x340100, + DelIgnore = 0x340104, + DestroyItem = 0x2f016b, DfBootPlayerVote = 0x340044, DfConfirmExpandSearch = 0x340036, DfGetJoinStatus = 0x340042, @@ -297,65 +298,65 @@ namespace Framework.Constants DfTeleport = 0x340045, DiscardedTimeSyncAcks = 0x32005e, DismissCritter = 0x300091, - DoCountdown = 0x340143, - DoMasterLootRoll = 0x2f00cb, + DoCountdown = 0x340145, + DoMasterLootRoll = 0x2f00cc, DoReadyCheck = 0x34005e, DuelResponse = 0x30007a, - EjectPassenger = 0x2f0103, + EjectPassenger = 0x2f0104, Emote = 0x3000df, EnableNagle = 0x350007, EnableTaxiNode = 0x30003c, - EngineSurvey = 0x340111, + EngineSurvey = 0x340112, EnterEncryptedModeAck = 0x350003, EnumCharacters = 0x340014, - EnumCharactersDeletedByClient = 0x34010b, + EnumCharactersDeletedByClient = 0x34010c, FarSight = 0x300080, GameEventDebugDisable = 0x2f005e, GameEventDebugEnable = 0x2f005d, GameObjReportUse = 0x300087, GameObjUse = 0x300086, - GarrisonAddFollowerHealth = 0x2f01d6, - GarrisonAssignFollowerToBuilding = 0x2f01bc, - GarrisonCancelConstruction = 0x2f01a9, - GarrisonCheckUpgradeable = 0x2f020d, - GarrisonCompleteMission = 0x2f01ff, - GarrisonFullyHealAllFollowers = 0x2f01d7, - GarrisonGenerateRecruits = 0x2f01bf, - GarrisonGetClassSpecCategoryInfo = 0x2f01ce, - GarrisonGetMapData = 0x2f01d5, - GarrisonGetMissionReward = 0x2f022f, - GarrisonLearnTalent = 0x2f01ca, - GarrisonMissionBonusRoll = 0x2f0201, - GarrisonPurchaseBuilding = 0x2f01a5, - GarrisonRecruitFollower = 0x2f01c1, - GarrisonRemoveFollower = 0x2f01f6, - GarrisonRemoveFollowerFromBuilding = 0x2f01bd, - GarrisonRenameFollower = 0x2f01be, - GarrisonRequestBlueprintAndSpecializationData = 0x2f01a4, - GarrisonRequestShipmentInfo = 0x2f01d9, - GarrisonResearchTalent = 0x2f01c2, - GarrisonSetBuildingActive = 0x2f01a6, - GarrisonSetFollowerFavorite = 0x2f01ba, - GarrisonSetFollowerInactive = 0x2f01b2, - GarrisonSetRecruitmentPreferences = 0x2f01c0, - GarrisonSocketTalent = 0x2f029c, - GarrisonStartMission = 0x2f01fe, - GarrisonSwapBuildings = 0x2f01aa, + GarrisonAddFollowerHealth = 0x2f01d7, + GarrisonAssignFollowerToBuilding = 0x2f01bd, + GarrisonCancelConstruction = 0x2f01aa, + GarrisonCheckUpgradeable = 0x2f020e, + GarrisonCompleteMission = 0x2f0200, + GarrisonFullyHealAllFollowers = 0x2f01d8, + GarrisonGenerateRecruits = 0x2f01c0, + GarrisonGetClassSpecCategoryInfo = 0x2f01cf, + GarrisonGetMapData = 0x2f01d6, + GarrisonGetMissionReward = 0x2f0230, + GarrisonLearnTalent = 0x2f01cb, + GarrisonMissionBonusRoll = 0x2f0202, + GarrisonPurchaseBuilding = 0x2f01a6, + GarrisonRecruitFollower = 0x2f01c2, + GarrisonRemoveFollower = 0x2f01f7, + GarrisonRemoveFollowerFromBuilding = 0x2f01be, + GarrisonRenameFollower = 0x2f01bf, + GarrisonRequestBlueprintAndSpecializationData = 0x2f01a5, + GarrisonRequestShipmentInfo = 0x2f01da, + GarrisonResearchTalent = 0x2f01c3, + GarrisonSetBuildingActive = 0x2f01a7, + GarrisonSetFollowerFavorite = 0x2f01bb, + GarrisonSetFollowerInactive = 0x2f01b3, + GarrisonSetRecruitmentPreferences = 0x2f01c1, + GarrisonSocketTalent = 0x2f029d, + GarrisonStartMission = 0x2f01ff, + GarrisonSwapBuildings = 0x2f01ab, GenerateRandomCharacterName = 0x340013, GetAccountCharacterList = 0x3400e3, - GetAccountNotifications = 0x34015f, - GetGarrisonInfo = 0x2f019f, + GetAccountNotifications = 0x340161, + GetGarrisonInfo = 0x2f01a0, GetItemPurchaseData = 0x3000cd, - GetLandingPageShipments = 0x2f01da, - GetMirrorImageData = 0x2f016e, + GetLandingPageShipments = 0x2f01db, + GetMirrorImageData = 0x2f016f, GetPvpOptionsEnabled = 0x34001a, - GetRafAccountInfo = 0x34014d, - GetRegionwideCharacterRestrictionAndMailData = 0x340190, - GetRemainingGameTime = 0x340119, - GetTrophyList = 0x2f01ef, - GetUndeleteCharacterCooldownStatus = 0x34010d, - GetVasAccountCharacterList = 0x34011e, - GetVasTransferTargetRealmList = 0x34011f, + GetRafAccountInfo = 0x34014f, + GetRegionwideCharacterRestrictionAndMailData = 0x340192, + GetRemainingGameTime = 0x34011a, + GetTrophyList = 0x2f01f0, + GetUndeleteCharacterCooldownStatus = 0x34010e, + GetVasAccountCharacterList = 0x34011f, + GetVasTransferTargetRealmList = 0x340120, GmTicketAcknowledgeSurvey = 0x3400bc, GmTicketGetCaseStatus = 0x3400bb, GmTicketGetSystemStatus = 0x3400ba, @@ -408,7 +409,7 @@ namespace Framework.Constants GuildUpdateInfoText = 0x2d0016, GuildUpdateMotdText = 0x2d0015, HearthAndResurrect = 0x30009f, - HideQuestChoice = 0x2f017e, + HideQuestChoice = 0x2f017f, HotfixRequest = 0x340011, IgnoreTrade = 0x2f0003, InitiateRolePoll = 0x340006, @@ -416,68 +417,68 @@ namespace Framework.Constants Inspect = 0x3000c7, InstanceAbandonVoteResponse = 0x340061, InstanceLockResponse = 0x3000a4, - IslandQueue = 0x2f0260, + IslandQueue = 0x2f0261, ItemPurchaseRefund = 0x3000ce, - ItemTextQuery = 0x2f020e, - JoinPetBattleQueue = 0x2f008d, + ItemTextQuery = 0x2f020f, + JoinPetBattleQueue = 0x2f008e, JoinRatedBattleground = 0x2f0025, KeepAlive = 0x3400ab, - KeyboundOverride = 0x2f00e1, + KeyboundOverride = 0x2f00e2, LatencyReport = 0x35000d, LearnPvpTalents = 0x3000fa, LearnTalents = 0x3000f8, LeaveGroup = 0x340075, - LeavePetBattleQueue = 0x2f008e, + LeavePetBattleQueue = 0x2f008f, LfgListApplyToGroup = 0x34003b, LfgListCancelApplication = 0x34003c, LfgListDeclineApplicant = 0x34003d, LfgListGetStatus = 0x340039, LfgListInviteApplicant = 0x34003e, LfgListInviteResponse = 0x34003f, - LfgListJoin = 0x2f0254, + LfgListJoin = 0x2f0255, LfgListLeave = 0x340038, LfgListSearch = 0x34003a, - LfgListUpdateRequest = 0x2f0255, + LfgListUpdateRequest = 0x2f0256, ListInventory = 0x300033, LiveRegionAccountRestore = 0x3400e6, LiveRegionCharacterCopy = 0x3400e5, LiveRegionGetAccountCharacterList = 0x3400e4, LiveRegionKeyBindingsCopy = 0x3400e7, LoadingScreenNotify = 0x340024, - LoadSelectedTrophy = 0x2f01f0, - LobbyMatchmakerAbandonQueue = 0x340172, - LobbyMatchmakerAcceptPartyInvite = 0x340169, - LobbyMatchmakerCreateCharacter = 0x34017b, - LobbyMatchmakerEnterQueue = 0x340170, - LobbyMatchmakerLeaveParty = 0x34016c, - LobbyMatchmakerPartyInvite = 0x340168, - LobbyMatchmakerPartyUninvite = 0x34016b, - LobbyMatchmakerQueuePropsalResponse = 0x340171, - LobbyMatchmakerRejectPartyInvite = 0x34016a, - LobbyMatchmakerSetPartyPlaylistEntry = 0x34016d, - LobbyMatchmakerSetPlayerReady = 0x34016e, + LoadSelectedTrophy = 0x2f01f1, + LobbyMatchmakerAbandonQueue = 0x340174, + LobbyMatchmakerAcceptPartyInvite = 0x34016b, + LobbyMatchmakerCreateCharacter = 0x34017d, + LobbyMatchmakerEnterQueue = 0x340172, + LobbyMatchmakerLeaveParty = 0x34016e, + LobbyMatchmakerPartyInvite = 0x34016a, + LobbyMatchmakerPartyUninvite = 0x34016d, + LobbyMatchmakerQueuePropsalResponse = 0x340173, + LobbyMatchmakerRejectPartyInvite = 0x34016c, + LobbyMatchmakerSetPartyPlaylistEntry = 0x34016f, + LobbyMatchmakerSetPlayerReady = 0x340170, LogoutCancel = 0x300070, LogoutInstant = 0x300071, LogoutLobbyMatchmaker = 0x300122, LogoutRequest = 0x30006f, LogDisconnect = 0x350005, LogStreamingError = 0x350009, - LootItem = 0x2f00c9, - LootMoney = 0x2f00c8, - LootRelease = 0x2f00cd, - LootRoll = 0x2f00ce, - LootUnit = 0x2f00c7, + LootItem = 0x2f00ca, + LootMoney = 0x2f00c9, + LootRelease = 0x2f00ce, + LootRoll = 0x2f00cf, + LootUnit = 0x2f00c8, LowLevelRaid1 = 0x3400ce, LowLevelRaid2 = 0x3000ab, MailCreateTextItem = 0x3000d9, - MailDelete = 0x2f00e3, + MailDelete = 0x2f00e4, MailGetList = 0x3000d4, MailMarkAsRead = 0x3000d8, MailReturnToSender = 0x340081, MailTakeItem = 0x3000d6, MailTakeMoney = 0x3000d5, - MakeContitionalAppearancePermanent = 0x2f00e4, - MasterLootItem = 0x2f00ca, + MakeContitionalAppearancePermanent = 0x2f00e5, + MasterLootItem = 0x2f00cb, MergeGuildBankItemWithGuildBankItem = 0x300052, MergeGuildBankItemWithItem = 0x30004f, MergeItemWithGuildBankItem = 0x30004d, @@ -485,7 +486,7 @@ namespace Framework.Constants MissileTrajectoryCollision = 0x2f0036, MountClearFanfare = 0x290003, MountSetFavorite = 0x34005c, - MountSpecialAnim = 0x2f0154, + MountSpecialAnim = 0x2f0155, MoveAddImpulseAck = 0x32006d, MoveApplyInertiaAck = 0x32006b, MoveApplyMovementForceAck = 0x320031, @@ -578,29 +579,29 @@ namespace Framework.Constants MoveUpdateFallSpeed = 0x320036, MoveWaterWalkAck = 0x320039, MythicPlusRequestMapStats = 0x2c0001, - NeutralPlayerSelectFaction = 0x2f0083, + NeutralPlayerSelectFaction = 0x2f0084, NextCinematicCamera = 0x3000e2, ObjectUpdateFailed = 0x2f002c, ObjectUpdateRescued = 0x2f002d, - OfferPetition = 0x2f0286, + OfferPetition = 0x2f0287, OpeningCinematic = 0x3000e1, - OpenItem = 0x2f020f, - OpenMissionNpc = 0x2f01d0, - OpenShipmentNpc = 0x2f01d8, - OpenTradeskillNpc = 0x2f01e3, + OpenItem = 0x2f0210, + OpenMissionNpc = 0x2f01d1, + OpenShipmentNpc = 0x2f01d9, + OpenTradeskillNpc = 0x2f01e4, OptOutOfLoot = 0x30008e, OverrideScreenFlash = 0x3000b8, PartyInvite = 0x340030, PartyInviteResponse = 0x340032, PartyUninvite = 0x340073, - PerformItemInteraction = 0x2f00ec, - PerksProgramItemsRefreshed = 0x2f02ae, - PerksProgramRequestCartCheckout = 0x2f02b1, + PerformItemInteraction = 0x2f00ed, + PerksProgramItemsRefreshed = 0x2f02af, + PerksProgramRequestCartCheckout = 0x2f02b2, PerksProgramRequestPendingRewards = 0x290012, - PerksProgramRequestPurchase = 0x2f02b0, - PerksProgramRequestRefund = 0x2f02b2, - PerksProgramSetFrozenVendorItem = 0x2f02b3, - PerksProgramStatusRequest = 0x2f02af, + PerksProgramRequestPurchase = 0x2f02b1, + PerksProgramRequestRefund = 0x2f02b3, + PerksProgramSetFrozenVendorItem = 0x2f02b4, + PerksProgramStatusRequest = 0x2f02b0, PetitionBuy = 0x30005a, PetitionRenameGuild = 0x3400f7, PetitionShowList = 0x300059, @@ -608,18 +609,18 @@ namespace Framework.Constants PetAbandon = 0x30001e, PetAbandonByNumber = 0x30001f, PetAction = 0x30001c, - PetBattleFinalNotify = 0x2f0092, + PetBattleFinalNotify = 0x2f0093, PetBattleInput = 0x34006d, - PetBattleQueueProposeMatchResult = 0x2f00e2, - PetBattleQuitNotify = 0x2f0091, + PetBattleQueueProposeMatchResult = 0x2f00e3, + PetBattleQuitNotify = 0x2f0092, PetBattleReplaceFrontPet = 0x34006e, - PetBattleRequestPvp = 0x2f008b, - PetBattleRequestUpdate = 0x2f008c, - PetBattleRequestWild = 0x2f0089, - PetBattleScriptErrorNotify = 0x2f0093, - PetBattleWildLocationFail = 0x3d008a, + PetBattleRequestPvp = 0x2f008c, + PetBattleRequestUpdate = 0x2f008d, + PetBattleRequestWild = 0x2f008a, + PetBattleScriptErrorNotify = 0x2f0094, + PetBattleWildLocationFail = 0x2f008b, PetCancelAura = 0x300020, - PetCastSpell = 0x2f0173, + PetCastSpell = 0x2f0174, PetRename = 0x3400b0, PetSetAction = 0x30001b, PetSpellAutocast = 0x300021, @@ -628,32 +629,32 @@ namespace Framework.Constants PlayerLogin = 0x340016, PushQuestToParty = 0x300031, PvpLogData = 0x2f0028, - QueryBattlePetName = 0x2f0147, + QueryBattlePetName = 0x2f0148, QueryCorpseLocationFromClient = 0x34008c, QueryCorpseTransport = 0x34008d, QueryCountdownTimer = 0x2f0055, - QueryCreature = 0x2f0141, - QueryGameObject = 0x2f0142, - QueryGarrisonPetName = 0x2f0148, + QueryCreature = 0x2f0142, + QueryGameObject = 0x2f0143, + QueryGarrisonPetName = 0x2f0149, QueryGuildInfo = 0x3400b6, QueryInspectAchievements = 0x300098, QueryNextMailTime = 0x3000d7, - QueryNpcText = 0x2f0143, - QueryPageText = 0x2f0145, - QueryPetition = 0x2f0149, - QueryPetName = 0x2f0146, + QueryNpcText = 0x2f0144, + QueryPageText = 0x2f0146, + QueryPetition = 0x2f014a, + QueryPetName = 0x2f0147, QueryPlayerNames = 0x35000e, QueryPlayerNamesForCommunity = 0x35000c, QueryPlayerNameByCommunityId = 0x35000b, QueryQuestCompletionNpcs = 0x2f0021, - QueryQuestInfo = 0x2f0144, + QueryQuestInfo = 0x2f0145, QueryQuestItemUsability = 0x2f0022, QueryRealmName = 0x3400b5, QueryScenarioPoi = 0x340082, - QuerySelectedWowLabsArea = 0x2f02ea, + QuerySelectedWowLabsArea = 0x2f02eb, QueryTime = 0x30006e, - QueryTreasurePicker = 0x2f0232, - QueryWowLabsAreaInfo = 0x2f02eb, + QueryTreasurePicker = 0x2f0233, + QueryWowLabsAreaInfo = 0x2f02ec, QuestConfirmAccept = 0x300030, QuestGiverAcceptQuest = 0x30002a, QuestGiverChooseReward = 0x30002c, @@ -667,114 +668,118 @@ namespace Framework.Constants QuestLogRemoveQuest = 0x3000cc, QuestPoiQuery = 0x3400dd, QuestPushResult = 0x300032, - QuestSessionBeginResponse = 0x2f0278, - QuestSessionRequestStart = 0x2f0277, - QuestSessionRequestStop = 0x340158, + QuestSessionBeginResponse = 0x2f0279, + QuestSessionRequestStart = 0x2f0278, + QuestSessionRequestStop = 0x34015a, QueuedMessagesEnd = 0x350008, - QuickJoinAutoAcceptRequests = 0x340130, - QuickJoinRequestInvite = 0x34012f, - QuickJoinRequestInviteWithConfirmation = 0x34015d, - QuickJoinRespondToInvite = 0x34012e, - QuickJoinSignalToastDisplayed = 0x34012d, + QuickJoinAutoAcceptRequests = 0x340131, + QuickJoinRequestInvite = 0x340130, + QuickJoinRequestInviteWithConfirmation = 0x34015f, + QuickJoinRespondToInvite = 0x34012f, + QuickJoinSignalToastDisplayed = 0x34012e, RafClaimActivityReward = 0x30009c, - RafClaimNextReward = 0x34014e, - RafGenerateRecruitmentLink = 0x340150, - RafUpdateRecruitmentInfo = 0x34014f, + RafClaimNextReward = 0x340150, + RafGenerateRecruitmentLink = 0x340152, + RafUpdateRecruitmentInfo = 0x340151, RandomRoll = 0x340080, ReadyCheckResponse = 0x34005f, - ReadItem = 0x2f0210, + ReadItem = 0x2f0211, + RecentAllyRequestData = 0x340197, + RecentAllySetNote = 0x340198, ReclaimCorpse = 0x300073, - RemoveNewItem = 0x2f0236, - RemoveRafRecruit = 0x340151, + RemoveNewItem = 0x2f0237, + RemoveRafRecruit = 0x340153, ReorderCharacters = 0x340015, RepairItem = 0x300084, - ReplaceTrophy = 0x2f01f1, + ReplaceTrophy = 0x2f01f2, RepopRequest = 0x3000c4, ReportPvpPlayerAfk = 0x30008c, - ReportServerLag = 0x2f0270, - ReportStuckInCombat = 0x2f0271, + ReportServerLag = 0x2f0271, + ReportStuckInCombat = 0x2f0272, RequestAccountData = 0x3400c2, - RequestAreaPoiUpdate = 0x2f0234, + RequestAreaPoiUpdate = 0x2f0235, RequestBattlefieldStatus = 0x340008, RequestCemeteryList = 0x2f0023, RequestCharacterGuildFollowInfo = 0x3400b7, - RequestCovenantCallings = 0x2f0262, + RequestCovenantCallings = 0x2f0263, RequestCrowdControlSpell = 0x3000c8, RequestCurrencyDataForAccountCharacters = 0x290019, - RequestGarrisonTalentWorldQuestUnlocks = 0x2f029b, + RequestGarrisonTalentWorldQuestUnlocks = 0x2f029c, RequestGuildPartyState = 0x2f0054, RequestGuildRewardsList = 0x2f0053, - RequestLatestSplashScreen = 0x2f0272, - RequestLfgListBlacklist = 0x2f017f, - RequestMythicPlusAffixes = 0x2f00b7, - RequestMythicPlusSeasonData = 0x2f00b8, - RequestPartyEligibilityForDelveTiers = 0x2f02e9, + RequestLatestSplashScreen = 0x2f0273, + RequestLfgListBlacklist = 0x2f0180, + RequestMythicPlusAffixes = 0x2f00b8, + RequestMythicPlusSeasonData = 0x2f00b9, + RequestPartyEligibilityForDelveTiers = 0x2f02ea, RequestPartyJoinUpdates = 0x340023, RequestPartyMemberStats = 0x34007f, RequestPetInfo = 0x300022, - RequestPlayedTime = 0x2f014c, + RequestPlayedTime = 0x2f014d, RequestPvpRewards = 0x2f0041, RequestRaidInfo = 0x3400f8, RequestRatedPvpInfo = 0x34000f, - RequestRealmGuildMasterInfo = 0x340193, - RequestScheduledAreaPoiUpdate = 0x2f0235, + RequestRealmGuildMasterInfo = 0x340195, + RequestScheduledAreaPoiUpdate = 0x2f0236, RequestScheduledPvpInfo = 0x2f0042, RequestStabledPets = 0x300023, RequestStoreFrontInfoUpdate = 0x29001e, - RequestVehicleExit = 0x2f00fe, - RequestVehicleNextSeat = 0x2f0100, - RequestVehiclePrevSeat = 0x2f00ff, - RequestVehicleSwitchSeat = 0x2f0101, - RequestWeeklyRewards = 0x2f0265, - RequestWorldQuestUpdate = 0x2f0233, - ResetChallengeMode = 0x2f00b5, - ResetChallengeModeCheat = 0x2f00b6, + RequestSurvey = 0x2f02fd, + RequestVehicleExit = 0x2f00ff, + RequestVehicleNextSeat = 0x2f0101, + RequestVehiclePrevSeat = 0x2f0100, + RequestVehicleSwitchSeat = 0x2f0102, + RequestWeeklyRewards = 0x2f0266, + RequestWorldQuestUpdate = 0x2f0234, + ResetChallengeMode = 0x2f00b6, + ResetChallengeModeCheat = 0x2f00b7, ResetInstances = 0x340094, ResurrectResponse = 0x3400af, - RevertMonumentAppearance = 0x2f01f3, - RideVehicleInteract = 0x2f0102, - RpeResetCharacter = 0x34017e, - SaveAccountDataExport = 0x340178, + RevertMonumentAppearance = 0x2f01f4, + RideVehicleInteract = 0x2f0103, + RpeResetCharacter = 0x340180, + SaveAccountDataExport = 0x34017a, SaveCufProfiles = 0x2f0037, SaveEquipmentSet = 0x3000a2, - SaveGuildEmblem = 0x2f0184, - SavePersonalEmblem = 0x2f0185, - ScenePlaybackCanceled = 0x2f00de, - ScenePlaybackComplete = 0x2f00dd, - SceneTriggerEvent = 0x2f00df, - SeamlessTransferComplete = 0x2f02d8, - SelectWowLabsArea = 0x2f02ec, + SaveGuildEmblem = 0x2f0185, + SavePersonalEmblem = 0x2f0186, + ScenePlaybackCanceled = 0x2f00df, + ScenePlaybackComplete = 0x2f00de, + SceneTriggerEvent = 0x2f00e0, + SeamlessTransferComplete = 0x2f02d9, + SelectWowLabsArea = 0x2f02ed, SelfRes = 0x3000cf, SellAllJunkItems = 0x300035, SellItem = 0x300034, - SendCharacterClubInvitation = 0x340126, - SendContactList = 0x3400fd, + SendCharacterClubInvitation = 0x340127, + SendContactList = 0x3400fe, SendMail = 0x340026, - SendPingUnit = 0x2f02da, - SendPingWorldPoint = 0x2f02db, + SendPingUnit = 0x2f02db, + SendPingWorldPoint = 0x2f02dc, SendTextEmote = 0x300019, ServerTimeOffsetRequest = 0x3400c9, - SetupWarbandGroups = 0x34018c, + SetupWarbandGroups = 0x34018e, SetActionBarToggles = 0x3000d0, SetActionButton = 0x340062, SetActiveMover = 0x320059, - SetAdvancedCombatLogging = 0x2f0192, + SetAdvancedCombatLogging = 0x2f0193, + SetAllowRecentAlliesSeeLocation = 0x2f02fe, SetAssistantLeader = 0x34007b, - SetBackpackAutosortDisabled = 0x2f0213, - SetBackpackSellJunkDisabled = 0x2f0214, - SetBankAutosortDisabled = 0x2f0215, - SetContactNotes = 0x340100, + SetBackpackAutosortDisabled = 0x2f0214, + SetBackpackSellJunkDisabled = 0x2f0215, + SetBankAutosortDisabled = 0x2f0216, + SetContactNotes = 0x340101, SetCurrencyFlags = 0x2f0015, - SetDifficultyId = 0x2f00e0, + SetDifficultyId = 0x2f00e1, SetDungeonDifficulty = 0x3400ae, - SetEmpowerMinHoldStagePercent = 0x2f013b, + SetEmpowerMinHoldStagePercent = 0x2f013c, SetEveryoneIsAssistant = 0x340046, - SetExcludedChatCensorSources = 0x340131, + SetExcludedChatCensorSources = 0x340132, SetFactionAtWar = 0x300076, SetFactionInactive = 0x300078, SetFactionNotAtWar = 0x300077, SetGameEventDebugViewState = 0x2f0065, - SetInsertItemsLeftToRight = 0x2f0217, + SetInsertItemsLeftToRight = 0x2f0218, SetLootMethod = 0x340074, SetLootSpecialization = 0x3000dd, SetPartyAssignment = 0x34007d, @@ -784,35 +789,35 @@ namespace Framework.Constants SetPetSpecialization = 0x2f0013, SetPlayerDeclinedNames = 0x3400b4, SetPreferredCemetery = 0x2f0024, - SetPvp = 0x2f0189, - SetRaidDifficulty = 0x340109, + SetPvp = 0x2f018a, + SetRaidDifficulty = 0x34010a, SetRestrictPingsToAssistants = 0x340047, SetRole = 0x340005, SetSavedInstanceExtend = 0x3400b2, SetSelection = 0x3000c6, SetSheathed = 0x30001a, - SetSortBagsRightToLeft = 0x2f0216, + SetSortBagsRightToLeft = 0x2f0217, SetTaxiBenchmarkMode = 0x30008b, - SetTitle = 0x2f0152, + SetTitle = 0x2f0153, SetTradeCurrency = 0x2f000a, SetTradeGold = 0x2f0009, SetTradeItem = 0x2f0007, - SetUsingPartyGarrison = 0x2f01d2, - SetWarMode = 0x2f018a, + SetUsingPartyGarrison = 0x2f01d3, + SetWarMode = 0x2f018b, SetWatchedFaction = 0x300079, ShowTradeSkill = 0x3400f0, SignPetition = 0x3000d1, SilencePartyTalker = 0x34007e, - SocialContractRequest = 0x340173, + SocialContractRequest = 0x340175, SocketGems = 0x300083, - SortAccountBankBags = 0x2f02de, - SortBags = 0x2f0218, - SortBankBags = 0x2f0219, - SpawnTrackingUpdate = 0x2f0167, - SpectateChange = 0x2f02d1, + SortAccountBankBags = 0x2f02df, + SortBags = 0x2f0219, + SortBankBags = 0x2f021a, + SpawnTrackingUpdate = 0x2f0168, + SpectateChange = 0x2f02d2, SpellClick = 0x300027, - SpellEmpowerRelease = 0x2f0139, - SpellEmpowerRestart = 0x2f013a, + SpellEmpowerRelease = 0x2f013a, + SpellEmpowerRestart = 0x2f013b, SpiritHealerActivate = 0x300042, SplitGuildBankItem = 0x300053, SplitGuildBankItemToInventory = 0x300050, @@ -825,7 +830,7 @@ namespace Framework.Constants StartWarGame = 0x34000a, StoreGuildBankItem = 0x300049, SubmitUserFeedback = 0x3400c1, - SubscriptionInterstitialResponse = 0x2f0290, + SubscriptionInterstitialResponse = 0x2f0291, SummonResponse = 0x340096, SupportTicketSubmitComplaint = 0x340072, SurrenderArena = 0x2f0020, @@ -836,7 +841,7 @@ namespace Framework.Constants SwapItem = 0x310006, SwapItemWithGuildBankItem = 0x30004a, SwapSubGroups = 0x340079, - TabardVendorActivate = 0x2f0186, + TabardVendorActivate = 0x2f0187, TalkToGossip = 0x300024, TaxiNodeStatusQuery = 0x30003b, TaxiQueryAvailableNodes = 0x30003d, @@ -846,51 +851,51 @@ namespace Framework.Constants TimeSyncResponseDropped = 0x32005c, TimeSyncResponseFailed = 0x32005b, ToggleDifficulty = 0x340083, - TogglePvp = 0x2f0188, + TogglePvp = 0x2f0189, TotemDestroyed = 0x300090, ToyClearFanfare = 0x290004, - TradeSkillSetFavorite = 0x2f0231, + TradeSkillSetFavorite = 0x2f0232, TrainerBuySpell = 0x300041, TrainerList = 0x300040, - TraitsCommitConfig = 0x2f02b9, - TraitsTalentTestUnlearnSpells = 0x2f02b7, - TransferCurrencyFromAccountCharacter = 0x2f02e7, + TraitsCommitConfig = 0x2f02ba, + TraitsTalentTestUnlearnSpells = 0x2f02b8, + TransferCurrencyFromAccountCharacter = 0x2f02e8, TransmogrifyItems = 0x2f0043, TurnInPetition = 0x3000d3, - Tutorial = 0x34010a, - UiMapQuestLinesRequest = 0x2f0261, + Tutorial = 0x34010b, + UiMapQuestLinesRequest = 0x2f0262, UnacceptTrade = 0x2f0005, - UndeleteCharacter = 0x34010c, + UndeleteCharacter = 0x34010d, UnlearnSkill = 0x30007d, UnlearnSpecialization = 0x2f0051, - UpdateAadcStatus = 0x340163, + UpdateAadcStatus = 0x340165, UpdateAccountBankTabSettings = 0x30012a, UpdateAccountData = 0x3400c3, - UpdateAreaTriggerVisual = 0x2f0176, + UpdateAreaTriggerVisual = 0x2f0177, UpdateClientSettings = 0x340090, - UpdateCraftingNpcRecipes = 0x2f01e4, + UpdateCraftingNpcRecipes = 0x2f01e5, UpdateMissileTrajectory = 0x320060, UpdateRaidTarget = 0x34007c, - UpdateSpellVisual = 0x2f0175, - UpdateVasPurchaseStates = 0x340121, - UpgradeGarrison = 0x2f019a, - UpgradeRuneforgeLegendary = 0x2f028e, + UpdateSpellVisual = 0x2f0176, + UpdateVasPurchaseStates = 0x340122, + UpgradeGarrison = 0x2f019b, + UpgradeRuneforgeLegendary = 0x2f028f, UsedFollow = 0x2f0032, - UseCritterItem = 0x2f0108, + UseCritterItem = 0x2f0109, UseEquipmentSet = 0x310001, - UseItem = 0x2f016f, - UseToy = 0x2f0172, - VasCheckTransferOk = 0x340136, - VasGetQueueMinutes = 0x340135, - VasGetServiceStatus = 0x340134, + UseItem = 0x2f0170, + UseToy = 0x2f0173, + VasCheckTransferOk = 0x340138, + VasGetQueueMinutes = 0x340137, + VasGetServiceStatus = 0x340136, ViolenceLevel = 0x2f0030, - VoiceChannelSttTokenRequest = 0x34013a, - VoiceChatJoinChannel = 0x34013b, - VoiceChatLogin = 0x340139, + VoiceChannelSttTokenRequest = 0x34013c, + VoiceChatJoinChannel = 0x34013d, + VoiceChatLogin = 0x34013b, Warden3Data = 0x340018, Who = 0x3400ad, WhoIs = 0x3400ac, - WorldLootObjectClick = 0x2f02d4, + WorldLootObjectClick = 0x2f02d5, WorldPortResponse = 0x340025, WrapItem = 0x310000, @@ -900,20 +905,20 @@ namespace Framework.Constants public enum ServerOpcodes : uint { AbortNewWorld = 0x360030, - AccountCharacterCurrencyLists = 0x360346, - AccountConversionStateUpdate = 0x36034b, - AccountCosmeticAdded = 0x3602ff, - AccountCriteriaUpdate = 0x3602e7, + AccountCharacterCurrencyLists = 0x360347, + AccountConversionStateUpdate = 0x36034c, + AccountCosmeticAdded = 0x360300, + AccountCriteriaUpdate = 0x3602e8, AccountDataTimes = 0x3601a8, - AccountExportResponse = 0x360337, - AccountItemCollectionData = 0x360351, + AccountExportResponse = 0x360338, + AccountItemCollectionData = 0x360352, AccountMountRemoved = 0x360047, AccountMountUpdate = 0x360046, - AccountNotificationsResponse = 0x3602fe, - AccountStoreCurrencyUpdate = 0x360320, - AccountStoreFrontUpdate = 0x360321, - AccountStoreItemStateChanged = 0x360322, - AccountStoreResult = 0x360323, + AccountNotificationsResponse = 0x3602ff, + AccountStoreCurrencyUpdate = 0x360321, + AccountStoreFrontUpdate = 0x360322, + AccountStoreItemStateChanged = 0x360323, + AccountStoreResult = 0x360324, AccountToyUpdate = 0x360048, AccountTransmogSetFavoritesUpdate = 0x36004c, AccountTransmogUpdate = 0x36004b, @@ -931,8 +936,8 @@ namespace Framework.Constants AddLossOfControl = 0x36010f, AddRunePower = 0x360156, AdjustSplineDuration = 0x360069, - AdvancedCombatLog = 0x3602fc, - AdventureJournalDataResponse = 0x3602f7, + AdvancedCombatLog = 0x3602fd, + AdventureJournalDataResponse = 0x3602f8, AeLootTargets = 0x3600b5, AeLootTargetAck = 0x3600b6, AiReaction = 0x360153, @@ -940,7 +945,7 @@ namespace Framework.Constants AllAccountCriteria = 0x360005, AllAchievementData = 0x360004, AllGuildAchievements = 0x420000, - ApplyMountEquipmentResult = 0x3602d4, + ApplyMountEquipmentResult = 0x3602d5, ArchaeologySurveryCast = 0x36001d, AreaPoiUpdateResponse = 0x4a0018, AreaSpiritHealerTime = 0x3601dc, @@ -965,14 +970,14 @@ namespace Framework.Constants AuctionableTokenSellConfirmRequired = 0x36026b, AuctionClosedNotification = 0x360190, AuctionCommandResult = 0x36018d, - AuctionDisableNewPostings = 0x360324, - AuctionFavoriteList = 0x3602ee, - AuctionGetCommodityQuoteResult = 0x3602e6, + AuctionDisableNewPostings = 0x360325, + AuctionFavoriteList = 0x3602ef, + AuctionGetCommodityQuoteResult = 0x3602e7, AuctionHelloResponse = 0x36018b, - AuctionListBiddedItemsResult = 0x3602e5, - AuctionListBucketsResult = 0x3602e1, - AuctionListItemsResult = 0x3602e2, - AuctionListOwnedItemsResult = 0x3602e4, + AuctionListBiddedItemsResult = 0x3602e6, + AuctionListBucketsResult = 0x3602e2, + AuctionListItemsResult = 0x3602e3, + AuctionListOwnedItemsResult = 0x3602e5, AuctionOutbidNotification = 0x36018f, AuctionOwnerBidNotification = 0x360191, AuctionReplicateResponse = 0x36018c, @@ -983,10 +988,10 @@ namespace Framework.Constants AuthFailed = 0x360000, AuthResponse = 0x360001, AvailableHotfixes = 0x3a0001, - BackpackDefaultSizeChanged = 0x360325, + BackpackDefaultSizeChanged = 0x360326, BagCleanupFinished = 0x4e0007, BarberShopResult = 0x36015b, - BatchPresenceSubscription = 0x3602c5, + BatchPresenceSubscription = 0x3602c6, BattlefieldList = 0x3c0005, BattlefieldPortDenied = 0x3c000b, BattlefieldStatusActive = 0x3c0001, @@ -1013,7 +1018,7 @@ namespace Framework.Constants BattlePayConfirmPurchase = 0x360220, BattlePayDeliveryEnded = 0x360214, BattlePayDeliveryStarted = 0x360213, - BattlePayDistributionAssignVasResponse = 0x360304, + BattlePayDistributionAssignVasResponse = 0x360305, BattlePayDistributionUnrevoked = 0x360211, BattlePayDistributionUpdate = 0x360212, BattlePayGetDistributionListResponse = 0x360210, @@ -1021,7 +1026,7 @@ namespace Framework.Constants BattlePayGetPurchaseListResponse = 0x36020f, BattlePayMountDelivered = 0x360215, BattlePayPurchaseUpdate = 0x36021f, - BattlePayStartCheckout = 0x3602b9, + BattlePayStartCheckout = 0x3602ba, BattlePayStartDistributionAssignToTargetResponse = 0x36021d, BattlePayStartPurchaseResponse = 0x36021c, BattlePayValidatePurchaseResponse = 0x3602ad, @@ -1045,8 +1050,8 @@ namespace Framework.Constants BossKill = 0x3c002b, BreakTarget = 0x3c0016, BroadcastAchievement = 0x3b0012, - BroadcastSummonCast = 0x3602c7, - BroadcastSummonResponse = 0x3602c8, + BroadcastSummonCast = 0x3602c8, + BroadcastSummonResponse = 0x3602c9, BuyFailed = 0x360164, BuySucceeded = 0x360163, CacheInfo = 0x3a000f, @@ -1085,6 +1090,9 @@ namespace Framework.Constants CapturePointRemoved = 0x3c0008, CastFailed = 0x4d0048, CasRefreshRemoteData = 0x360115, + CatalogShopLicenseData = 0x3602ae, + CatalogShopObtainLicense = 0x360358, + CatalogShopOpenCheckoutResult = 0x360353, CautionaryChannelMessage = 0x3b0009, CautionaryChatMessage = 0x3b0008, ChainMissileBounce = 0x360061, @@ -1131,8 +1139,8 @@ namespace Framework.Constants CheckAbandonNpe = 0x4a0023, CheckCharacterNameAvailabilityResult = 0x36001b, CheckWargameEntry = 0x360027, - ChromieTimeSelectExpansionSuccess = 0x3602f1, - ClaimRafRewardResponse = 0x3602d8, + ChromieTimeSelectExpansionSuccess = 0x3602f2, + ClaimRafRewardResponse = 0x3602d9, ClearAllSpellCharges = 0x4d0016, ClearBossEmotes = 0x360054, ClearCooldown = 0x360158, @@ -1142,13 +1150,13 @@ namespace Framework.Constants ClearTarget = 0x3c0022, ClearTreasurePickerCache = 0x4b0022, CloseArtifactForge = 0x36023b, - ClubFinderErrorMessage = 0x3602d0, - ClubFinderGetClubPostingIdsResponse = 0x3602d3, - ClubFinderLookupClubPostingsList = 0x3602d1, - ClubFinderResponseCharacterApplicationList = 0x3602ce, - ClubFinderResponsePostRecruitmentMessage = 0x3602d2, - ClubFinderUpdateApplications = 0x3602cf, - ClubFinderWhisperApplicantResponse = 0x360310, + ClubFinderErrorMessage = 0x3602d1, + ClubFinderGetClubPostingIdsResponse = 0x3602d4, + ClubFinderLookupClubPostingsList = 0x3602d2, + ClubFinderResponseCharacterApplicationList = 0x3602cf, + ClubFinderResponsePostRecruitmentMessage = 0x3602d3, + ClubFinderUpdateApplications = 0x3602d0, + ClubFinderWhisperApplicantResponse = 0x360311, CoinRemoved = 0x3600b4, CombatEventFailed = 0x3c0019, CommentatorMapInfo = 0x3601a4, @@ -1169,9 +1177,9 @@ namespace Framework.Constants ConsumableTokenRedeemConfirmRequired = 0x360272, ConsumableTokenRedeemResponse = 0x360273, ContactList = 0x360222, - ContributionLastUpdateResponse = 0x3602b2, + ContributionLastUpdateResponse = 0x3602b3, ControlUpdate = 0x3600e4, - ConvertItemsToCurrencyValue = 0x3602fa, + ConvertItemsToCurrencyValue = 0x3602fb, CooldownCheat = 0x3601d5, CooldownEvent = 0x360157, CorpseLocation = 0x3600eb, @@ -1179,27 +1187,27 @@ namespace Framework.Constants CorpseTransportQuery = 0x3601b0, CovenantCallingsAvailabilityResponse = 0x4b0024, CovenantPreviewOpenNpc = 0x360294, - CovenantRenownSendCatchupState = 0x3602fb, - CraftingHouseHelloResponse = 0x360331, - CraftingOrderCancelResult = 0x36032d, - CraftingOrderClaimResult = 0x360329, - CraftingOrderCraftResult = 0x36032b, - CraftingOrderCreateResult = 0x360327, - CraftingOrderFulfillResult = 0x36032c, - CraftingOrderListOrdersResponse = 0x360328, - CraftingOrderNpcRewardInfo = 0x360333, - CraftingOrderRejectResult = 0x36032f, - CraftingOrderReleaseResult = 0x36032a, - CraftingOrderUpdateState = 0x360332, - CraftEnchantResult = 0x360330, + CovenantRenownSendCatchupState = 0x3602fc, + CraftingHouseHelloResponse = 0x360332, + CraftingOrderCancelResult = 0x36032e, + CraftingOrderClaimResult = 0x36032a, + CraftingOrderCraftResult = 0x36032c, + CraftingOrderCreateResult = 0x360328, + CraftingOrderFulfillResult = 0x36032d, + CraftingOrderListOrdersResponse = 0x360329, + CraftingOrderNpcRewardInfo = 0x360334, + CraftingOrderRejectResult = 0x360330, + CraftingOrderReleaseResult = 0x36032b, + CraftingOrderUpdateState = 0x360333, + CraftEnchantResult = 0x360331, CreateChar = 0x36019e, CreateShipmentResponse = 0x360233, - CreatorVisualsOverride = 0x360336, + CreatorVisualsOverride = 0x360337, CriteriaDeleted = 0x360184, CriteriaUpdate = 0x36017e, CrossedInebriationThreshold = 0x36015f, - CurrencyTransferLog = 0x360348, - CurrencyTransferResult = 0x360347, + CurrencyTransferLog = 0x360349, + CurrencyTransferResult = 0x360348, CustomLoadScreen = 0x360064, DailyQuestsReset = 0x4b0000, DamageCalcLog = 0x4d0054, @@ -1209,7 +1217,7 @@ namespace Framework.Constants DefenseMessage = 0x3b000c, DeleteChar = 0x36019f, DeleteExpiredMissionsResult = 0x400022, - DelvesAccountDataElementChanged = 0x36034d, + DelvesAccountDataElementChanged = 0x36034e, DestroyArenaUnit = 0x3601de, DestructibleBuildingDamage = 0x360196, DifferentInstanceFromParty = 0x360020, @@ -1247,12 +1255,12 @@ namespace Framework.Constants ExpectedSpamRecords = 0x3b0005, ExplorationExperience = 0x3601fb, ExportAccountProfile = 0x3600f0, - ExternalTransactionIdGenerated = 0x3602f8, + ExternalTransactionIdGenerated = 0x3602f9, FactionBonusInfo = 0x3601c1, FailedPlayerCondition = 0x4a0002, FailedQuestTurnIn = 0x3602a8, FeatureSystemStatus = 0x360058, - FeatureSystemStatus2 = 0x360345, + FeatureSystemStatus2 = 0x360346, FeatureSystemStatusGlueScreen = 0x360059, FeignDeathResisted = 0x3601e0, FishEscaped = 0x36016e, @@ -1267,11 +1275,11 @@ namespace Framework.Constants FriendStatus = 0x360223, GainMawPower = 0x360279, GameObjectActivateAnimKit = 0x36005c, - GameObjectBase = 0x3602bf, - GameObjectCloseInteraction = 0x36030f, + GameObjectBase = 0x3602c0, + GameObjectCloseInteraction = 0x360310, GameObjectCustomAnim = 0x36005d, GameObjectDespawn = 0x36005e, - GameObjectInteraction = 0x36030e, + GameObjectInteraction = 0x36030f, GameObjectPlaySpellVisual = 0x4d003c, GameObjectPlaySpellVisualKit = 0x4d003b, GameObjectResetState = 0x3601bb, @@ -1350,11 +1358,11 @@ namespace Framework.Constants GarrisonUpgradeResult = 0x40000d, GarrisonUseRecallPortalResult = 0x40001f, GenerateRandomCharacterNameResult = 0x36001c, - GenerateSsoTokenResponse = 0x3602b3, + GenerateSsoTokenResponse = 0x3602b4, GetAccountCharacterListResult = 0x3601fd, GetGarrisonInfoResult = 0x400000, GetLandingPageShipmentsResponse = 0x360236, - GetRealmHiddenResult = 0x36033c, + GetRealmHiddenResult = 0x36033d, GetRemainingGameTimeResponse = 0x360271, GetSelectedTrophyIdResponse = 0x36025e, GetShipmentsOfTypeResponse = 0x360235, @@ -1437,7 +1445,7 @@ namespace Framework.Constants GuildRewardList = 0x420008, GuildRoster = 0x420003, GuildSendRankChange = 0x420001, - HardcoreDeathAlert = 0x360344, + HardcoreDeathAlert = 0x360345, HealthUpdate = 0x36016f, HighestThreatUpdate = 0x360177, HotfixConnect = 0x3a0003, @@ -1475,7 +1483,7 @@ namespace Framework.Constants InvalidPromotionCode = 0x3601ef, InventoryChangeFailure = 0x4e0005, InventoryFixupComplete = 0x3602aa, - InventoryFullOverflow = 0x3602bb, + InventoryFullOverflow = 0x3602bc, IslandAzeriteGain = 0x3601f8, IslandComplete = 0x3601f9, IsQuestCompleteResponse = 0x4b0004, @@ -1483,17 +1491,17 @@ namespace Framework.Constants ItemCooldown = 0x36025f, ItemEnchantTimeUpdate = 0x3601f1, ItemExpirePurchaseRefund = 0x360034, - ItemInteractionComplete = 0x3602f0, + ItemInteractionComplete = 0x3602f1, ItemPurchaseRefundResult = 0x360032, ItemPushResult = 0x3600c0, ItemTimeUpdate = 0x3601f0, KickReason = 0x360128, - LatencyReportPing = 0x360300, + LatencyReportPing = 0x360301, LearnedSpells = 0x4d003e, LearnPvpTalentFailed = 0x36006d, LearnTalentFailed = 0x36006c, - LegacyLootRules = 0x3602c0, - LevelLinkingResult = 0x3602d6, + LegacyLootRules = 0x3602c1, + LevelLinkingResult = 0x3602d7, LevelUpInfo = 0x360186, LfgBootPlayer = 0x440019, LfgDisabled = 0x440017, @@ -1529,12 +1537,12 @@ namespace Framework.Constants LiveRegionKeyBindingsCopyResult = 0x36020c, LoadCufProfiles = 0x360055, LoadEquipmentSet = 0x3601ac, - LobbyMatchmakerLobbyAcquiredServer = 0x360311, - LobbyMatchmakerPartyInfo = 0x360312, - LobbyMatchmakerPartyInviteRejected = 0x360313, - LobbyMatchmakerQueueProposed = 0x360315, - LobbyMatchmakerQueueResult = 0x360316, - LobbyMatchmakerReceiveInvite = 0x360314, + LobbyMatchmakerLobbyAcquiredServer = 0x360312, + LobbyMatchmakerPartyInfo = 0x360313, + LobbyMatchmakerPartyInviteRejected = 0x360314, + LobbyMatchmakerQueueProposed = 0x360316, + LobbyMatchmakerQueueResult = 0x360317, + LobbyMatchmakerReceiveInvite = 0x360315, LoginSetTimeSpeed = 0x3601ab, LoginVerifyWorld = 0x36002f, LogoutCancelAck = 0x360124, @@ -1558,17 +1566,17 @@ namespace Framework.Constants MapObjectivesInit = 0x3c002a, MapObjEvents = 0x36005f, MasterLootCandidateList = 0x3600bc, - MeetingStoneFailed = 0x360317, + MeetingStoneFailed = 0x360318, MessageBox = 0x36000a, MinimapPing = 0x36016c, MirrorImageComponentedData = 0x4d0004, MirrorImageCreatureData = 0x4d0003, - MirrorVars = 0x360355, + MirrorVars = 0x360359, MissileCancel = 0x360060, ModifyCooldown = 0x360200, Motd = 0x3b0003, MountResult = 0x36000f, - MovementEnforcementAlert = 0x3602c6, + MovementEnforcementAlert = 0x3602c7, MoveAddImpulse = 0x480062, MoveApplyInertia = 0x48005e, MoveApplyMovementForce = 0x480045, @@ -1689,14 +1697,14 @@ namespace Framework.Constants MythicPlusNewWeekRecord = 0x3600af, MythicPlusSeasonData = 0x3600a9, NeutralPlayerFactionSelectResult = 0x360074, - NewDataBuild = 0x36033b, + NewDataBuild = 0x36033c, NewTaxiPath = 0x36011d, NewWorld = 0x36002b, NotifyDestLocSpellCast = 0x4d0034, NotifyMissileTrajectoryCollision = 0x360149, NotifyMoney = 0x360031, NotifyReceivedMail = 0x3600d9, - NpcInteractionOpenResult = 0x36030d, + NpcInteractionOpenResult = 0x36030e, OfferPetitionError = 0x360154, OnCancelExpectedRideVehicleAura = 0x360183, OnMonsterMove = 0x480002, @@ -1707,21 +1715,21 @@ namespace Framework.Constants OverrideLight = 0x360159, PageText = 0x3601b7, PartyCommandResult = 0x36022c, - PartyEligibilityForDelveTiersResponse = 0x360350, + PartyEligibilityForDelveTiersResponse = 0x360351, PartyInvite = 0x360056, PartyKillLog = 0x3601f6, PartyMemberFullState = 0x3601f5, PartyMemberPartialState = 0x3601f4, - PartyNotifyLfgLeaderChange = 0x3602f6, + PartyNotifyLfgLeaderChange = 0x3602f7, PartyUpdate = 0x36008c, PastTimeEvents = 0x36005b, PauseMirrorTimer = 0x3601ae, PendingRaidLock = 0x360195, - PerksProgramActivityComplete = 0x36030a, - PerksProgramActivityUpdate = 0x360306, - PerksProgramDisabled = 0x36030b, - PerksProgramResult = 0x360307, - PerksProgramVendorUpdate = 0x360305, + PerksProgramActivityComplete = 0x36030b, + PerksProgramActivityUpdate = 0x360307, + PerksProgramDisabled = 0x36030c, + PerksProgramResult = 0x360308, + PerksProgramVendorUpdate = 0x360306, PetitionAlreadySigned = 0x360037, PetitionRenameGuildResponse = 0x420042, PetitionShowList = 0x36015c, @@ -1794,7 +1802,7 @@ namespace Framework.Constants PowerUpdate = 0x360170, PreloadChildMap = 0x36000d, PreloadWorld = 0x36002c, - PrepopulateNameCache = 0x3602c9, + PrepopulateNameCache = 0x3602ca, PreRessurect = 0x360203, PrintNotification = 0x360063, ProcResist = 0x3601f7, @@ -1807,7 +1815,7 @@ namespace Framework.Constants PvpMatchStart = 0x3c002d, PvpMatchStatistics = 0x3c0010, PvpOptionsEnabled = 0x3c0013, - PvpTierRecord = 0x360301, + PvpTierRecord = 0x360302, QueryBattlePetNameResponse = 0x3a000c, QueryCreatureResponse = 0x3a0006, QueryGameObjectResponse = 0x3a0007, @@ -1842,10 +1850,10 @@ namespace Framework.Constants QuestPoiQueryResponse = 0x4b001d, QuestPoiUpdateResponse = 0x4b001f, QuestPushResult = 0x4b0010, - QuestSessionInfoResponse = 0x3602ec, - QuestSessionReadyCheck = 0x3602da, - QuestSessionReadyCheckResponse = 0x3602db, - QuestSessionResult = 0x3602d9, + QuestSessionInfoResponse = 0x3602ed, + QuestSessionReadyCheck = 0x3602db, + QuestSessionReadyCheckResponse = 0x3602dc, + QuestSessionResult = 0x3602da, QuestUpdateAddCredit = 0x4b000c, QuestUpdateAddCreditSimple = 0x4b000d, QuestUpdateAddPvpCredit = 0x4b000e, @@ -1853,9 +1861,9 @@ namespace Framework.Constants QuestUpdateFailed = 0x4b000a, QuestUpdateFailedTimer = 0x4b000b, QueueSummaryUpdate = 0x3602a9, - RafAccountInfo = 0x3602d7, - RafActivityStateChanged = 0x3602e8, - RafDebugFriendMonths = 0x360338, + RafAccountInfo = 0x3602d8, + RafActivityStateChanged = 0x3602e9, + RafDebugFriendMonths = 0x360339, RaidDifficultySet = 0x360244, RaidGroupOnly = 0x360246, RaidInstanceMessage = 0x3b000a, @@ -1871,7 +1879,9 @@ namespace Framework.Constants ReattachResurrect = 0x3601e7, ReceivePingUnit = 0x360039, ReceivePingWorldPoint = 0x36003a, - RecraftItemResult = 0x36032e, + RecentAllyDataResponse = 0x360354, + RecentAllyNoteUpdated = 0x360355, + RecraftItemResult = 0x36032f, RecruitAFriendFailure = 0x36015e, RefreshComponent = 0x3600ed, RegionwideCharacterMailData = 0x36001a, @@ -1885,14 +1895,14 @@ namespace Framework.Constants RequestScheduledPvpInfoResponse = 0x3c0015, ResetCompressionContext = 0x3d0007, ResetFailedNotify = 0x360155, - ResetLastLoadedConfigCvars = 0x360335, + ResetLastLoadedConfigCvars = 0x360336, ResetQuestPoi = 0x4b0020, ResetRangedCombatTimer = 0x3c0023, ResetWeeklyCurrency = 0x360009, RespecWipeConfirm = 0x3600b0, RespondInspectAchievements = 0x360006, - ResponsePerkPendingRewards = 0x360308, - ResponsePerkRecentPurchases = 0x360309, + ResponsePerkPendingRewards = 0x360309, + ResponsePerkRecentPurchases = 0x36030a, RestartGlobalCooldown = 0x4d0052, RestrictedAccountWarning = 0x360052, ResumeCast = 0x4d002c, @@ -1902,8 +1912,8 @@ namespace Framework.Constants ResurrectRequest = 0x360012, ResyncRunes = 0x4d0050, ReturningPlayerPrompt = 0x36023f, - ReturnApplicantList = 0x3602cd, - ReturnRecruitingClubs = 0x3602cc, + ReturnApplicantList = 0x3602ce, + ReturnRecruitingClubs = 0x3602cd, RoleChangedInform = 0x360021, RoleChosen = 0x44001d, RolePollInform = 0x360022, @@ -1950,7 +1960,7 @@ namespace Framework.Constants SetFactionStanding = 0x3601c8, SetFactionVisible = 0x3601c6, SetFlatSpellModifier = 0x4d0027, - SetInstanceLeaver = 0x360356, + SetInstanceLeaver = 0x36035a, SetItemPurchaseData = 0x360033, SetLootMethodFailed = 0x360267, SetMaxWeeklyQuantity = 0x360036, @@ -1961,25 +1971,25 @@ namespace Framework.Constants SetPlayerDeclinedNamesResult = 0x4a000b, SetPlayHoverAnim = 0x360053, SetProficiency = 0x3601d1, - SetQuestReplayCooldownOverride = 0x3602e0, + SetQuestReplayCooldownOverride = 0x3602e1, SetShipmentReadyResponse = 0x40003a, SetSpellCharges = 0x4d0018, SetTimeZoneInformation = 0x360116, SetVehicleRecId = 0x360194, - ShadowlandsCapacitanceUpdate = 0x36030c, + ShadowlandsCapacitanceUpdate = 0x36030d, ShipmentFactionUpdateResult = 0x40003b, - ShowDelvesCompanionConfigurationUi = 0x36034e, - ShowDelvesDisplayUi = 0x36034c, + ShowDelvesCompanionConfigurationUi = 0x36034f, + ShowDelvesDisplayUi = 0x36034d, ShowNeutralPlayerFactionSelectUi = 0x360073, ShowQuestCompletionText = 0x4b0015, ShowTaxiNodes = 0x36016b, ShowTradeSkillResponse = 0x36020d, - SocialContractRequestResponse = 0x360318, + SocialContractRequestResponse = 0x360319, SocketGemsFailure = 0x3601c4, SocketGemsSuccess = 0x3601c3, SpecialMountAnim = 0x36013e, - SpectateEnd = 0x36033a, - SpectatePlayer = 0x360339, + SpectateEnd = 0x36033b, + SpectatePlayer = 0x36033a, SpecInvoluntarilyChanged = 0x3601b6, SpellAbsorbLog = 0x4d000c, SpellCategoryCooldown = 0x4d0006, @@ -2009,7 +2019,7 @@ namespace Framework.Constants SpellPrepare = 0x4d0029, SpellStart = 0x4d002b, SpellVisualLoadScreen = 0x360065, - SplashScreenShowLatest = 0x3602f2, + SplashScreenShowLatest = 0x3602f3, StandStateUpdate = 0x3601ba, StarterBuildActivateFailed = 0x36006b, StartElapsedTimer = 0x3600a0, @@ -2028,16 +2038,17 @@ namespace Framework.Constants SummonRaidMemberValidateFailed = 0x360023, SummonRequest = 0x3601be, SupercededSpells = 0x4d003d, + SurveyDelivered = 0x360357, SuspendComms = 0x3d0002, SuspendToken = 0x360040, - SyncWowEntitlements = 0x3602ea, + SyncWowEntitlements = 0x3602eb, TalentsInvoluntarilyReset = 0x3601b5, TaxiNodeStatus = 0x36011b, TextEmote = 0x360119, ThreatClear = 0x36017a, ThreatRemove = 0x360179, ThreatUpdate = 0x360178, - TimerunningSeasonEnded = 0x36034f, + TimerunningSeasonEnded = 0x360350, TimeAdjustment = 0x480001, TimeSyncRequest = 0x480000, TitleEarned = 0x360175, @@ -2064,21 +2075,21 @@ namespace Framework.Constants UndeleteCooldownStatusResponse = 0x360263, UnlearnedSpells = 0x4d003f, UnloadChildMap = 0x36000e, - UnsetInstanceLeaver = 0x360357, - UpdateAadcStatusResponse = 0x360302, + UnsetInstanceLeaver = 0x36035b, + UpdateAadcStatusResponse = 0x360303, UpdateAccountData = 0x3601a6, UpdateAccountDataComplete = 0x3601a7, UpdateActionButtons = 0x360078, - UpdateBnetSessionKey = 0x3602ba, + UpdateBnetSessionKey = 0x3602bb, UpdateCapturePoint = 0x3c0007, - UpdateCelestialBody = 0x3602b6, + UpdateCelestialBody = 0x3602b7, UpdateCharacterFlags = 0x36025b, UpdateChargeCategoryCooldown = 0x360202, UpdateCooldown = 0x360201, UpdateCraftingNpcRecipes = 0x400038, UpdateDailyMissionCounter = 0x400021, UpdateExpansionLevel = 0x3600e3, - UpdateGameTimeState = 0x3602bd, + UpdateGameTimeState = 0x3602be, UpdateInstanceOwnership = 0x360148, UpdateLastInstance = 0x360127, UpdateObject = 0x460000, @@ -2090,16 +2101,16 @@ namespace Framework.Constants UserlistRemove = 0x3b0010, UserlistUpdate = 0x3b0011, UseEquipmentSetResult = 0x3601eb, - VasCheckTransferOkResponse = 0x3602b1, - VasGetQueueMinutesResponse = 0x3602af, - VasGetServiceStatusResponse = 0x3602ae, + VasCheckTransferOkResponse = 0x3602b2, + VasGetQueueMinutesResponse = 0x3602b0, + VasGetServiceStatusResponse = 0x3602af, VasPurchaseComplete = 0x360289, VasPurchaseStateUpdate = 0x360288, VendorInventory = 0x360051, VignetteUpdate = 0x4a0010, - VoiceChannelInfoResponse = 0x3602b5, - VoiceChannelSttTokenResponse = 0x3602fd, - VoiceLoginResponse = 0x3602b4, + VoiceChannelInfoResponse = 0x3602b6, + VoiceChannelSttTokenResponse = 0x3602fe, + VoiceLoginResponse = 0x3602b5, VoidItemSwapResponse = 0x4e0004, VoidStorageContents = 0x4e0001, VoidStorageFailed = 0x4e0000, @@ -2108,29 +2119,29 @@ namespace Framework.Constants WaitQueueFinish = 0x360003, WaitQueueUpdate = 0x360002, Warden3Data = 0x36000b, - Warden3Disabled = 0x3602b8, - Warden3Enabled = 0x3602b7, + Warden3Disabled = 0x3602b9, + Warden3Enabled = 0x3602b8, WarfrontComplete = 0x3601fa, WargameRequestOpponentResponse = 0x3c0012, WargameRequestSuccessfullySentToOpponent = 0x3c0011, Weather = 0x360145, - WeeklyRewardsProgressResult = 0x3602f5, - WeeklyRewardsResult = 0x3602f3, - WeeklyRewardClaimResult = 0x3602f4, + WeeklyRewardsProgressResult = 0x3602f6, + WeeklyRewardsResult = 0x3602f4, + WeeklyRewardClaimResult = 0x3602f5, Who = 0x3b0002, WhoIs = 0x360144, - WillBeKickedForAddedSubscriptionTime = 0x3602bc, + WillBeKickedForAddedSubscriptionTime = 0x3602bd, WorldQuestUpdateResponse = 0x4a0017, WorldServerInfo = 0x360045, - WowEntitlementNotification = 0x3602eb, - WowLabsAreaInfo = 0x36031d, - WowLabsNotifyPlayersMatchEnd = 0x360319, - WowLabsNotifyPlayersMatchStateChanged = 0x36031a, - WowLabsPartyError = 0x360326, - WowLabsSetAreaIdResult = 0x36031b, - WowLabsSetPredictionCircle = 0x36031f, - WowLabsSetSelectedAreaId = 0x36031c, - XpAwardedFromCurrency = 0x360334, + WowEntitlementNotification = 0x3602ec, + WowLabsAreaInfo = 0x36031e, + WowLabsNotifyPlayersMatchEnd = 0x36031a, + WowLabsNotifyPlayersMatchStateChanged = 0x36031b, + WowLabsPartyError = 0x360327, + WowLabsSetAreaIdResult = 0x36031c, + WowLabsSetPredictionCircle = 0x360320, + WowLabsSetSelectedAreaId = 0x36031d, + XpAwardedFromCurrency = 0x360335, XpGainAborted = 0x360062, XpGainEnabled = 0x360245, ZoneUnderAttack = 0x3b000b, diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index e734968bb..efcfa0296 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -2542,587 +2542,618 @@ namespace Framework.Constants ReadyCheckInProgress = 617, ReadyCheckThrottled = 618, VoteToAbandonNotYet = 619, - DungeonDifficultyFailed = 620, - DungeonDifficultyChangedS = 621, - TradeWrongRealm = 622, - TradeNotOnTaplist = 623, - ChatPlayerAmbiguousS = 624, - LootCantLootThatNow = 625, - LootMasterInvFull = 626, - LootMasterUniqueItem = 627, - LootMasterOther = 628, - FilteringYouS = 629, - UsePreventedByMechanicS = 630, - ItemUniqueEquippable = 631, - LfgLeaderIsLfmS = 632, - LfgPending = 633, - CantSpeakLangage = 634, - VendorMissingTurnins = 635, - BattlegroundNotInTeam = 636, - NotInBattleground = 637, - NotEnoughHonorPoints = 638, - NotEnoughArenaPoints = 639, - SocketingRequiresMetaGem = 640, - SocketingMetaGemOnlyInMetaslot = 641, - SocketingRequiresHydraulicGem = 642, - SocketingHydraulicGemOnlyInHydraulicslot = 643, - SocketingRequiresCogwheelGem = 644, - SocketingCogwheelGemOnlyInCogwheelslot = 645, - SocketingItemTooLowLevel = 646, - ItemMaxCountSocketed = 647, - SystemDisabled = 648, - QuestFailedTooManyDailyQuestsI = 649, - ItemMaxCountEquippedSocketed = 650, - ItemUniqueEquippableSocketed = 651, - UserSquelched = 652, - AccountSilenced = 653, - PartyMemberSilenced = 654, - PartyMemberSilencedLfgDelist = 655, - TooMuchGold = 656, - NotBarberSitting = 657, - QuestFailedCais = 658, - InviteRestrictedTrial = 659, - VoiceIgnoreFull = 660, - VoiceIgnoreSelf = 661, - VoiceIgnoreNotFound = 662, - VoiceIgnoreAlreadyS = 663, - VoiceIgnoreAddedS = 664, - VoiceIgnoreRemovedS = 665, - VoiceIgnoreAmbiguous = 666, - VoiceIgnoreDeleted = 667, - UnknownMacroOptionS = 668, - NotDuringArenaMatch = 669, - NotInRatedBattleground = 670, - PlayerSilenced = 671, - PlayerUnsilenced = 672, - ComsatDisconnect = 673, - ComsatReconnectAttempt = 674, - ComsatConnectFail = 675, - MailInvalidAttachmentSlot = 676, - MailTooManyAttachments = 677, - MailInvalidAttachment = 678, - MailAttachmentExpired = 679, - VoiceChatParentalDisableMic = 680, - ProfaneChatName = 681, - PlayerSilencedEcho = 682, - PlayerUnsilencedEcho = 683, - LootCantLootThat = 684, - ArenaExpiredCais = 685, - GroupActionThrottled = 686, - AlreadyPickpocketed = 687, - NameInvalid = 688, - NameNoName = 689, - NameTooShort = 690, - NameTooLong = 691, - NameMixedLanguages = 692, - NameProfane = 693, - NameReserved = 694, - NameThreeConsecutive = 695, - NameInvalidSpace = 696, - NameConsecutiveSpaces = 697, - NameRussianConsecutiveSilentCharacters = 698, - NameRussianSilentCharacterAtBeginningOrEnd = 699, - NameDeclensionDoesntMatchBaseName = 700, - RecruitAFriendNotLinked = 701, - RecruitAFriendNotNow = 702, - RecruitAFriendSummonLevelMax = 703, - RecruitAFriendSummonCooldown = 704, - RecruitAFriendSummonOffline = 705, - RecruitAFriendInsufExpanLvl = 706, - RecruitAFriendMapIncomingTransferNotAllowed = 707, - NotSameAccount = 708, - BadOnUseEnchant = 709, - TradeSelf = 710, - TooManySockets = 711, - ItemMaxLimitCategoryCountExceededIs = 712, - TradeTargetMaxLimitCategoryCountExceededIs = 713, - ItemMaxLimitCategorySocketedExceededIs = 714, - ItemMaxLimitCategoryEquippedExceededIs = 715, - ShapeshiftFormCannotEquip = 716, - ItemInventoryFullSatchel = 717, - ScalingStatItemLevelExceeded = 718, - ScalingStatItemLevelTooLow = 719, - PurchaseLevelTooLow = 720, - GroupSwapFailed = 721, - InviteInCombat = 722, - InvalidGlyphSlot = 723, - GenericNoValidTargets = 724, - CalendarEventAlertS = 725, - PetLearnSpellS = 726, - PetLearnAbilityS = 727, - PetSpellUnlearnedS = 728, - InviteUnknownRealm = 729, - InviteNoPartyServer = 730, - InvitePartyBusy = 731, - InvitePartyBusyPendingRequest = 732, - InvitePartyBusyPendingSuggest = 733, - PartyTargetAmbiguous = 734, - PartyLfgInviteRaidLocked = 735, - PartyLfgBootLimit = 736, - PartyLfgBootCooldownS = 737, - PartyLfgBootNotEligibleS = 738, - PartyLfgBootInpatientTimerS = 739, - PartyLfgBootInProgress = 740, - PartyLfgBootTooFewPlayers = 741, - PartyLfgBootVoteSucceeded = 742, - PartyLfgBootVoteFailed = 743, - PartyLfgBootDisallowedByMap = 744, - PartyLfgBootDungeonComplete = 745, - PartyLfgBootLootRolls = 746, - PartyLfgBootVoteRegistered = 747, - PartyPrivateGroupOnly = 748, - PartyLfgTeleportInCombat = 749, - PartyTimeRunningSeasonIdMustMatch = 750, - RaidDisallowedByLevel = 751, - RaidDisallowedByCrossRealm = 752, - PartyRoleNotAvailable = 753, - JoinLfgObjectFailed = 754, - LfgRemovedLevelup = 755, - LfgRemovedXpToggle = 756, - LfgRemovedFactionChange = 757, - BattlegroundInfoThrottled = 758, - BattlegroundAlreadyIn = 759, - ArenaTeamChangeFailedQueued = 760, - ArenaTeamPermissions = 761, - NotWhileFalling = 762, - NotWhileMoving = 763, - NotWhileFatigued = 764, - MaxSockets = 765, - MultiCastActionTotemS = 766, - BattlegroundJoinLevelup = 767, - RemoveFromPvpQueueXpGain = 768, - BattlegroundJoinXpGain = 769, - BattlegroundJoinMercenary = 770, - BattlegroundJoinTooManyHealers = 771, - BattlegroundJoinRatedTooManyHealers = 772, - BattlegroundJoinTooManyTanks = 773, - BattlegroundJoinTooManyDamage = 774, - RaidDifficultyFailed = 775, - RaidDifficultyChangedS = 776, - LegacyRaidDifficultyChangedS = 777, - RaidLockoutChangedS = 778, - RaidConvertedToParty = 779, - PartyConvertedToRaid = 780, - PlayerDifficultyChangedS = 781, - GmresponseDbError = 782, - BattlegroundJoinRangeIndex = 783, - ArenaJoinRangeIndex = 784, - RemoveFromPvpQueueFactionChange = 785, - BattlegroundJoinFailed = 786, - BattlegroundJoinNoValidSpecForRole = 787, - BattlegroundJoinRespec = 788, - BattlegroundInvitationDeclined = 789, - BattlegroundInvitationDeclinedBy = 790, - BattlegroundJoinTimedOut = 791, - BattlegroundDupeQueue = 792, - BattlegroundJoinMustCompleteQuest = 793, - InBattlegroundRespec = 794, - MailLimitedDurationItem = 795, - YellRestrictedTrial = 796, - ChatRaidRestrictedTrial = 797, - LfgRoleCheckFailed = 798, - LfgRoleCheckFailedTimeout = 799, - LfgRoleCheckFailedNotViable = 800, - LfgReadyCheckFailed = 801, - LfgReadyCheckFailedTimeout = 802, - LfgGroupFull = 803, - LfgNoLfgObject = 804, - LfgNoSlotsPlayer = 805, - LfgNoSlotsParty = 806, - LfgNoSpec = 807, - LfgMismatchedSlots = 808, - LfgMismatchedSlotsLocalXrealm = 809, - LfgPartyPlayersFromDifferentRealms = 810, - LfgMembersNotPresent = 811, - LfgGetInfoTimeout = 812, - LfgInvalidSlot = 813, - LfgDeserterPlayer = 814, - LfgDeserterParty = 815, - LfgDead = 816, - LfgRandomCooldownPlayer = 817, - LfgRandomCooldownParty = 818, - LfgTooManyMembers = 819, - LfgTooFewMembers = 820, - LfgProposalFailed = 821, - LfgProposalDeclinedSelf = 822, - LfgProposalDeclinedParty = 823, - LfgNoSlotsSelected = 824, - LfgNoRolesSelected = 825, - LfgRoleCheckInitiated = 826, - LfgReadyCheckInitiated = 827, - LfgPlayerDeclinedRoleCheck = 828, - LfgPlayerDeclinedReadyCheck = 829, - LfgLorewalking = 830, - LfgJoinedQueue = 831, - LfgJoinedFlexQueue = 832, - LfgJoinedRfQueue = 833, - LfgJoinedScenarioQueue = 834, - LfgJoinedWorldPvpQueue = 835, - LfgJoinedBattlefieldQueue = 836, - LfgJoinedList = 837, - QueuedPlunderstorm = 838, - LfgLeftQueue = 839, - LfgLeftList = 840, - LfgRoleCheckAborted = 841, - LfgReadyCheckAborted = 842, - LfgCantUseBattleground = 843, - LfgCantUseDungeons = 844, - LfgReasonTooManyLfg = 845, - LfgFarmLimit = 846, - LfgNoCrossFactionParties = 847, - InvalidTeleportLocation = 848, - TooFarToInteract = 849, - BattlegroundPlayersFromDifferentRealms = 850, - DifficultyChangeCooldownS = 851, - DifficultyChangeCombatCooldownS = 852, - DifficultyChangeWorldstate = 853, - DifficultyChangeEncounter = 854, - DifficultyChangeCombat = 855, - DifficultyChangePlayerBusy = 856, - DifficultyChangePlayerOnVehicle = 857, - DifficultyChangeAlreadyStarted = 858, - DifficultyChangeOtherHeroicS = 859, - DifficultyChangeHeroicInstanceAlreadyRunning = 860, - ArenaTeamPartySize = 861, - SoloShuffleWargameGroupSize = 862, - SoloShuffleWargameGroupComp = 863, - SoloRbgWargameGroupSize = 864, - SoloRbgWargameGroupComp = 865, - SoloMinItemLevel = 866, - PvpPlayerAbandoned = 867, - BattlegroundJoinGroupQueueWithoutHealer = 868, - QuestForceRemovedS = 869, - AttackNoActions = 870, - InRandomBg = 871, - InNonRandomBg = 872, - BnFriendSelf = 873, - BnFriendAlready = 874, - BnFriendBlocked = 875, - BnFriendListFull = 876, - BnFriendRequestSent = 877, - BnBroadcastThrottle = 878, - BgDeveloperOnly = 879, - CurrencySpellSlotMismatch = 880, - CurrencyNotTradable = 881, - RequiresExpansionS = 882, - QuestFailedSpell = 883, - TalentFailedUnspentTalentPoints = 884, - TalentFailedNotEnoughTalentsInPrimaryTree = 885, - TalentFailedNoPrimaryTreeSelected = 886, - TalentFailedCantRemoveTalent = 887, - TalentFailedUnknown = 888, - TalentFailedInCombat = 889, - TalentFailedInPvpMatch = 890, - TalentFailedInMythicPlus = 891, - WargameRequestFailure = 892, - RankRequiresAuthenticator = 893, - GuildBankVoucherFailed = 894, - WargameRequestSent = 895, - RequiresAchievementI = 896, - RefundResultExceedMaxCurrency = 897, - CantBuyQuantity = 898, - ItemIsBattlePayLocked = 899, - PartyAlreadyInBattlegroundQueue = 900, - PartyConfirmingBattlegroundQueue = 901, - BattlefieldTeamPartySize = 902, - InsuffTrackedCurrencyIs = 903, - NotOnTournamentRealm = 904, - GuildTrialAccountTrial = 905, - GuildTrialAccountVeteran = 906, - GuildUndeletableDueToLevel = 907, - CantDoThatInAGroup = 908, - GuildLeaderReplaced = 909, - TransmogrifyCantEquip = 910, - TransmogrifyInvalidItemType = 911, - TransmogrifyNotSoulbound = 912, - TransmogrifyInvalidSource = 913, - TransmogrifyInvalidDestination = 914, - TransmogrifyMismatch = 915, - TransmogrifyLegendary = 916, - TransmogrifySameItem = 917, - TransmogrifySameAppearance = 918, - TransmogrifyNotEquipped = 919, - VoidDepositFull = 920, - VoidWithdrawFull = 921, - VoidStorageWrapped = 922, - VoidStorageStackable = 923, - VoidStorageUnbound = 924, - VoidStorageRepair = 925, - VoidStorageCharges = 926, - VoidStorageQuest = 927, - VoidStorageConjured = 928, - VoidStorageMail = 929, - VoidStorageBag = 930, - VoidTransferStorageFull = 931, - VoidTransferInvFull = 932, - VoidTransferInternalError = 933, - VoidTransferItemInvalid = 934, - DifficultyDisabledInLfg = 935, - VoidStorageUnique = 936, - VoidStorageLoot = 937, - VoidStorageHoliday = 938, - VoidStorageDuration = 939, - VoidStorageLoadFailed = 940, - VoidStorageInvalidItem = 941, - VoidStorageAccountItem = 942, - ParentalControlsChatMuted = 943, - SorStartExperienceIncomplete = 944, - SorInvalidEmail = 945, - SorInvalidComment = 946, - ChallengeModeResetCooldownS = 947, - ChallengeModeResetKeystone = 948, - PetJournalAlreadyInLoadout = 949, - ReportSubmittedSuccessfully = 950, - ReportSubmissionFailed = 951, - SuggestionSubmittedSuccessfully = 952, - BugSubmittedSuccessfully = 953, - ChallengeModeEnabled = 954, - ChallengeModeDisabled = 955, - PetbattleCreateFailed = 956, - PetbattleNotHere = 957, - PetbattleNotHereOnTransport = 958, - PetbattleNotHereUnevenGround = 959, - PetbattleNotHereObstructed = 960, - PetbattleNotWhileInCombat = 961, - PetbattleNotWhileDead = 962, - PetbattleNotWhileFlying = 963, - PetbattleTargetInvalid = 964, - PetbattleTargetOutOfRange = 965, - PetbattleTargetNotCapturable = 966, - PetbattleNotATrainer = 967, - PetbattleDeclined = 968, - PetbattleInBattle = 969, - PetbattleInvalidLoadout = 970, - PetbattleAllPetsDead = 971, - PetbattleNoPetsInSlots = 972, - PetbattleNoAccountLock = 973, - PetbattleWildPetTapped = 974, - PetbattleRestrictedAccount = 975, - PetbattleOpponentNotAvailable = 976, - PetbattleNotWhileInMatchedBattle = 977, - CantHaveMorePetsOfThatType = 978, - CantHaveMorePets = 979, - PvpMapNotFound = 980, - PvpMapNotSet = 981, - PetbattleQueueQueued = 982, - PetbattleQueueAlreadyQueued = 983, - PetbattleQueueJoinFailed = 984, - PetbattleQueueJournalLock = 985, - PetbattleQueueRemoved = 986, - PetbattleQueueProposalDeclined = 987, - PetbattleQueueProposalTimeout = 988, - PetbattleQueueOpponentDeclined = 989, - PetbattleQueueRequeuedInternal = 990, - PetbattleQueueRequeuedRemoved = 991, - PetbattleQueueSlotLocked = 992, - PetbattleQueueSlotEmpty = 993, - PetbattleQueueSlotNoTracker = 994, - PetbattleQueueSlotNoSpecies = 995, - PetbattleQueueSlotCantBattle = 996, - PetbattleQueueSlotRevoked = 997, - PetbattleQueueSlotDead = 998, - PetbattleQueueSlotNoPet = 999, - PetbattleQueueNotWhileNeutral = 1000, - PetbattleGameTimeLimitWarning = 1001, - PetbattleGameRoundsLimitWarning = 1002, - HasRestriction = 1003, - ItemUpgradeItemTooLowLevel = 1004, - ItemUpgradeNoPath = 1005, - ItemUpgradeNoMoreUpgrades = 1006, - BonusRollEmpty = 1007, - ChallengeModeFull = 1008, - ChallengeModeInProgress = 1009, - ChallengeModeIncorrectKeystone = 1010, - StartRestrictedChallengeMode = 1011, - BattletagFriendNotFound = 1012, - BattletagFriendNotValid = 1013, - BattletagFriendNotAllowed = 1014, - BattletagFriendThrottled = 1015, - BattletagFriendSuccess = 1016, - PetTooHighLevelToUncage = 1017, - PetbattleInternal = 1018, - CantCagePetYet = 1019, - NoLootInChallengeMode = 1020, - QuestPetBattleVictoriesPvpIi = 1021, - RoleCheckAlreadyInProgress = 1022, - RecruitAFriendAccountLimit = 1023, - RecruitAFriendFailed = 1024, - SetLootPersonal = 1025, - SetLootMethodFailedCombat = 1026, - ReagentBankFull = 1027, - ReagentBankLocked = 1028, - GarrisonBuildingExists = 1029, - GarrisonInvalidPlot = 1030, - GarrisonInvalidBuildingid = 1031, - GarrisonInvalidPlotBuilding = 1032, - GarrisonRequiresBlueprint = 1033, - GarrisonNotEnoughCurrency = 1034, - GarrisonNotEnoughGold = 1035, - GarrisonCompleteMissionWrongFollowerType = 1036, - AlreadyUsingLfgList = 1037, - RestrictedAccountLfgListTrial = 1038, - ToyUseLimitReached = 1039, - ToyAlreadyKnown = 1040, - TransmogSetAlreadyKnown = 1041, - NotEnoughCurrency = 1042, - SpecIsDisabled = 1043, - FeatureRestrictedTrial = 1044, - CantBeObliterated = 1045, - CantBeScrapped = 1046, - CantBeRecrafted = 1047, - ArtifactRelicDoesNotMatchArtifact = 1048, - MustEquipArtifact = 1049, - CantDoThatRightNow = 1050, - AffectingCombat = 1051, - EquipmentManagerCombatSwapS = 1052, - EquipmentManagerBagsFull = 1053, - EquipmentManagerMissingItemS = 1054, - MovieRecordingWarningPerf = 1055, - MovieRecordingWarningDiskFull = 1056, - MovieRecordingWarningNoMovie = 1057, - MovieRecordingWarningRequirements = 1058, - MovieRecordingWarningCompressing = 1059, - NoChallengeModeReward = 1060, - ClaimedChallengeModeReward = 1061, - ChallengeModePeriodResetSs = 1062, - CantDoThatChallengeModeActive = 1063, - TalentFailedRestArea = 1064, - CannotAbandonLastPet = 1065, - TestCvarSetSss = 1066, - QuestTurnInFailReason = 1067, - ClaimedChallengeModeRewardOld = 1068, - TalentGrantedByAura = 1069, - ChallengeModeAlreadyComplete = 1070, - GlyphTargetNotAvailable = 1071, - PvpWarmodeToggleOn = 1072, - PvpWarmodeToggleOff = 1073, - SpellFailedLevelRequirement = 1074, - SpellFailedCantFlyHere = 1075, - BattlegroundJoinRequiresLevel = 1076, - BattlegroundJoinDisqualified = 1077, - BattlegroundJoinDisqualifiedNoName = 1078, - VoiceChatGenericUnableToConnect = 1079, - VoiceChatServiceLost = 1080, - VoiceChatChannelNameTooShort = 1081, - VoiceChatChannelNameTooLong = 1082, - VoiceChatChannelAlreadyExists = 1083, - VoiceChatTargetNotFound = 1084, - VoiceChatTooManyRequests = 1085, - VoiceChatPlayerSilenced = 1086, - VoiceChatParentalDisableAll = 1087, - VoiceChatDisabled = 1088, - NoPvpReward = 1089, - ClaimedPvpReward = 1090, - AzeriteEssenceSelectionFailedEssenceNotUnlocked = 1091, - AzeriteEssenceSelectionFailedCantRemoveEssence = 1092, - AzeriteEssenceSelectionFailedConditionFailed = 1093, - AzeriteEssenceSelectionFailedRestArea = 1094, - AzeriteEssenceSelectionFailedSlotLocked = 1095, - AzeriteEssenceSelectionFailedNotAtForge = 1096, - AzeriteEssenceSelectionFailedHeartLevelTooLow = 1097, - AzeriteEssenceSelectionFailedNotEquipped = 1098, - SocketingGenericFailure = 1099, - SocketingRequiresPunchcardredGem = 1100, - SocketingPunchcardredGemOnlyInPunchcardredslot = 1101, - SocketingRequiresPunchcardyellowGem = 1102, - SocketingPunchcardyellowGemOnlyInPunchcardyellowslot = 1103, - SocketingRequiresPunchcardblueGem = 1104, - SocketingPunchcardblueGemOnlyInPunchcardblueslot = 1105, - SocketingRequiresDominationShard = 1106, - SocketingDominationShardOnlyInDominationslot = 1107, - SocketingRequiresCypherGem = 1108, - SocketingCypherGemOnlyInCypherslot = 1109, - SocketingRequiresTinkerGem = 1110, - SocketingTinkerGemOnlyInTinkerslot = 1111, - SocketingRequiresPrimordialGem = 1112, - SocketingPrimordialGemOnlyInPrimordialslot = 1113, - SocketingRequiresFragranceGem = 1114, - SocketingFragranceGemOnlyInFragranceslot = 1115, - SocketingRequiresSingingThunderGem = 1116, - SocketingSingingthunderGemOnlyInSingingthunderslot = 1117, - SocketingRequiresSingingSeaGem = 1118, - SocketingSingingseaGemOnlyInSingingseaslot = 1119, - SocketingRequiresSingingWindGem = 1120, - SocketingSingingwindGemOnlyInSingingwindslot = 1121, - SocketingRequiresFiberGem = 1122, - SocketingFiberGemOnlyInFiberslot = 1123, - LevelLinkingResultLinked = 1124, - LevelLinkingResultUnlinked = 1125, - ClubFinderErrorPostClub = 1126, - ClubFinderErrorApplyClub = 1127, - ClubFinderErrorRespondApplicant = 1128, - ClubFinderErrorCancelApplication = 1129, - ClubFinderErrorTypeAcceptApplication = 1130, - ClubFinderErrorTypeNoInvitePermissions = 1131, - ClubFinderErrorTypeNoPostingPermissions = 1132, - ClubFinderErrorTypeApplicantList = 1133, - ClubFinderErrorTypeApplicantListNoPerm = 1134, - ClubFinderErrorTypeFinderNotAvailable = 1135, - ClubFinderErrorTypeGetPostingIds = 1136, - ClubFinderErrorTypeJoinApplication = 1137, - ClubFinderErrorTypeRealmNotEligible = 1138, - ClubFinderErrorTypeFlaggedRename = 1139, - ClubFinderErrorTypeFlaggedDescriptionChange = 1140, - ItemInteractionNotEnoughGold = 1141, - ItemInteractionNotEnoughCurrency = 1142, - ItemInteractionNoConversionOutput = 1143, - PlayerChoiceErrorPendingChoice = 1144, - SoulbindInvalidConduit = 1145, - SoulbindInvalidConduitItem = 1146, - SoulbindInvalidTalent = 1147, - SoulbindDuplicateConduit = 1148, - ActivateSoulbindS = 1149, - ActivateSoulbindFailedRestArea = 1150, - CantUseProfanity = 1151, - NotInPetBattle = 1152, - NotInNpe = 1153, - NoSpec = 1154, - NoDominationshardOverwrite = 1155, - UseWeeklyRewardsDisabled = 1156, - CrossFactionGroupJoined = 1157, - CantTargetUnfriendlyInOverworld = 1158, - EquipablespellsSlotsFull = 1159, - ItemModAppearanceGroupAlreadyKnown = 1160, - CantBulkSellItemWithRefund = 1161, - NoSoulboundItemInAccountBank = 1162, - NoRefundableItemInAccountBank = 1163, - CantDeleteInAccountBank = 1164, - NoImmediateContainerInAccountBank = 1165, - NoOpenImmediateContainerInAccountBank = 1166, - CantTradeAccountItem = 1167, - NoAccountInventoryLock = 1168, - BankNotAccessible = 1169, - TooManyAccountBankTabs = 1170, - BankTabNotUnlocked = 1171, - AccountMoneyLocked = 1172, - BankTabInvalidName = 1173, - BankTabInvalidText = 1174, - CharacterBankNotConverted = 1175, - WowLabsPartyErrorTypePartyIsFull = 1176, - WowLabsPartyErrorTypeMaxInviteSent = 1177, - WowLabsPartyErrorTypePlayerAlreadyInvited = 1178, - WowLabsPartyErrorTypePartyInviteInvalid = 1179, - WowLabsLobbyMatchmakerErrorEnterQueueFailed = 1180, - WowLabsLobbyMatchmakerErrorLeaveQueueFailed = 1181, - WowLabsSetWowLabsAreaIdFailed = 1182, - PlunderstormCannotQueue = 1183, - TargetIsSelfFoundCannotTrade = 1184, - PlayerIsSelfFoundCannotTrade = 1185, - MailRecepientIsSelfFoundCannotReceiveMail = 1186, - PlayerIsSelfFoundCannotSendMail = 1187, - PlayerIsSelfFoundCannotUseAuctionHouse = 1188, - MailTargetCannotReceiveMail = 1189, - RemixInvalidTransferRequest = 1190, - CurrencyTransferInvalidCharacter = 1191, - CurrencyTransferInvalidCurrency = 1192, - CurrencyTransferInsufficientCurrency = 1193, - CurrencyTransferMaxQuantity = 1194, - CurrencyTransferNoValidSource = 1195, - CurrencyTransferCharacterLoggedIn = 1196, - CurrencyTransferServerError = 1197, - CurrencyTransferUnmetRequirements = 1198, - CurrencyTransferTransactionInProgress = 1199, - CurrencyTransferDisabled = 1200, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + VoteToAbandonEncounter = 620, + DungeonDifficultyFailed = 621, + DungeonDifficultyChangedS = 622, + TradeWrongRealm = 623, + TradeNotOnTaplist = 624, + ChatPlayerAmbiguousS = 625, + LootCantLootThatNow = 626, + LootMasterInvFull = 627, + LootMasterUniqueItem = 628, + LootMasterOther = 629, + FilteringYouS = 630, + UsePreventedByMechanicS = 631, + ItemUniqueEquippable = 632, + LfgLeaderIsLfmS = 633, + LfgPending = 634, + CantSpeakLangage = 635, + VendorMissingTurnins = 636, + BattlegroundNotInTeam = 637, + NotInBattleground = 638, + NotEnoughHonorPoints = 639, + NotEnoughArenaPoints = 640, + SocketingRequiresMetaGem = 641, + SocketingMetaGemOnlyInMetaslot = 642, + SocketingRequiresHydraulicGem = 643, + SocketingHydraulicGemOnlyInHydraulicslot = 644, + SocketingRequiresCogwheelGem = 645, + SocketingCogwheelGemOnlyInCogwheelslot = 646, + SocketingItemTooLowLevel = 647, + ItemMaxCountSocketed = 648, + SystemDisabled = 649, + QuestFailedTooManyDailyQuestsI = 650, + ItemMaxCountEquippedSocketed = 651, + ItemUniqueEquippableSocketed = 652, + UserSquelched = 653, + AccountSilenced = 654, + PartyMemberSilenced = 655, + PartyMemberSilencedLfgDelist = 656, + TooMuchGold = 657, + NotBarberSitting = 658, + QuestFailedCais = 659, + InviteRestrictedTrial = 660, + VoiceIgnoreFull = 661, + VoiceIgnoreSelf = 662, + VoiceIgnoreNotFound = 663, + VoiceIgnoreAlreadyS = 664, + VoiceIgnoreAddedS = 665, + VoiceIgnoreRemovedS = 666, + VoiceIgnoreAmbiguous = 667, + VoiceIgnoreDeleted = 668, + UnknownMacroOptionS = 669, + NotDuringArenaMatch = 670, + NotInRatedBattleground = 671, + PlayerSilenced = 672, + PlayerUnsilenced = 673, + ComsatDisconnect = 674, + ComsatReconnectAttempt = 675, + ComsatConnectFail = 676, + MailInvalidAttachmentSlot = 677, + MailTooManyAttachments = 678, + MailInvalidAttachment = 679, + MailAttachmentExpired = 680, + VoiceChatParentalDisableMic = 681, + ProfaneChatName = 682, + PlayerSilencedEcho = 683, + PlayerUnsilencedEcho = 684, + LootCantLootThat = 685, + ArenaExpiredCais = 686, + GroupActionThrottled = 687, + AlreadyPickpocketed = 688, + NameInvalid = 689, + NameNoName = 690, + NameTooShort = 691, + NameTooLong = 692, + NameMixedLanguages = 693, + NameProfane = 694, + NameReserved = 695, + NameThreeConsecutive = 696, + NameInvalidSpace = 697, + NameConsecutiveSpaces = 698, + NameRussianConsecutiveSilentCharacters = 699, + NameRussianSilentCharacterAtBeginningOrEnd = 700, + NameDeclensionDoesntMatchBaseName = 701, + RecruitAFriendNotLinked = 702, + RecruitAFriendNotNow = 703, + RecruitAFriendSummonLevelMax = 704, + RecruitAFriendSummonCooldown = 705, + RecruitAFriendSummonOffline = 706, + RecruitAFriendInsufExpanLvl = 707, + RecruitAFriendMapIncomingTransferNotAllowed = 708, + NotSameAccount = 709, + BadOnUseEnchant = 710, + TradeSelf = 711, + TooManySockets = 712, + ItemMaxLimitCategoryCountExceededIs = 713, + TradeTargetMaxLimitCategoryCountExceededIs = 714, + ItemMaxLimitCategorySocketedExceededIs = 715, + ItemMaxLimitCategoryEquippedExceededIs = 716, + ShapeshiftFormCannotEquip = 717, + ItemInventoryFullSatchel = 718, + ScalingStatItemLevelExceeded = 719, + ScalingStatItemLevelTooLow = 720, + PurchaseLevelTooLow = 721, + GroupSwapFailed = 722, + InviteInCombat = 723, + InvalidGlyphSlot = 724, + GenericNoValidTargets = 725, + CalendarEventAlertS = 726, + PetLearnSpellS = 727, + PetLearnAbilityS = 728, + PetSpellUnlearnedS = 729, + InviteUnknownRealm = 730, + InviteNoPartyServer = 731, + InvitePartyBusy = 732, + InvitePartyBusyPendingRequest = 733, + InvitePartyBusyPendingSuggest = 734, + PartyTargetAmbiguous = 735, + PartyLfgInviteRaidLocked = 736, + PartyLfgBootLimit = 737, + PartyLfgBootCooldownS = 738, + PartyLfgBootNotEligibleS = 739, + PartyLfgBootInpatientTimerS = 740, + PartyLfgBootInProgress = 741, + PartyLfgBootTooFewPlayers = 742, + PartyLfgBootVoteSucceeded = 743, + PartyLfgBootVoteFailed = 744, + PartyLfgBootDisallowedByMap = 745, + PartyLfgBootDungeonComplete = 746, + PartyLfgBootLootRolls = 747, + PartyLfgBootVoteRegistered = 748, + PartyPrivateGroupOnly = 749, + PartyLfgTeleportInCombat = 750, + PartyTimeRunningSeasonIdMustMatch = 751, + RaidDisallowedByLevel = 752, + RaidDisallowedByCrossRealm = 753, + PartyRoleNotAvailable = 754, + JoinLfgObjectFailed = 755, + LfgRemovedLevelup = 756, + LfgRemovedXpToggle = 757, + LfgRemovedFactionChange = 758, + BattlegroundInfoThrottled = 759, + BattlegroundAlreadyIn = 760, + ArenaTeamChangeFailedQueued = 761, + ArenaTeamPermissions = 762, + NotWhileFalling = 763, + NotWhileMoving = 764, + NotWhileFatigued = 765, + MaxSockets = 766, + MultiCastActionTotemS = 767, + BattlegroundJoinLevelup = 768, + RemoveFromPvpQueueXpGain = 769, + BattlegroundJoinXpGain = 770, + BattlegroundJoinMercenary = 771, + BattlegroundJoinTooManyHealers = 772, + BattlegroundJoinRatedTooManyHealers = 773, + BattlegroundJoinTooManyTanks = 774, + BattlegroundJoinTooManyDamage = 775, + RaidDifficultyFailed = 776, + RaidDifficultyChangedS = 777, + LegacyRaidDifficultyChangedS = 778, + RaidLockoutChangedS = 779, + RaidConvertedToParty = 780, + PartyConvertedToRaid = 781, + PlayerDifficultyChangedS = 782, + GmresponseDbError = 783, + BattlegroundJoinRangeIndex = 784, + ArenaJoinRangeIndex = 785, + RemoveFromPvpQueueFactionChange = 786, + BattlegroundJoinFailed = 787, + BattlegroundJoinNoValidSpecForRole = 788, + BattlegroundJoinRespec = 789, + BattlegroundInvitationDeclined = 790, + BattlegroundInvitationDeclinedBy = 791, + BattlegroundJoinTimedOut = 792, + BattlegroundDupeQueue = 793, + BattlegroundJoinMustCompleteQuest = 794, + InBattlegroundRespec = 795, + MailLimitedDurationItem = 796, + YellRestrictedTrial = 797, + ChatRaidRestrictedTrial = 798, + LfgRoleCheckFailed = 799, + LfgRoleCheckFailedTimeout = 800, + LfgRoleCheckFailedNotViable = 801, + LfgReadyCheckFailed = 802, + LfgReadyCheckFailedTimeout = 803, + LfgGroupFull = 804, + LfgNoLfgObject = 805, + LfgNoSlotsPlayer = 806, + LfgNoSlotsParty = 807, + LfgNoSpec = 808, + LfgMismatchedSlots = 809, + LfgMismatchedSlotsLocalXrealm = 810, + LfgPartyPlayersFromDifferentRealms = 811, + LfgMembersNotPresent = 812, + LfgGetInfoTimeout = 813, + LfgInvalidSlot = 814, + LfgDeserterPlayer = 815, + LfgDeserterParty = 816, + LfgDead = 817, + LfgRandomCooldownPlayer = 818, + LfgRandomCooldownParty = 819, + LfgTooManyMembers = 820, + LfgTooFewMembers = 821, + LfgProposalFailed = 822, + LfgProposalDeclinedSelf = 823, + LfgProposalDeclinedParty = 824, + LfgNoSlotsSelected = 825, + LfgNoRolesSelected = 826, + LfgRoleCheckInitiated = 827, + LfgReadyCheckInitiated = 828, + LfgPlayerDeclinedRoleCheck = 829, + LfgPlayerDeclinedReadyCheck = 830, + LfgLorewalking = 831, + LfgJoinedQueue = 832, + LfgJoinedFlexQueue = 833, + LfgJoinedRfQueue = 834, + LfgJoinedScenarioQueue = 835, + LfgJoinedWorldPvpQueue = 836, + LfgJoinedBattlefieldQueue = 837, + LfgJoinedList = 838, + QueuedPlunderstorm = 839, + LfgLeftQueue = 840, + LfgLeftList = 841, + LfgRoleCheckAborted = 842, + LfgReadyCheckAborted = 843, + LfgCantUseBattleground = 844, + LfgCantUseDungeons = 845, + LfgReasonTooManyLfg = 846, + LfgFarmLimit = 847, + LfgNoCrossFactionParties = 848, + InvalidTeleportLocation = 849, + TooFarToInteract = 850, + BattlegroundPlayersFromDifferentRealms = 851, + DifficultyChangeCooldownS = 852, + DifficultyChangeCombatCooldownS = 853, + DifficultyChangeWorldstate = 854, + DifficultyChangeEncounter = 855, + DifficultyChangeCombat = 856, + DifficultyChangePlayerBusy = 857, + DifficultyChangePlayerOnVehicle = 858, + DifficultyChangeAlreadyStarted = 859, + DifficultyChangeOtherHeroicS = 860, + DifficultyChangeHeroicInstanceAlreadyRunning = 861, + ArenaTeamPartySize = 862, + SoloShuffleWargameGroupSize = 863, + SoloShuffleWargameGroupComp = 864, + SoloRbgWargameGroupSize = 865, + SoloRbgWargameGroupComp = 866, + SoloMinItemLevel = 867, + PvpPlayerAbandoned = 868, + BattlegroundJoinGroupQueueWithoutHealer = 869, + QuestForceRemovedS = 870, + AttackNoActions = 871, + InRandomBg = 872, + InNonRandomBg = 873, + BnFriendSelf = 874, + BnFriendAlready = 875, + BnFriendBlocked = 876, + BnFriendListFull = 877, + BnFriendRequestSent = 878, + BnBroadcastThrottle = 879, + BgDeveloperOnly = 880, + CurrencySpellSlotMismatch = 881, + CurrencyNotTradable = 882, + RequiresExpansionS = 883, + QuestFailedSpell = 884, + TalentFailedUnspentTalentPoints = 885, + TalentFailedNotEnoughTalentsInPrimaryTree = 886, + TalentFailedNoPrimaryTreeSelected = 887, + TalentFailedCantRemoveTalent = 888, + TalentFailedUnknown = 889, + TalentFailedInCombat = 890, + TalentFailedInPvpMatch = 891, + TalentFailedInMythicPlus = 892, + WargameRequestFailure = 893, + RankRequiresAuthenticator = 894, + GuildBankVoucherFailed = 895, + WargameRequestSent = 896, + RequiresAchievementI = 897, + RefundResultExceedMaxCurrency = 898, + CantBuyQuantity = 899, + ItemIsBattlePayLocked = 900, + PartyAlreadyInBattlegroundQueue = 901, + PartyConfirmingBattlegroundQueue = 902, + BattlefieldTeamPartySize = 903, + InsuffTrackedCurrencyIs = 904, + NotOnTournamentRealm = 905, + GuildTrialAccountTrial = 906, + GuildTrialAccountVeteran = 907, + GuildUndeletableDueToLevel = 908, + CantDoThatInAGroup = 909, + GuildLeaderReplaced = 910, + TransmogrifyCantEquip = 911, + TransmogrifyInvalidItemType = 912, + TransmogrifyNotSoulbound = 913, + TransmogrifyInvalidSource = 914, + TransmogrifyInvalidDestination = 915, + TransmogrifyMismatch = 916, + TransmogrifyLegendary = 917, + TransmogrifySameItem = 918, + TransmogrifySameAppearance = 919, + TransmogrifyNotEquipped = 920, + VoidDepositFull = 921, + VoidWithdrawFull = 922, + VoidStorageWrapped = 923, + VoidStorageStackable = 924, + VoidStorageUnbound = 925, + VoidStorageRepair = 926, + VoidStorageCharges = 927, + VoidStorageQuest = 928, + VoidStorageConjured = 929, + VoidStorageMail = 930, + VoidStorageBag = 931, + VoidTransferStorageFull = 932, + VoidTransferInvFull = 933, + VoidTransferInternalError = 934, + VoidTransferItemInvalid = 935, + DifficultyDisabledInLfg = 936, + VoidStorageUnique = 937, + VoidStorageLoot = 938, + VoidStorageHoliday = 939, + VoidStorageDuration = 940, + VoidStorageLoadFailed = 941, + VoidStorageInvalidItem = 942, + VoidStorageAccountItem = 943, + ParentalControlsChatMuted = 944, + SorStartExperienceIncomplete = 945, + SorInvalidEmail = 946, + SorInvalidComment = 947, + ChallengeModeResetCooldownS = 948, + ChallengeModeResetKeystone = 949, + PetJournalAlreadyInLoadout = 950, + ReportSubmittedSuccessfully = 951, + ReportSubmissionFailed = 952, + SuggestionSubmittedSuccessfully = 953, + BugSubmittedSuccessfully = 954, + ChallengeModeEnabled = 955, + ChallengeModeDisabled = 956, + PetbattleCreateFailed = 957, + PetbattleNotHere = 958, + PetbattleNotHereOnTransport = 959, + PetbattleNotHereUnevenGround = 960, + PetbattleNotHereObstructed = 961, + PetbattleNotWhileInCombat = 962, + PetbattleNotWhileDead = 963, + PetbattleNotWhileFlying = 964, + PetbattleTargetInvalid = 965, + PetbattleTargetOutOfRange = 966, + PetbattleTargetNotCapturable = 967, + PetbattleNotATrainer = 968, + PetbattleDeclined = 969, + PetbattleInBattle = 970, + PetbattleInvalidLoadout = 971, + PetbattleAllPetsDead = 972, + PetbattleNoPetsInSlots = 973, + PetbattleNoAccountLock = 974, + PetbattleWildPetTapped = 975, + PetbattleRestrictedAccount = 976, + PetbattleOpponentNotAvailable = 977, + PetbattleNotWhileInMatchedBattle = 978, + CantHaveMorePetsOfThatType = 979, + CantHaveMorePets = 980, + PvpMapNotFound = 981, + PvpMapNotSet = 982, + PetbattleQueueQueued = 983, + PetbattleQueueAlreadyQueued = 984, + PetbattleQueueJoinFailed = 985, + PetbattleQueueJournalLock = 986, + PetbattleQueueRemoved = 987, + PetbattleQueueProposalDeclined = 988, + PetbattleQueueProposalTimeout = 989, + PetbattleQueueOpponentDeclined = 990, + PetbattleQueueRequeuedInternal = 991, + PetbattleQueueRequeuedRemoved = 992, + PetbattleQueueSlotLocked = 993, + PetbattleQueueSlotEmpty = 994, + PetbattleQueueSlotNoTracker = 995, + PetbattleQueueSlotNoSpecies = 996, + PetbattleQueueSlotCantBattle = 997, + PetbattleQueueSlotRevoked = 998, + PetbattleQueueSlotDead = 999, + PetbattleQueueSlotNoPet = 1000, + PetbattleQueueNotWhileNeutral = 1001, + PetbattleGameTimeLimitWarning = 1002, + PetbattleGameRoundsLimitWarning = 1003, + HasRestriction = 1004, + ItemUpgradeItemTooLowLevel = 1005, + ItemUpgradeNoPath = 1006, + ItemUpgradeNoMoreUpgrades = 1007, + BonusRollEmpty = 1008, + ChallengeModeFull = 1009, + ChallengeModeInProgress = 1010, + ChallengeModeIncorrectKeystone = 1011, + StartRestrictedChallengeMode = 1012, + BattletagFriendNotFound = 1013, + BattletagFriendNotValid = 1014, + BattletagFriendNotAllowed = 1015, + BattletagFriendThrottled = 1016, + BattletagFriendSuccess = 1017, + PetTooHighLevelToUncage = 1018, + PetbattleInternal = 1019, + CantCagePetYet = 1020, + NoLootInChallengeMode = 1021, + QuestPetBattleVictoriesPvpIi = 1022, + RoleCheckAlreadyInProgress = 1023, + RecruitAFriendAccountLimit = 1024, + RecruitAFriendFailed = 1025, + SetLootPersonal = 1026, + SetLootMethodFailedCombat = 1027, + ReagentBankFull = 1028, + ReagentBankLocked = 1029, + GarrisonBuildingExists = 1030, + GarrisonInvalidPlot = 1031, + GarrisonInvalidBuildingid = 1032, + GarrisonInvalidPlotBuilding = 1033, + GarrisonRequiresBlueprint = 1034, + GarrisonNotEnoughCurrency = 1035, + GarrisonNotEnoughGold = 1036, + GarrisonCompleteMissionWrongFollowerType = 1037, + AlreadyUsingLfgList = 1038, + RestrictedAccountLfgListTrial = 1039, + ToyUseLimitReached = 1040, + ToyAlreadyKnown = 1041, + TransmogSetAlreadyKnown = 1042, + NotEnoughCurrency = 1043, + SpecIsDisabled = 1044, + FeatureRestrictedTrial = 1045, + CantBeObliterated = 1046, + CantBeScrapped = 1047, + CantBeRecrafted = 1048, + ArtifactRelicDoesNotMatchArtifact = 1049, + MustEquipArtifact = 1050, + CantDoThatRightNow = 1051, + AffectingCombat = 1052, + EquipmentManagerCombatSwapS = 1053, + EquipmentManagerBagsFull = 1054, + EquipmentManagerMissingItemS = 1055, + MovieRecordingWarningPerf = 1056, + MovieRecordingWarningDiskFull = 1057, + MovieRecordingWarningNoMovie = 1058, + MovieRecordingWarningRequirements = 1059, + MovieRecordingWarningCompressing = 1060, + NoChallengeModeReward = 1061, + ClaimedChallengeModeReward = 1062, + ChallengeModePeriodResetSs = 1063, + CantDoThatChallengeModeActive = 1064, + TalentFailedRestArea = 1065, + CannotAbandonLastPet = 1066, + TestCvarSetSss = 1067, + QuestTurnInFailReason = 1068, + ClaimedChallengeModeRewardOld = 1069, + TalentGrantedByAura = 1070, + ChallengeModeAlreadyComplete = 1071, + GlyphTargetNotAvailable = 1072, + PvpWarmodeToggleOn = 1073, + PvpWarmodeToggleOff = 1074, + SpellFailedLevelRequirement = 1075, + SpellFailedCantFlyHere = 1076, + BattlegroundJoinRequiresLevel = 1077, + BattlegroundJoinDisqualified = 1078, + BattlegroundJoinDisqualifiedNoName = 1079, + VoiceChatGenericUnableToConnect = 1080, + VoiceChatServiceLost = 1081, + VoiceChatChannelNameTooShort = 1082, + VoiceChatChannelNameTooLong = 1083, + VoiceChatChannelAlreadyExists = 1084, + VoiceChatTargetNotFound = 1085, + VoiceChatTooManyRequests = 1086, + VoiceChatPlayerSilenced = 1087, + VoiceChatParentalDisableAll = 1088, + VoiceChatDisabled = 1089, + NoPvpReward = 1090, + ClaimedPvpReward = 1091, + AzeriteEssenceSelectionFailedEssenceNotUnlocked = 1092, + AzeriteEssenceSelectionFailedCantRemoveEssence = 1093, + AzeriteEssenceSelectionFailedConditionFailed = 1094, + AzeriteEssenceSelectionFailedRestArea = 1095, + AzeriteEssenceSelectionFailedSlotLocked = 1096, + AzeriteEssenceSelectionFailedNotAtForge = 1097, + AzeriteEssenceSelectionFailedHeartLevelTooLow = 1098, + AzeriteEssenceSelectionFailedNotEquipped = 1099, + SocketingGenericFailure = 1100, + SocketingRequiresPunchcardredGem = 1101, + SocketingPunchcardredGemOnlyInPunchcardredslot = 1102, + SocketingRequiresPunchcardyellowGem = 1103, + SocketingPunchcardyellowGemOnlyInPunchcardyellowslot = 1104, + SocketingRequiresPunchcardblueGem = 1105, + SocketingPunchcardblueGemOnlyInPunchcardblueslot = 1106, + SocketingRequiresDominationShard = 1107, + SocketingDominationShardOnlyInDominationslot = 1108, + SocketingRequiresCypherGem = 1109, + SocketingCypherGemOnlyInCypherslot = 1110, + SocketingRequiresTinkerGem = 1111, + SocketingTinkerGemOnlyInTinkerslot = 1112, + SocketingRequiresPrimordialGem = 1113, + SocketingPrimordialGemOnlyInPrimordialslot = 1114, + SocketingRequiresFragranceGem = 1115, + SocketingFragranceGemOnlyInFragranceslot = 1116, + SocketingRequiresSingingThunderGem = 1117, + SocketingSingingthunderGemOnlyInSingingthunderslot = 1118, + SocketingRequiresSingingSeaGem = 1119, + SocketingSingingseaGemOnlyInSingingseaslot = 1120, + SocketingRequiresSingingWindGem = 1121, + SocketingSingingwindGemOnlyInSingingwindslot = 1122, + SocketingRequiresFiberGem = 1123, + SocketingFiberGemOnlyInFiberslot = 1124, + LevelLinkingResultLinked = 1125, + LevelLinkingResultUnlinked = 1126, + ClubFinderErrorPostClub = 1127, + ClubFinderErrorApplyClub = 1128, + ClubFinderErrorRespondApplicant = 1129, + ClubFinderErrorCancelApplication = 1130, + ClubFinderErrorTypeAcceptApplication = 1131, + ClubFinderErrorTypeNoInvitePermissions = 1132, + ClubFinderErrorTypeNoPostingPermissions = 1133, + ClubFinderErrorTypeApplicantList = 1134, + ClubFinderErrorTypeApplicantListNoPerm = 1135, + ClubFinderErrorTypeFinderNotAvailable = 1136, + ClubFinderErrorTypeGetPostingIds = 1137, + ClubFinderErrorTypeJoinApplication = 1138, + ClubFinderErrorTypeRealmNotEligible = 1139, + ClubFinderErrorTypeFlaggedRename = 1140, + ClubFinderErrorTypeFlaggedDescriptionChange = 1141, + ItemInteractionNotEnoughGold = 1142, + ItemInteractionNotEnoughCurrency = 1143, + ItemInteractionNoConversionOutput = 1144, + PlayerChoiceErrorPendingChoice = 1145, + SoulbindInvalidConduit = 1146, + SoulbindInvalidConduitItem = 1147, + SoulbindInvalidTalent = 1148, + SoulbindDuplicateConduit = 1149, + ActivateSoulbindS = 1150, + ActivateSoulbindFailedRestArea = 1151, + CantUseProfanity = 1152, + NotInPetBattle = 1153, + NotInNpe = 1154, + NoSpec = 1155, + NoDominationshardOverwrite = 1156, + UseWeeklyRewardsDisabled = 1157, + CrossFactionGroupJoined = 1158, + CantTargetUnfriendlyInOverworld = 1159, + EquipablespellsSlotsFull = 1160, + ItemModAppearanceGroupAlreadyKnown = 1161, + CantBulkSellItemWithRefund = 1162, + NoSoulboundItemInAccountBank = 1163, + NoRefundableItemInAccountBank = 1164, + CantDeleteInAccountBank = 1165, + NoImmediateContainerInAccountBank = 1166, + NoOpenImmediateContainerInAccountBank = 1167, + CantTradeAccountItem = 1168, + NoAccountInventoryLock = 1169, + BankNotAccessible = 1170, + TooManyAccountBankTabs = 1171, + BankTabNotUnlocked = 1172, + AccountMoneyLocked = 1173, + BankTabInvalidName = 1174, + BankTabInvalidText = 1175, + CharacterBankNotConverted = 1176, + WowLabsPartyErrorTypePartyIsFull = 1177, + WowLabsPartyErrorTypeMaxInviteSent = 1178, + WowLabsPartyErrorTypePlayerAlreadyInvited = 1179, + WowLabsPartyErrorTypePartyInviteInvalid = 1180, + WowLabsLobbyMatchmakerErrorEnterQueueFailed = 1181, + WowLabsLobbyMatchmakerErrorLeaveQueueFailed = 1182, + WowLabsSetWowLabsAreaIdFailed = 1183, + PlunderstormCannotQueue = 1184, + TargetIsSelfFoundCannotTrade = 1185, + PlayerIsSelfFoundCannotTrade = 1186, + MailRecepientIsSelfFoundCannotReceiveMail = 1187, + PlayerIsSelfFoundCannotSendMail = 1188, + PlayerIsSelfFoundCannotUseAuctionHouse = 1189, + MailTargetCannotReceiveMail = 1190, + RemixInvalidTransferRequest = 1191, + CurrencyTransferInvalidCharacter = 1192, + CurrencyTransferInvalidCurrency = 1193, + CurrencyTransferInsufficientCurrency = 1194, + CurrencyTransferMaxQuantity = 1195, + CurrencyTransferNoValidSource = 1196, + CurrencyTransferCharacterLoggedIn = 1197, + CurrencyTransferServerError = 1198, + CurrencyTransferUnmetRequirements = 1199, + CurrencyTransferTransactionInProgress = 1200, + CurrencyTransferDisabled = 1201, + RecentAllyPinServerError = 1202, } public enum SceneFlags diff --git a/Source/Framework/Constants/SupportSystemConst.cs b/Source/Framework/Constants/SupportSystemConst.cs index 225a55330..6fdb3149f 100644 --- a/Source/Framework/Constants/SupportSystemConst.cs +++ b/Source/Framework/Constants/SupportSystemConst.cs @@ -19,6 +19,10 @@ namespace Framework.Constants Calendar = 11, Mail = 12, PvP = 13, + PvPScoreboard = 14, + PvPGroupMember = 15, + CraftingOrder = 16, + RecentAlly = 17 } public enum ReportMajorCategory diff --git a/Source/Framework/Database/Databases/CharacterDatabase.cs b/Source/Framework/Database/Databases/CharacterDatabase.cs index ac7e10482..02739ee51 100644 --- a/Source/Framework/Database/Databases/CharacterDatabase.cs +++ b/Source/Framework/Database/Databases/CharacterDatabase.cs @@ -35,13 +35,13 @@ namespace Framework.Database "subject, deliver_time, expire_time, money, has_items FROM mail WHERE receiver = ? "); PrepareStatement(CharStatements.SEL_MAIL_LIST_ITEMS, "SELECT itemEntry,count FROM item_instance WHERE guid = ?"); PrepareStatement(CharStatements.SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, " + - "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + + "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.createTime, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + "c.personalTabardEmblemStyle, c.personalTabardEmblemColor, c.personalTabardBorderStyle, c.personalTabardBorderColor, c.personalTabardBackgroundColor " + "FROM characters AS c LEFT JOIN character_pet AS cp ON c.summonedPetNumber = cp.id LEFT JOIN guild_member AS gm ON c.guid = gm.guid " + "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 " + "WHERE c.account = ? AND c.deleteInfos_Name IS NULL"); PrepareStatement(CharStatements.SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, " + - "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + + "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.createTime, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + "c.personalTabardEmblemStyle, c.personalTabardEmblemColor, c.personalTabardBorderStyle, c.personalTabardBorderColor, c.personalTabardBackgroundColor, cd.genitive " + "FROM characters AS c LEFT JOIN character_pet AS cp ON c.summonedPetNumber = cp.id LEFT JOIN guild_member AS gm ON c.guid = gm.guid " + "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid " + @@ -49,13 +49,13 @@ namespace Framework.Database PrepareStatement(CharStatements.SEL_ENUM_CUSTOMIZATIONS, "SELECT cc.guid, cc.chrCustomizationOptionID, cc.chrCustomizationChoiceID FROM character_customizations cc " + "LEFT JOIN characters c ON cc.guid = c.guid WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY cc.guid, cc.chrCustomizationOptionID"); PrepareStatement(CharStatements.SEL_UNDELETE_ENUM, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, " + - "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + + "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.createTime, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + "c.personalTabardEmblemStyle, c.personalTabardEmblemColor, c.personalTabardBorderStyle, c.personalTabardBorderColor, c.personalTabardBackgroundColor " + "FROM characters AS c LEFT JOIN character_pet AS cp ON c.summonedPetNumber = cp.id LEFT JOIN guild_member AS gm ON c.guid = gm.guid " + "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 " + "WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL"); PrepareStatement(CharStatements.SEL_UNDELETE_ENUM_DECLINED_NAME, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, " + - "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + + "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level AS cpLevel, c.equipmentCache, cb.guid AS cbGuid, c.slot, c.createTime, c.logout_time, c.activeTalentGroup, c.lastLoginBuild, " + "c.personalTabardEmblemStyle, c.personalTabardEmblemColor, c.personalTabardBorderStyle, c.personalTabardBorderColor, c.personalTabardBackgroundColor, cd.genitive" + "FROM characters AS c LEFT JOIN character_pet AS cp ON c.summonedPetNumber = cp.id LEFT JOIN guild_member AS gm ON c.guid = gm.guid " + "LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid " + @@ -649,8 +649,8 @@ namespace Framework.Database PrepareStatement(CharStatements.INS_CHAR_TRAIT_ENTRIES, "INSERT INTO character_trait_entry (guid, traitConfigId, traitNodeId, traitNodeEntryId, `rank`) VALUES (?, ?, ?, ?, ?)"); PrepareStatement(CharStatements.DEL_CHAR_TRAIT_ENTRIES, "DELETE FROM character_trait_entry WHERE guid = ? AND traitConfigId = ?"); PrepareStatement(CharStatements.DEL_CHAR_TRAIT_ENTRIES_BY_CHAR, "DELETE FROM character_trait_entry WHERE guid = ?"); - PrepareStatement(CharStatements.SEL_CHAR_TRAIT_CONFIGS, "SELECT traitConfigId, type, chrSpecializationId, combatConfigFlags, localIdentifier, skillLineId, traitSystemId, `name` FROM character_trait_config WHERE guid = ?"); - PrepareStatement(CharStatements.INS_CHAR_TRAIT_CONFIGS, "INSERT INTO character_trait_config (guid, traitConfigId, type, chrSpecializationId, combatConfigFlags, localIdentifier, skillLineId, traitSystemId, `name`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); + PrepareStatement(CharStatements.SEL_CHAR_TRAIT_CONFIGS, "SELECT traitConfigId, type, chrSpecializationId, combatConfigFlags, localIdentifier, skillLineId, traitSystemId, variationId, `name` FROM character_trait_config WHERE guid = ?"); + PrepareStatement(CharStatements.INS_CHAR_TRAIT_CONFIGS, "INSERT INTO character_trait_config (guid, traitConfigId, type, chrSpecializationId, combatConfigFlags, localIdentifier, skillLineId, traitSystemId, variationId, `name`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); PrepareStatement(CharStatements.DEL_CHAR_TRAIT_CONFIGS, "DELETE FROM character_trait_config WHERE guid = ? AND traitConfigId = ?"); PrepareStatement(CharStatements.DEL_CHAR_TRAIT_CONFIGS_BY_CHAR, "DELETE FROM character_trait_config WHERE guid = ?"); diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index 22580514e..b70c31e2f 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -365,8 +365,9 @@ namespace Framework.Database // ContentTuning.db2 PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING, "SELECT ID, Flags, ExpansionID, HealthItemLevelCurveID, DamageItemLevelCurveID, " + - "HealthPrimaryStatCurveID, DamagePrimaryStatCurveID, MinLevel, MaxLevel, MinLevelType, MaxLevelType, TargetLevelDelta, TargetLevelMaxDelta, " + - "TargetLevelMin, TargetLevelMax, MinItemLevel, QuestXpMultiplier FROM content_tuning WHERE (`VerifiedBuild` > 0) = ?"); + "HealthPrimaryStatCurveID, DamagePrimaryStatCurveID, PrimaryStatScalingModPlayerDataElementCharacterID, " + + "PrimaryStatScalingModPlayerDataElementCharacterMultiplier, MinLevel, MaxLevel, MinLevelType, MaxLevelType, TargetLevelDelta, " + + "TargetLevelMaxDelta, TargetLevelMin, TargetLevelMax, MinItemLevel, QuestXpMultiplier FROM content_tuning WHERE (`VerifiedBuild` > 0) = ?"); // ContentTuningXExpected.db2 PrepareStatement(HotfixStatements.SEL_CONTENT_TUNING_X_EXPECTED, "SELECT ID, ExpectedStatModID, MinMythicPlusSeasonID, MaxMythicPlusSeasonID, " + @@ -722,8 +723,8 @@ namespace Framework.Database // ItemBonusTreeNode.db2 PrepareStatement(HotfixStatements.SEL_ITEM_BONUS_TREE_NODE, "SELECT ID, ItemContext, ChildItemBonusTreeID, ChildItemBonusListID, ChildItemLevelSelectorID, " + - "ChildItemBonusListGroupID, IblGroupPointsModSetID, MinMythicPlusLevel, MaxMythicPlusLevel, ParentItemBonusTreeID FROM item_bonus_tree_node" + - " WHERE (`VerifiedBuild` > 0) = ?"); + "ChildItemBonusListGroupID, IblGroupPointsModSetID, MinMythicPlusLevel, MaxMythicPlusLevel, ItemCreationContextGroupID, Flags, " + + "ParentItemBonusTreeID FROM item_bonus_tree_node WHERE (`VerifiedBuild` > 0) = ?"); // ItemChildEquipment.db2 PrepareStatement(HotfixStatements.SEL_ITEM_CHILD_EQUIPMENT, "SELECT ID, ParentItemID, ChildItemID, ChildItemEquipSlot FROM item_child_equipment" + @@ -737,6 +738,10 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_ITEM_CONTEXT_PICKER_ENTRY, "SELECT ID, ItemCreationContext, OrderIndex, PVal, LabelID, Flags, PlayerConditionID, " + "ItemContextPickerID FROM item_context_picker_entry WHERE (`VerifiedBuild` > 0) = ?"); + // ItemCreationContext.db2 + PrepareStatement(HotfixStatements.SEL_ITEM_CREATION_CONTEXT, "SELECT ID, ItemContext, ItemCreationContextGroupID FROM item_creation_context" + + " WHERE (`VerifiedBuild` > 0) = ?"); + // ItemCurrencyCost.db2 PrepareStatement(HotfixStatements.SEL_ITEM_CURRENCY_COST, "SELECT ID, ItemID FROM item_currency_cost WHERE (`VerifiedBuild` > 0) = ?"); @@ -808,9 +813,16 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_ITEM_NAME_DESCRIPTION_LOCALE, "SELECT ID, Description_lang FROM item_name_description_locale" + " WHERE (`VerifiedBuild` > 0) = ? AND locale = ?"); + // ItemOffsetCurve.db2 + PrepareStatement(HotfixStatements.SEL_ITEM_OFFSET_CURVE, "SELECT ID, CurveID, Offset FROM item_offset_curve WHERE (`VerifiedBuild` > 0) = ?"); + // ItemPriceBase.db2 PrepareStatement(HotfixStatements.SEL_ITEM_PRICE_BASE, "SELECT ID, ItemLevel, Armor, Weapon FROM item_price_base WHERE (`VerifiedBuild` > 0) = ?"); + // ItemScalingConfig.db2 + PrepareStatement(HotfixStatements.SEL_ITEM_SCALING_CONFIG, "SELECT ID, ItemOffsetCurveID, ItemLevel, RequiredLevel, Unknown1125 FROM item_scaling_config" + + " WHERE (`VerifiedBuild` > 0) = ?"); + // ItemSearchName.db2 PrepareStatement(HotfixStatements.SEL_ITEM_SEARCH_NAME, "SELECT ID, AllowableRace, Display, OverallQualityID, ExpansionID, MinFactionID, MinReputation, " + "AllowableClass, RequiredLevel, RequiredSkill, RequiredSkillRank, RequiredAbility, ItemLevel, Flags1, Flags2, Flags3, Flags4, Flags5" + @@ -837,12 +849,12 @@ namespace Framework.Database "StatPercentEditor10, StatModifierBonusStat1, StatModifierBonusStat2, StatModifierBonusStat3, StatModifierBonusStat4, StatModifierBonusStat5, " + "StatModifierBonusStat6, StatModifierBonusStat7, StatModifierBonusStat8, StatModifierBonusStat9, StatModifierBonusStat10, Stackable, " + "MaxCount, MinReputation, RequiredAbility, SellPrice, BuyPrice, VendorStackCount, PriceVariance, PriceRandomValue, Flags1, Flags2, Flags3, " + - "Flags4, Flags5, FactionRelated, ModifiedCraftingReagentItemID, ContentTuningID, PlayerLevelToItemLevelCurveID, ItemNameDescriptionID, " + - "RequiredTransmogHoliday, RequiredHoliday, GemProperties, SocketMatchEnchantmentId, TotemCategoryID, InstanceBound, ZoneBound1, ZoneBound2, " + - "ItemSet, LockID, PageID, ItemDelay, MinFactionID, RequiredSkillRank, RequiredSkill, ItemLevel, AllowableClass, ArtifactID, SpellWeight, " + - "SpellWeightCategory, SocketType1, SocketType2, SocketType3, SheatheType, Material, PageMaterialID, Bonding, DamageDamageType, " + - "ContainerSlots, RequiredPVPMedal, RequiredPVPRank, RequiredLevel, InventoryType, OverallQualityID FROM item_sparse" + - " WHERE (`VerifiedBuild` > 0) = ?"); + "Flags4, Flags5, FactionRelated, ModifiedCraftingReagentItemID, ContentTuningID, PlayerLevelToItemLevelCurveID, ItemLevelOffsetCurveID, " + + "ItemLevelOffsetItemLevel, ItemNameDescriptionID, RequiredTransmogHoliday, RequiredHoliday, GemProperties, SocketMatchEnchantmentId, " + + "TotemCategoryID, InstanceBound, ZoneBound1, ZoneBound2, ItemSet, LockID, PageID, ItemDelay, MinFactionID, RequiredSkillRank, RequiredSkill, " + + "ItemLevel, AllowableClass, ArtifactID, SpellWeight, SpellWeightCategory, SocketType1, SocketType2, SocketType3, SheatheType, Material, " + + "PageMaterialID, Bonding, DamageDamageType, ContainerSlots, RequiredPVPMedal, RequiredPVPRank, RequiredLevel, InventoryType, " + + "OverallQualityID FROM item_sparse WHERE (`VerifiedBuild` > 0) = ?"); PrepareStatement(HotfixStatements.SEL_ITEM_SPARSE_LOCALE, "SELECT ID, Description_lang, Display3_lang, Display2_lang, Display1_lang, Display_lang" + " FROM item_sparse_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?"); @@ -1068,19 +1080,19 @@ namespace Framework.Database " AND locale = ?"); // PlayerDataElementAccount.db2 - PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_ELEMENT_ACCOUNT, "SELECT ID, StorageIndex, Type FROM player_data_element_account" + + PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_ELEMENT_ACCOUNT, "SELECT ID, StorageIndex, Type, Unknown1125 FROM player_data_element_account" + " WHERE (`VerifiedBuild` > 0) = ?"); // PlayerDataElementCharacter.db2 - PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_ELEMENT_CHARACTER, "SELECT ID, StorageIndex, Type FROM player_data_element_character" + + PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_ELEMENT_CHARACTER, "SELECT ID, StorageIndex, Type, Unknown1125 FROM player_data_element_character" + " WHERE (`VerifiedBuild` > 0) = ?"); // PlayerDataFlagAccount.db2 - PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_FLAG_ACCOUNT, "SELECT ID, StorageIndex, Unknown1107 FROM player_data_flag_account" + + PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_FLAG_ACCOUNT, "SELECT ID, StorageIndex, Unknown1107, Unknown1125 FROM player_data_flag_account" + " WHERE (`VerifiedBuild` > 0) = ?"); // PlayerDataFlagCharacter.db2 - PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_FLAG_CHARACTER, "SELECT ID, StorageIndex, Unknown1107 FROM player_data_flag_character" + + PrepareStatement(HotfixStatements.SEL_PLAYER_DATA_FLAG_CHARACTER, "SELECT ID, StorageIndex, Unknown1107, Unknown1125 FROM player_data_flag_character" + " WHERE (`VerifiedBuild` > 0) = ?"); // PowerDisplay.db2 @@ -1483,10 +1495,11 @@ namespace Framework.Database "TraitCondAccountElementID FROM trait_cond WHERE (`VerifiedBuild` > 0) = ?"); // TraitCost.db2 - PrepareStatement(HotfixStatements.SEL_TRAIT_COST, "SELECT InternalName, ID, Amount, TraitCurrencyID FROM trait_cost WHERE (`VerifiedBuild` > 0) = ?"); + PrepareStatement(HotfixStatements.SEL_TRAIT_COST, "SELECT InternalName, ID, Amount, TraitCurrencyID, CurveID FROM trait_cost WHERE (`VerifiedBuild` > 0) = ?"); // TraitCurrency.db2 - PrepareStatement(HotfixStatements.SEL_TRAIT_CURRENCY, "SELECT ID, Type, CurrencyTypesID, Flags, Icon FROM trait_currency WHERE (`VerifiedBuild` > 0) = ?"); + PrepareStatement(HotfixStatements.SEL_TRAIT_CURRENCY, "SELECT ID, Type, CurrencyTypesID, Flags, Icon, PlayerDataElementAccountID, " + + "PlayerDataElementCharacterID FROM trait_currency WHERE (`VerifiedBuild` > 0) = ?"); // TraitCurrencySource.db2 PrepareStatement(HotfixStatements.SEL_TRAIT_CURRENCY_SOURCE, "SELECT Requirement, ID, TraitCurrencyID, Amount, QuestID, AchievementID, PlayerLevel, " + @@ -1557,6 +1570,10 @@ namespace Framework.Database PrepareStatement(HotfixStatements.SEL_TRAIT_SUB_TREE_LOCALE, "SELECT ID, Name_lang, Description_lang FROM trait_sub_tree_locale WHERE (`VerifiedBuild` > 0) = ?" + " AND locale = ?"); + // TraitSystem.db2 + PrepareStatement(HotfixStatements.SEL_TRAIT_SYSTEM, "SELECT ID, Flags, WidgetSetID, TraitChangeSpell, ItemID, VariationType FROM trait_system" + + " WHERE (`VerifiedBuild` > 0) = ?"); + // TraitTree.db2 PrepareStatement(HotfixStatements.SEL_TRAIT_TREE, "SELECT ID, TraitSystemID, Unused1000_1, FirstTraitNodeID, PlayerConditionID, Flags, Unused1000_2, " + "Unused1000_3 FROM trait_tree WHERE (`VerifiedBuild` > 0) = ?"); @@ -1611,7 +1628,8 @@ namespace Framework.Database // UiMapAssignment.db2 PrepareStatement(HotfixStatements.SEL_UI_MAP_ASSIGNMENT, "SELECT UiMinX, UiMinY, UiMaxX, UiMaxY, Region1X, Region1Y, Region1Z, Region2X, Region2Y, " + - "Region2Z, ID, UiMapID, OrderIndex, MapID, AreaID, WmoDoodadPlacementID, WmoGroupID FROM ui_map_assignment WHERE (`VerifiedBuild` > 0) = ?"); + "Region2Z, ID, UiMapID, OrderIndex, MapID, AreaID, WmoDoodadPlacementID, WmoGroupID, Unknown1125 FROM ui_map_assignment" + + " WHERE (`VerifiedBuild` > 0) = ?"); // UiMapLink.db2 PrepareStatement(HotfixStatements.SEL_UI_MAP_LINK, "SELECT UiMinX, UiMinY, UiMaxX, UiMaxY, ID, ParentUiMapID, OrderIndex, ChildUiMapID, PlayerConditionID, " + @@ -2040,6 +2058,8 @@ namespace Framework.Database SEL_ITEM_CONTEXT_PICKER_ENTRY, + SEL_ITEM_CREATION_CONTEXT, + SEL_ITEM_CURRENCY_COST, SEL_ITEM_DAMAGE_AMMO, @@ -2076,8 +2096,12 @@ namespace Framework.Database SEL_ITEM_NAME_DESCRIPTION, SEL_ITEM_NAME_DESCRIPTION_LOCALE, + SEL_ITEM_OFFSET_CURVE, + SEL_ITEM_PRICE_BASE, + SEL_ITEM_SCALING_CONFIG, + SEL_ITEM_SEARCH_NAME, SEL_ITEM_SEARCH_NAME_LOCALE, @@ -2441,6 +2465,8 @@ namespace Framework.Database SEL_TRAIT_SUB_TREE, SEL_TRAIT_SUB_TREE_LOCALE, + SEL_TRAIT_SYSTEM, + SEL_TRAIT_TREE, SEL_TRAIT_TREE_LOADOUT, diff --git a/Source/Framework/IO/ByteBuffer.cs b/Source/Framework/IO/ByteBuffer.cs index 46050fda6..5766a9cd0 100644 --- a/Source/Framework/IO/ByteBuffer.cs +++ b/Source/Framework/IO/ByteBuffer.cs @@ -351,6 +351,29 @@ namespace Framework.IO { WriteUInt32(Time.GetPackedTimeFromDateTime(DateTime.Now)); } + + public void Write(T value) + { + switch (value) + { + case sbyte v: WriteInt8(v); break; + case short v: WriteInt16(v); break; + case int v: WriteInt32(v); break; + case long v: WriteInt64(v); break; + case byte v: WriteUInt8(v); break; + case ushort v: WriteUInt16(v); break; + case uint v: WriteUInt32(v); break; + case ulong v: WriteUInt64(v); break; + case float v: WriteFloat(v); break; + case double v: WriteDouble(v); break; + case string v: WriteString(v); break; + case bool v: WriteBit(v); break; + case byte[] v: WriteBytes(v); break; + case Vector3 v: WriteVector3(v); break; + default: + throw new InvalidOperationException($"Type {typeof(T)} is not supported for writing."); + } + } #endregion public bool HasUnfinishedBitPack() diff --git a/Source/Game/Achievements/CriteriaHandler.cs b/Source/Game/Achievements/CriteriaHandler.cs index a71cae3fb..f4865121c 100644 --- a/Source/Game/Achievements/CriteriaHandler.cs +++ b/Source/Game/Achievements/CriteriaHandler.cs @@ -200,12 +200,12 @@ namespace Game.Achievements case CriteriaType.SkillRaised: uint skillvalue = referencePlayer.GetBaseSkillValue((SkillType)criteria.Entry.Asset); if (skillvalue != 0) - SetCriteriaProgress(criteria, skillvalue, referencePlayer); + SetCriteriaProgress(criteria, skillvalue, referencePlayer); break; case CriteriaType.AchieveSkillStep: uint maxSkillvalue = referencePlayer.GetPureMaxSkillValue((SkillType)criteria.Entry.Asset); if (maxSkillvalue != 0) - SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer); + SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer); break; case CriteriaType.CompleteQuestsCount: SetCriteriaProgress(criteria, (ulong)referencePlayer.GetRewardedQuestCount(), referencePlayer); @@ -253,7 +253,7 @@ namespace Game.Achievements var rewQuests = referencePlayer.GetRewardedQuests(); foreach (uint rewQuest in rewQuests) { - Quest quest = Global.ObjectMgr.GetQuestTemplate(rewQuest); + Quest quest = Global.ObjectMgr.GetQuestTemplate(rewQuest); if (quest != null && quest.QuestSortID >= 0 && quest.QuestSortID == criteria.Entry.Asset) ++counter; } @@ -3605,19 +3605,12 @@ namespace Game.Achievements { bool hasTraitNodeEntry() { - foreach (var traitConfig in referencePlayer.m_activePlayerData.TraitConfigs) - { - if ((TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat) - { - if (referencePlayer.m_activePlayerData.ActiveCombatTraitConfigID != traitConfig.ID - || !((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.ActiveForSpec)) - continue; - } - - foreach (var traitEntry in traitConfig.Entries) + TraitConfig config = referencePlayer.GetTraitConfig((int)(uint)referencePlayer.m_activePlayerData.ActiveCombatTraitConfigID); + if (config != null && ((TraitCombatConfigFlags)(int)config.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.ActiveForSpec)) + foreach (TraitEntry traitEntry in config.Entries) if (traitEntry.TraitNodeEntryID == reqValue) return true; - } + return false; } if (!hasTraitNodeEntry()) @@ -3626,21 +3619,14 @@ namespace Game.Achievements } case ModifierTreeType.PlayerHasTraitNodeEntryInActiveConfigRankGreaterOrEqualThan: // 341 { - var traitNodeEntryRank = new Func(() => + int? traitNodeEntryRank = new Func(() => { - foreach (var traitConfig in referencePlayer.m_activePlayerData.TraitConfigs) - { - if ((TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat) - { - if (referencePlayer.m_activePlayerData.ActiveCombatTraitConfigID != traitConfig.ID - || !((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.ActiveForSpec)) - continue; - } - - foreach (var traitEntry in traitConfig.Entries) + TraitConfig config = referencePlayer.GetTraitConfig((int)(uint)referencePlayer.m_activePlayerData.ActiveCombatTraitConfigID); + if (config != null && ((TraitCombatConfigFlags)(int)config.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.ActiveForSpec)) + foreach (TraitEntry traitEntry in config.Entries) if (traitEntry.TraitNodeEntryID == secondaryAsset) - return (short)traitEntry.Rank; - } + return traitEntry.Rank; + return null; })(); if (!traitNodeEntryRank.HasValue || traitNodeEntryRank < reqValue) @@ -3673,7 +3659,7 @@ namespace Game.Achievements case ModifierTreeType.PlayerHasAtLeastProfPathRanks: // 355 { uint ranks = 0; - foreach (TraitConfig traitConfig in referencePlayer.m_activePlayerData.TraitConfigs) + foreach (var (_, (traitConfig, _)) in referencePlayer.m_activePlayerData.TraitConfigs) { if ((TraitConfigType)(int)traitConfig.Type != TraitConfigType.Profession) continue; @@ -3751,7 +3737,7 @@ namespace Game.Achievements } case ModifierTreeType.PlayerHasActiveTraitSubTree: // 385 { - int traitConfigWithSubtree = referencePlayer.m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => + int traitConfigWithSubtree = referencePlayer.m_activePlayerData.TraitConfigs.FindIf(traitConfig => { if (traitConfig.Type == (int)TraitConfigType.Combat && (referencePlayer.m_activePlayerData.ActiveCombatTraitConfigID != traitConfig.ID @@ -3762,7 +3748,7 @@ namespace Game.Achievements { return traitSubTree.TraitSubTreeID == reqValue && traitSubTree.Active != 0; }) >= 0; - }); + }).Item1; if (traitConfigWithSubtree < 0) return false; break; @@ -3784,7 +3770,7 @@ namespace Game.Achievements case ModifierTreeType.PlayerDataElementAccountBetween: // 391 { var value = referencePlayer.GetDataElementAccount(reqValue); - return value >= secondaryAsset && value <= tertiaryAsset; + return value >= secondaryAsset && value <= tertiaryAsset; } case ModifierTreeType.PlayerHasCompletedQuestOrIsReadyToTurnIn: // 392 { @@ -3823,336 +3809,336 @@ namespace Game.Achievements } public class CriteriaManager : Singleton -{ - Dictionary _criteriaDataMap = new(); - - Dictionary _criteriaTrees = new(); - Dictionary _criteria = new(); - Dictionary _criteriaModifiers = new(); - - MultiMap _criteriaTreeByCriteria = new(); - - // store criterias by type to speed up lookup - MultiMap _criteriasByType = new(); - MultiMap[] _criteriasByAsset = new MultiMap[(int)CriteriaType.Count]; - MultiMap _guildCriteriasByType = new(); - MultiMap[] _scenarioCriteriasByTypeAndScenarioId = new MultiMap[(int)CriteriaType.Count]; - MultiMap _questObjectiveCriteriasByType = new(); - - MultiMap[] _criteriasByStartEvent = new MultiMap[(int)CriteriaStartEvent.Count]; - MultiMap[] _criteriasByFailEvent = new MultiMap[(int)CriteriaFailEvent.Count]; - - CriteriaManager() { - for (var i = 0; i < (int)CriteriaType.Count; ++i) + Dictionary _criteriaDataMap = new(); + + Dictionary _criteriaTrees = new(); + Dictionary _criteria = new(); + Dictionary _criteriaModifiers = new(); + + MultiMap _criteriaTreeByCriteria = new(); + + // store criterias by type to speed up lookup + MultiMap _criteriasByType = new(); + MultiMap[] _criteriasByAsset = new MultiMap[(int)CriteriaType.Count]; + MultiMap _guildCriteriasByType = new(); + MultiMap[] _scenarioCriteriasByTypeAndScenarioId = new MultiMap[(int)CriteriaType.Count]; + MultiMap _questObjectiveCriteriasByType = new(); + + MultiMap[] _criteriasByStartEvent = new MultiMap[(int)CriteriaStartEvent.Count]; + MultiMap[] _criteriasByFailEvent = new MultiMap[(int)CriteriaFailEvent.Count]; + + CriteriaManager() { - _criteriasByAsset[i] = new MultiMap(); - _scenarioCriteriasByTypeAndScenarioId[i] = new MultiMap(); - } - - for (var i = 0; i < (int)CriteriaStartEvent.Count; ++i) - _criteriasByStartEvent[i] = new(); - - for (var i = 0; i < (int)CriteriaFailEvent.Count; ++i) - _criteriasByFailEvent[i] = new(); - - } - - public void LoadCriteriaModifiersTree() - { - uint oldMSTime = Time.GetMSTime(); - - if (CliDB.ModifierTreeStorage.Empty()) - { - Log.outInfo(LogFilter.ServerLoading, "Loaded 0 criteria modifiers."); - return; - } - - // Load modifier tree nodes - foreach (var tree in CliDB.ModifierTreeStorage.Values) - { - ModifierTreeNode node = new(); - node.Entry = tree; - _criteriaModifiers[node.Entry.Id] = node; - } - - // Build tree - foreach (var treeNode in _criteriaModifiers.Values) - { - ModifierTreeNode parentNode = _criteriaModifiers.LookupByKey(treeNode.Entry.Parent); - if (parentNode != null) - parentNode.Children.Add(treeNode); - } - - Log.outInfo(LogFilter.ServerLoading, "Loaded {0} criteria modifiers in {1} ms", _criteriaModifiers.Count, Time.GetMSTimeDiffToNow(oldMSTime)); - } - - T GetEntry(Dictionary map, CriteriaTreeRecord tree) where T : new() - { - CriteriaTreeRecord cur = tree; - var obj = map.LookupByKey(tree.Id); - while (obj == null) - { - if (cur.Parent == 0) - break; - - cur = CliDB.CriteriaTreeStorage.LookupByKey(cur.Parent); - if (cur == null) - break; - - obj = map.LookupByKey(cur.Id); - } - - if (obj == null) - return default; - - return obj; - } - - public void LoadCriteriaList() - { - uint oldMSTime = Time.GetMSTime(); - - Dictionary achievementCriteriaTreeIds = new(); - foreach (AchievementRecord achievement in CliDB.AchievementStorage.Values) - if (achievement.CriteriaTree != 0) - achievementCriteriaTreeIds[achievement.CriteriaTree] = achievement; - - Dictionary scenarioCriteriaTreeIds = new(); - foreach (ScenarioStepRecord scenarioStep in CliDB.ScenarioStepStorage.Values) - { - if (scenarioStep.CriteriaTreeId != 0) - scenarioCriteriaTreeIds[scenarioStep.CriteriaTreeId] = scenarioStep; - } - - Dictionary questObjectiveCriteriaTreeIds = new(); - foreach (var pair in Global.ObjectMgr.GetQuestTemplates()) - { - foreach (QuestObjective objective in pair.Value.Objectives) + for (var i = 0; i < (int)CriteriaType.Count; ++i) { - if (objective.Type != QuestObjectiveType.CriteriaTree) + _criteriasByAsset[i] = new MultiMap(); + _scenarioCriteriasByTypeAndScenarioId[i] = new MultiMap(); + } + + for (var i = 0; i < (int)CriteriaStartEvent.Count; ++i) + _criteriasByStartEvent[i] = new(); + + for (var i = 0; i < (int)CriteriaFailEvent.Count; ++i) + _criteriasByFailEvent[i] = new(); + + } + + public void LoadCriteriaModifiersTree() + { + uint oldMSTime = Time.GetMSTime(); + + if (CliDB.ModifierTreeStorage.Empty()) + { + Log.outInfo(LogFilter.ServerLoading, "Loaded 0 criteria modifiers."); + return; + } + + // Load modifier tree nodes + foreach (var tree in CliDB.ModifierTreeStorage.Values) + { + ModifierTreeNode node = new(); + node.Entry = tree; + _criteriaModifiers[node.Entry.Id] = node; + } + + // Build tree + foreach (var treeNode in _criteriaModifiers.Values) + { + ModifierTreeNode parentNode = _criteriaModifiers.LookupByKey(treeNode.Entry.Parent); + if (parentNode != null) + parentNode.Children.Add(treeNode); + } + + Log.outInfo(LogFilter.ServerLoading, "Loaded {0} criteria modifiers in {1} ms", _criteriaModifiers.Count, Time.GetMSTimeDiffToNow(oldMSTime)); + } + + T GetEntry(Dictionary map, CriteriaTreeRecord tree) where T : new() + { + CriteriaTreeRecord cur = tree; + var obj = map.LookupByKey(tree.Id); + while (obj == null) + { + if (cur.Parent == 0) + break; + + cur = CliDB.CriteriaTreeStorage.LookupByKey(cur.Parent); + if (cur == null) + break; + + obj = map.LookupByKey(cur.Id); + } + + if (obj == null) + return default; + + return obj; + } + + public void LoadCriteriaList() + { + uint oldMSTime = Time.GetMSTime(); + + Dictionary achievementCriteriaTreeIds = new(); + foreach (AchievementRecord achievement in CliDB.AchievementStorage.Values) + if (achievement.CriteriaTree != 0) + achievementCriteriaTreeIds[achievement.CriteriaTree] = achievement; + + Dictionary scenarioCriteriaTreeIds = new(); + foreach (ScenarioStepRecord scenarioStep in CliDB.ScenarioStepStorage.Values) + { + if (scenarioStep.CriteriaTreeId != 0) + scenarioCriteriaTreeIds[scenarioStep.CriteriaTreeId] = scenarioStep; + } + + Dictionary questObjectiveCriteriaTreeIds = new(); + foreach (var pair in Global.ObjectMgr.GetQuestTemplates()) + { + foreach (QuestObjective objective in pair.Value.Objectives) + { + if (objective.Type != QuestObjectiveType.CriteriaTree) + continue; + + if (objective.ObjectID != 0) + questObjectiveCriteriaTreeIds[(uint)objective.ObjectID] = objective; + } + } + + // Load criteria tree nodes + foreach (CriteriaTreeRecord tree in CliDB.CriteriaTreeStorage.Values) + { + // Find linked achievement + AchievementRecord achievement = GetEntry(achievementCriteriaTreeIds, tree); + ScenarioStepRecord scenarioStep = GetEntry(scenarioCriteriaTreeIds, tree); + QuestObjective questObjective = GetEntry(questObjectiveCriteriaTreeIds, tree); + if (achievement == null && scenarioStep == null && questObjective == null) continue; - if (objective.ObjectID != 0) - questObjectiveCriteriaTreeIds[(uint)objective.ObjectID] = objective; - } - } + CriteriaTree criteriaTree = new(); + criteriaTree.Id = tree.Id; + criteriaTree.Achievement = achievement; + criteriaTree.ScenarioStep = scenarioStep; + criteriaTree.QuestObjective = questObjective; + criteriaTree.Entry = tree; - // Load criteria tree nodes - foreach (CriteriaTreeRecord tree in CliDB.CriteriaTreeStorage.Values) - { - // Find linked achievement - AchievementRecord achievement = GetEntry(achievementCriteriaTreeIds, tree); - ScenarioStepRecord scenarioStep = GetEntry(scenarioCriteriaTreeIds, tree); - QuestObjective questObjective = GetEntry(questObjectiveCriteriaTreeIds, tree); - if (achievement == null && scenarioStep == null && questObjective == null) - continue; - - CriteriaTree criteriaTree = new(); - criteriaTree.Id = tree.Id; - criteriaTree.Achievement = achievement; - criteriaTree.ScenarioStep = scenarioStep; - criteriaTree.QuestObjective = questObjective; - criteriaTree.Entry = tree; - - _criteriaTrees[criteriaTree.Entry.Id] = criteriaTree; - } - - // Build tree - foreach (var pair in _criteriaTrees) - { - CriteriaTree parent = _criteriaTrees.LookupByKey(pair.Value.Entry.Parent); - if (parent != null) - parent.Children.Add(pair.Value); - - if (CliDB.CriteriaStorage.HasRecord(pair.Value.Entry.CriteriaID)) - _criteriaTreeByCriteria.Add(pair.Value.Entry.CriteriaID, pair.Value); - } - - for (var i = 0; i < (int)CriteriaFailEvent.Count; ++i) - _criteriasByFailEvent[i] = new MultiMap(); - - // Load criteria - uint criterias = 0; - uint guildCriterias = 0; - uint scenarioCriterias = 0; - uint questObjectiveCriterias = 0; - foreach (CriteriaRecord criteriaEntry in CliDB.CriteriaStorage.Values) - { - Cypher.Assert(criteriaEntry.Type < CriteriaType.Count, $"CriteriaType.Count must be greater than or equal to {criteriaEntry.Type + 1} but is currently equal to {CriteriaType.Count}"); - Cypher.Assert(criteriaEntry.StartEvent < (byte)CriteriaStartEvent.Count, $"CriteriaStartEvent.Count must be greater than or equal to {criteriaEntry.StartEvent + 1} but is currently equal to {CriteriaStartEvent.Count}"); - Cypher.Assert(criteriaEntry.FailEvent < (byte)CriteriaFailEvent.Count, $"CriteriaFailEvent.Count must be greater than or equal to {criteriaEntry.FailEvent + 1} but is currently equal to {CriteriaFailEvent.Count}"); - - var treeList = _criteriaTreeByCriteria.LookupByKey(criteriaEntry.Id); - if (treeList.Empty()) - continue; - - Criteria criteria = new(); - criteria.Id = criteriaEntry.Id; - criteria.Entry = criteriaEntry; - criteria.Modifier = _criteriaModifiers.LookupByKey(criteriaEntry.ModifierTreeId); - - _criteria[criteria.Id] = criteria; - - List scenarioIds = new(); - foreach (CriteriaTree tree in treeList) - { - tree.Criteria = criteria; - - AchievementRecord achievement = tree.Achievement; - if (achievement != null) - { - if (achievement.Flags.HasAnyFlag(AchievementFlags.Guild)) - criteria.FlagsCu |= CriteriaFlagsCu.Guild; - else if (achievement.Flags.HasAnyFlag(AchievementFlags.Account)) - criteria.FlagsCu |= CriteriaFlagsCu.Account; - else - criteria.FlagsCu |= CriteriaFlagsCu.Player; - } - else if (tree.ScenarioStep != null) - { - criteria.FlagsCu |= CriteriaFlagsCu.Scenario; - scenarioIds.Add(tree.ScenarioStep.ScenarioID); - } - else if (tree.QuestObjective != null) - criteria.FlagsCu |= CriteriaFlagsCu.QuestObjective; + _criteriaTrees[criteriaTree.Entry.Id] = criteriaTree; } - if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.Player | CriteriaFlagsCu.Account)) + // Build tree + foreach (var pair in _criteriaTrees) { - ++criterias; - _criteriasByType.Add(criteriaEntry.Type, criteria); - if (IsCriteriaTypeStoredByAsset(criteriaEntry.Type)) + CriteriaTree parent = _criteriaTrees.LookupByKey(pair.Value.Entry.Parent); + if (parent != null) + parent.Children.Add(pair.Value); + + if (CliDB.CriteriaStorage.HasRecord(pair.Value.Entry.CriteriaID)) + _criteriaTreeByCriteria.Add(pair.Value.Entry.CriteriaID, pair.Value); + } + + for (var i = 0; i < (int)CriteriaFailEvent.Count; ++i) + _criteriasByFailEvent[i] = new MultiMap(); + + // Load criteria + uint criterias = 0; + uint guildCriterias = 0; + uint scenarioCriterias = 0; + uint questObjectiveCriterias = 0; + foreach (CriteriaRecord criteriaEntry in CliDB.CriteriaStorage.Values) + { + Cypher.Assert(criteriaEntry.Type < CriteriaType.Count, $"CriteriaType.Count must be greater than or equal to {criteriaEntry.Type + 1} but is currently equal to {CriteriaType.Count}"); + Cypher.Assert(criteriaEntry.StartEvent < (byte)CriteriaStartEvent.Count, $"CriteriaStartEvent.Count must be greater than or equal to {criteriaEntry.StartEvent + 1} but is currently equal to {CriteriaStartEvent.Count}"); + Cypher.Assert(criteriaEntry.FailEvent < (byte)CriteriaFailEvent.Count, $"CriteriaFailEvent.Count must be greater than or equal to {criteriaEntry.FailEvent + 1} but is currently equal to {CriteriaFailEvent.Count}"); + + var treeList = _criteriaTreeByCriteria.LookupByKey(criteriaEntry.Id); + if (treeList.Empty()) + continue; + + Criteria criteria = new(); + criteria.Id = criteriaEntry.Id; + criteria.Entry = criteriaEntry; + criteria.Modifier = _criteriaModifiers.LookupByKey(criteriaEntry.ModifierTreeId); + + _criteria[criteria.Id] = criteria; + + List scenarioIds = new(); + foreach (CriteriaTree tree in treeList) { - if (criteriaEntry.Type != CriteriaType.RevealWorldMapOverlay) - _criteriasByAsset[(int)criteriaEntry.Type].Add(criteriaEntry.Asset, criteria); - else + tree.Criteria = criteria; + + AchievementRecord achievement = tree.Achievement; + if (achievement != null) { - var worldOverlayEntry = CliDB.WorldMapOverlayStorage.LookupByKey(criteriaEntry.Asset); - if (worldOverlayEntry == null) - break; + if (achievement.Flags.HasAnyFlag(AchievementFlags.Guild)) + criteria.FlagsCu |= CriteriaFlagsCu.Guild; + else if (achievement.Flags.HasAnyFlag(AchievementFlags.Account)) + criteria.FlagsCu |= CriteriaFlagsCu.Account; + else + criteria.FlagsCu |= CriteriaFlagsCu.Player; + } + else if (tree.ScenarioStep != null) + { + criteria.FlagsCu |= CriteriaFlagsCu.Scenario; + scenarioIds.Add(tree.ScenarioStep.ScenarioID); + } + else if (tree.QuestObjective != null) + criteria.FlagsCu |= CriteriaFlagsCu.QuestObjective; + } - for (byte j = 0; j < SharedConst.MaxWorldMapOverlayArea; ++j) + if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.Player | CriteriaFlagsCu.Account)) + { + ++criterias; + _criteriasByType.Add(criteriaEntry.Type, criteria); + if (IsCriteriaTypeStoredByAsset(criteriaEntry.Type)) + { + if (criteriaEntry.Type != CriteriaType.RevealWorldMapOverlay) + _criteriasByAsset[(int)criteriaEntry.Type].Add(criteriaEntry.Asset, criteria); + else { - if (worldOverlayEntry.AreaID[j] != 0) + var worldOverlayEntry = CliDB.WorldMapOverlayStorage.LookupByKey(criteriaEntry.Asset); + if (worldOverlayEntry == null) + break; + + for (byte j = 0; j < SharedConst.MaxWorldMapOverlayArea; ++j) { - bool valid = true; - for (byte i = 0; i < j; ++i) - if (worldOverlayEntry.AreaID[j] == worldOverlayEntry.AreaID[i]) - valid = false; - if (valid) - _criteriasByAsset[(int)criteriaEntry.Type].Add(worldOverlayEntry.AreaID[j], criteria); + if (worldOverlayEntry.AreaID[j] != 0) + { + bool valid = true; + for (byte i = 0; i < j; ++i) + if (worldOverlayEntry.AreaID[j] == worldOverlayEntry.AreaID[i]) + valid = false; + if (valid) + _criteriasByAsset[(int)criteriaEntry.Type].Add(worldOverlayEntry.AreaID[j], criteria); + } } } } } + + if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.Guild)) + { + ++guildCriterias; + _guildCriteriasByType.Add(criteriaEntry.Type, criteria); + } + + if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.Scenario)) + { + ++scenarioCriterias; + foreach (uint scenarioId in scenarioIds) + _scenarioCriteriasByTypeAndScenarioId[(int)criteriaEntry.Type].Add(scenarioId, criteria); + } + + if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.QuestObjective)) + { + ++questObjectiveCriterias; + _questObjectiveCriteriasByType.Add(criteriaEntry.Type, criteria); + } + + if (criteriaEntry.StartEvent != 0) + _criteriasByStartEvent[criteriaEntry.StartEvent].Add((int)criteriaEntry.StartAsset, criteria); + + if (criteriaEntry.FailEvent != 0) + _criteriasByFailEvent[criteriaEntry.FailEvent].Add((int)criteriaEntry.FailAsset, criteria); } - if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.Guild)) - { - ++guildCriterias; - _guildCriteriasByType.Add(criteriaEntry.Type, criteria); - } - - if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.Scenario)) - { - ++scenarioCriterias; - foreach (uint scenarioId in scenarioIds) - _scenarioCriteriasByTypeAndScenarioId[(int)criteriaEntry.Type].Add(scenarioId, criteria); - } - - if (criteria.FlagsCu.HasAnyFlag(CriteriaFlagsCu.QuestObjective)) - { - ++questObjectiveCriterias; - _questObjectiveCriteriasByType.Add(criteriaEntry.Type, criteria); - } - - if (criteriaEntry.StartEvent != 0) - _criteriasByStartEvent[criteriaEntry.StartEvent].Add((int)criteriaEntry.StartAsset, criteria); - - if (criteriaEntry.FailEvent != 0) - _criteriasByFailEvent[criteriaEntry.FailEvent].Add((int)criteriaEntry.FailAsset, criteria); + Log.outInfo(LogFilter.ServerLoading, $"Loaded {criterias} criteria, {guildCriterias} guild criteria, {scenarioCriterias} scenario criteria and {questObjectiveCriterias} quest objective criteria in {Time.GetMSTimeDiffToNow(oldMSTime)} ms."); } - Log.outInfo(LogFilter.ServerLoading, $"Loaded {criterias} criteria, {guildCriterias} guild criteria, {scenarioCriterias} scenario criteria and {questObjectiveCriterias} quest objective criteria in {Time.GetMSTimeDiffToNow(oldMSTime)} ms."); - } - - public void LoadCriteriaData() - { - uint oldMSTime = Time.GetMSTime(); - - _criteriaDataMap.Clear(); // need for reload case - - SQLResult result = DB.World.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM criteria_data"); - if (result.IsEmpty()) + public void LoadCriteriaData() { - Log.outInfo(LogFilter.ServerLoading, "Loaded 0 additional criteria data. DB table `criteria_data` is empty."); - return; + uint oldMSTime = Time.GetMSTime(); + + _criteriaDataMap.Clear(); // need for reload case + + SQLResult result = DB.World.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM criteria_data"); + if (result.IsEmpty()) + { + Log.outInfo(LogFilter.ServerLoading, "Loaded 0 additional criteria data. DB table `criteria_data` is empty."); + return; + } + + uint count = 0; + do + { + uint criteria_id = result.Read(0); + + Criteria criteria = GetCriteria(criteria_id); + if (criteria == null) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` contains data for non-existing criteria (Entry: {0}). Ignored.", criteria_id); + continue; + } + + CriteriaDataType dataType = (CriteriaDataType)result.Read(1); + string scriptName = result.Read(4); + uint scriptId = 0; + if (!scriptName.IsEmpty()) + { + if (dataType != CriteriaDataType.Script) + Log.outError(LogFilter.Sql, "Table `criteria_data` contains a ScriptName for non-scripted data type (Entry: {0}, type {1}), useless data.", criteria_id, dataType); + else + scriptId = Global.ObjectMgr.GetScriptId(scriptName); + } + + CriteriaData data = new(dataType, result.Read(2), result.Read(3), scriptId); + + if (!data.IsValid(criteria)) + continue; + + // this will allocate empty data set storage + CriteriaDataSet dataSet = new(); + dataSet.SetCriteriaId(criteria_id); + + // add real data only for not NONE data types + if (data.DataType != CriteriaDataType.None) + dataSet.Add(data); + + _criteriaDataMap[criteria_id] = dataSet; + // counting data by and data types + ++count; + } + while (result.NextRow()); + + Log.outInfo(LogFilter.ServerLoading, "Loaded {0} additional criteria data in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } - uint count = 0; - do + public CriteriaTree GetCriteriaTree(uint criteriaTreeId) { - uint criteria_id = result.Read(0); - - Criteria criteria = GetCriteria(criteria_id); - if (criteria == null) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` contains data for non-existing criteria (Entry: {0}). Ignored.", criteria_id); - continue; - } - - CriteriaDataType dataType = (CriteriaDataType)result.Read(1); - string scriptName = result.Read(4); - uint scriptId = 0; - if (!scriptName.IsEmpty()) - { - if (dataType != CriteriaDataType.Script) - Log.outError(LogFilter.Sql, "Table `criteria_data` contains a ScriptName for non-scripted data type (Entry: {0}, type {1}), useless data.", criteria_id, dataType); - else - scriptId = Global.ObjectMgr.GetScriptId(scriptName); - } - - CriteriaData data = new(dataType, result.Read(2), result.Read(3), scriptId); - - if (!data.IsValid(criteria)) - continue; - - // this will allocate empty data set storage - CriteriaDataSet dataSet = new(); - dataSet.SetCriteriaId(criteria_id); - - // add real data only for not NONE data types - if (data.DataType != CriteriaDataType.None) - dataSet.Add(data); - - _criteriaDataMap[criteria_id] = dataSet; - // counting data by and data types - ++count; + return _criteriaTrees.LookupByKey(criteriaTreeId); } - while (result.NextRow()); - Log.outInfo(LogFilter.ServerLoading, "Loaded {0} additional criteria data in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); - } + public Criteria GetCriteria(uint criteriaId) + { + return _criteria.LookupByKey(criteriaId); + } - public CriteriaTree GetCriteriaTree(uint criteriaTreeId) - { - return _criteriaTrees.LookupByKey(criteriaTreeId); - } + public ModifierTreeNode GetModifierTree(uint modifierTreeId) + { + return _criteriaModifiers.LookupByKey(modifierTreeId); + } - public Criteria GetCriteria(uint criteriaId) - { - return _criteria.LookupByKey(criteriaId); - } - - public ModifierTreeNode GetModifierTree(uint modifierTreeId) - { - return _criteriaModifiers.LookupByKey(modifierTreeId); - } - - public static CriteriaType[] GetRetroactivelyUpdateableCriteriaTypes() => - [ - CriteriaType.CompleteResearchProject, + public static CriteriaType[] GetRetroactivelyUpdateableCriteriaTypes() => + [ + CriteriaType.CompleteResearchProject, CriteriaType.CompleteAnyResearchProject, CriteriaType.ReachLevel, CriteriaType.SkillRaised, @@ -4204,760 +4190,760 @@ namespace Game.Achievements CriteriaType.EarnAchievementPoints, CriteriaType.BattlePetAchievementPointsEarned, CriteriaType.EarnAchievement // criteria possibly completed by retroactive scan, must be last - ]; + ]; - bool IsCriteriaTypeStoredByAsset(CriteriaType type) - { - switch (type) + bool IsCriteriaTypeStoredByAsset(CriteriaType type) { - case CriteriaType.KillCreature: - case CriteriaType.WinBattleground: - case CriteriaType.SkillRaised: - case CriteriaType.EarnAchievement: - case CriteriaType.CompleteQuestsInZone: - case CriteriaType.ParticipateInBattleground: - case CriteriaType.KilledByCreature: - case CriteriaType.CompleteQuest: - case CriteriaType.BeSpellTarget: - case CriteriaType.CastSpell: - case CriteriaType.TrackedWorldStateUIModified: - case CriteriaType.PVPKillInArea: - case CriteriaType.LearnOrKnowSpell: - case CriteriaType.AcquireItem: - case CriteriaType.AchieveSkillStep: - case CriteriaType.UseItem: - case CriteriaType.LootItem: - case CriteriaType.RevealWorldMapOverlay: - case CriteriaType.ReputationGained: - case CriteriaType.EquipItemInSlot: - case CriteriaType.DeliverKillingBlowToClass: - case CriteriaType.DeliverKillingBlowToRace: - case CriteriaType.DoEmote: - case CriteriaType.EquipItem: - case CriteriaType.UseGameobject: - case CriteriaType.GainAura: - case CriteriaType.CatchFishInFishingHole: - case CriteriaType.LearnSpellFromSkillLine: - case CriteriaType.DefeatDungeonEncounterWhileElegibleForLoot: - case CriteriaType.GetLootByType: - case CriteriaType.LandTargetedSpellOnTarget: - case CriteriaType.LearnTradeskillSkillLine: - case CriteriaType.DefeatDungeonEncounter: - case CriteriaType.LearnToy: - case CriteriaType.LearnAnyTransmog: - return true; - default: - return false; - } - } - - public List GetPlayerCriteriaByType(CriteriaType type, uint asset) - { - if (asset != 0 && IsCriteriaTypeStoredByAsset(type)) - { - if (_criteriasByAsset[(int)type].ContainsKey(asset)) - return _criteriasByAsset[(int)type][asset]; - - return new List(); + switch (type) + { + case CriteriaType.KillCreature: + case CriteriaType.WinBattleground: + case CriteriaType.SkillRaised: + case CriteriaType.EarnAchievement: + case CriteriaType.CompleteQuestsInZone: + case CriteriaType.ParticipateInBattleground: + case CriteriaType.KilledByCreature: + case CriteriaType.CompleteQuest: + case CriteriaType.BeSpellTarget: + case CriteriaType.CastSpell: + case CriteriaType.TrackedWorldStateUIModified: + case CriteriaType.PVPKillInArea: + case CriteriaType.LearnOrKnowSpell: + case CriteriaType.AcquireItem: + case CriteriaType.AchieveSkillStep: + case CriteriaType.UseItem: + case CriteriaType.LootItem: + case CriteriaType.RevealWorldMapOverlay: + case CriteriaType.ReputationGained: + case CriteriaType.EquipItemInSlot: + case CriteriaType.DeliverKillingBlowToClass: + case CriteriaType.DeliverKillingBlowToRace: + case CriteriaType.DoEmote: + case CriteriaType.EquipItem: + case CriteriaType.UseGameobject: + case CriteriaType.GainAura: + case CriteriaType.CatchFishInFishingHole: + case CriteriaType.LearnSpellFromSkillLine: + case CriteriaType.DefeatDungeonEncounterWhileElegibleForLoot: + case CriteriaType.GetLootByType: + case CriteriaType.LandTargetedSpellOnTarget: + case CriteriaType.LearnTradeskillSkillLine: + case CriteriaType.DefeatDungeonEncounter: + case CriteriaType.LearnToy: + case CriteriaType.LearnAnyTransmog: + return true; + default: + return false; + } } - return _criteriasByType.LookupByKey(type); - } - - public List GetScenarioCriteriaByTypeAndScenario(CriteriaType type, uint scenarioId) - { - return _scenarioCriteriasByTypeAndScenarioId[(int)type].LookupByKey(scenarioId); - } - - public MultiMap GetCriteriaByStartEvent(CriteriaStartEvent startEvent) - { - return _criteriasByStartEvent[(int)startEvent]; - } - - public List GetCriteriaByStartEvent(CriteriaStartEvent startEvent, int asset) - { - return _criteriasByStartEvent[(int)startEvent].LookupByKey(asset); - } - - public MultiMap GetCriteriaByFailEvent(CriteriaFailEvent failEvent) - { - return _criteriasByFailEvent[(int)failEvent]; - } - - public List GetCriteriaByFailEvent(CriteriaFailEvent failEvent, int asset) - { - return _criteriasByFailEvent[(int)failEvent].LookupByKey(asset); - } - - public List GetGuildCriteriaByType(CriteriaType type) - { - return _guildCriteriasByType.LookupByKey(type); - } - - public List GetQuestObjectiveCriteriaByType(CriteriaType type) - { - return _questObjectiveCriteriasByType[type]; - } - - public List GetCriteriaTreesByCriteria(uint criteriaId) - { - return _criteriaTreeByCriteria.LookupByKey(criteriaId); - } - - public CriteriaDataSet GetCriteriaDataSet(Criteria criteria) - { - return _criteriaDataMap.LookupByKey(criteria.Id); - } - - public static bool IsGroupCriteriaType(CriteriaType type) - { - switch (type) + public List GetPlayerCriteriaByType(CriteriaType type, uint asset) { - case CriteriaType.KillCreature: - case CriteriaType.WinBattleground: - case CriteriaType.BeSpellTarget: // NYI - case CriteriaType.WinAnyRankedArena: - case CriteriaType.GainAura: // NYI - case CriteriaType.WinAnyBattleground: // NYI - return true; - default: - break; + if (asset != 0 && IsCriteriaTypeStoredByAsset(type)) + { + if (_criteriasByAsset[(int)type].ContainsKey(asset)) + return _criteriasByAsset[(int)type][asset]; + + return new List(); + } + + return _criteriasByType.LookupByKey(type); } - return false; - } - - public static void WalkCriteriaTree(CriteriaTree tree, Action func) - { - foreach (CriteriaTree node in tree.Children) - WalkCriteriaTree(node, func); - - func(tree); - } -} - -public class ModifierTreeNode -{ - public ModifierTreeRecord Entry; - public List Children = new(); -} - -public class Criteria -{ - public uint Id; - public CriteriaRecord Entry; - public ModifierTreeNode Modifier; - public CriteriaFlagsCu FlagsCu; -} - -public class CriteriaTree -{ - public uint Id; - public CriteriaTreeRecord Entry; - public AchievementRecord Achievement; - public ScenarioStepRecord ScenarioStep; - public QuestObjective QuestObjective; - public Criteria Criteria; - public List Children = new(); -} - -public class CriteriaProgress -{ - public ulong Counter; - public long Date; // latest update time. - public ObjectGuid PlayerGUID; // GUID of the player that completed this criteria (guild achievements) - public bool Changed; -} - -[StructLayout(LayoutKind.Explicit)] -public class CriteriaData -{ - [FieldOffset(0)] - public CriteriaDataType DataType; - - [FieldOffset(4)] - public CreatureStruct Creature; - - [FieldOffset(4)] - public ClassRaceStruct ClassRace; - - [FieldOffset(4)] - public HealthStruct Health; - - [FieldOffset(4)] - public AuraStruct Aura; - - [FieldOffset(4)] - public ValueStruct Value; - - [FieldOffset(4)] - public LevelStruct Level; - - [FieldOffset(4)] - public GenderStruct Gender; - - [FieldOffset(4)] - public MapPlayersStruct MapPlayers; - - [FieldOffset(4)] - public TeamStruct TeamId; - - [FieldOffset(4)] - public DrunkStruct Drunk; - - [FieldOffset(4)] - public HolidayStruct Holiday; - - [FieldOffset(4)] - public BgLossTeamScoreStruct BattlegroundScore; - - [FieldOffset(4)] - public EquippedItemStruct EquippedItem; - - [FieldOffset(4)] - public MapIdStruct MapId; - - [FieldOffset(4)] - public KnownTitleStruct KnownTitle; - - [FieldOffset(4)] - public GameEventStruct GameEvent; - - [FieldOffset(4)] - public ItemQualityStruct itemQuality; - - [FieldOffset(4)] - public RawStruct Raw; - - [FieldOffset(12)] - public uint ScriptId; - - public CriteriaData() - { - DataType = CriteriaDataType.None; - - Raw.Value1 = 0; - Raw.Value2 = 0; - ScriptId = 0; - } - - public CriteriaData(CriteriaDataType _dataType, uint _value1, uint _value2, uint _scriptId) - { - DataType = _dataType; - - Raw.Value1 = _value1; - Raw.Value2 = _value2; - ScriptId = _scriptId; - } - - public bool IsValid(Criteria criteria) - { - if (DataType >= CriteriaDataType.Max) + public List GetScenarioCriteriaByTypeAndScenario(CriteriaType type, uint scenarioId) { - Log.outError(LogFilter.Sql, "Table `criteria_data` for criteria (Entry: {0}) has wrong data type ({1}), ignored.", criteria.Id, DataType); + return _scenarioCriteriasByTypeAndScenarioId[(int)type].LookupByKey(scenarioId); + } + + public MultiMap GetCriteriaByStartEvent(CriteriaStartEvent startEvent) + { + return _criteriasByStartEvent[(int)startEvent]; + } + + public List GetCriteriaByStartEvent(CriteriaStartEvent startEvent, int asset) + { + return _criteriasByStartEvent[(int)startEvent].LookupByKey(asset); + } + + public MultiMap GetCriteriaByFailEvent(CriteriaFailEvent failEvent) + { + return _criteriasByFailEvent[(int)failEvent]; + } + + public List GetCriteriaByFailEvent(CriteriaFailEvent failEvent, int asset) + { + return _criteriasByFailEvent[(int)failEvent].LookupByKey(asset); + } + + public List GetGuildCriteriaByType(CriteriaType type) + { + return _guildCriteriasByType.LookupByKey(type); + } + + public List GetQuestObjectiveCriteriaByType(CriteriaType type) + { + return _questObjectiveCriteriasByType[type]; + } + + public List GetCriteriaTreesByCriteria(uint criteriaId) + { + return _criteriaTreeByCriteria.LookupByKey(criteriaId); + } + + public CriteriaDataSet GetCriteriaDataSet(Criteria criteria) + { + return _criteriaDataMap.LookupByKey(criteria.Id); + } + + public static bool IsGroupCriteriaType(CriteriaType type) + { + switch (type) + { + case CriteriaType.KillCreature: + case CriteriaType.WinBattleground: + case CriteriaType.BeSpellTarget: // NYI + case CriteriaType.WinAnyRankedArena: + case CriteriaType.GainAura: // NYI + case CriteriaType.WinAnyBattleground: // NYI + return true; + default: + break; + } + return false; } - switch (criteria.Entry.Type) + public static void WalkCriteriaTree(CriteriaTree tree, Action func) { - case CriteriaType.KillCreature: - case CriteriaType.KillAnyCreature: - case CriteriaType.WinBattleground: - case CriteriaType.MaxDistFallenWithoutDying: - case CriteriaType.CompleteQuest: // only hardcoded list - case CriteriaType.CastSpell: - case CriteriaType.WinAnyRankedArena: - case CriteriaType.DoEmote: - case CriteriaType.KillPlayer: - case CriteriaType.WinDuel: - case CriteriaType.GetLootByType: - case CriteriaType.LandTargetedSpellOnTarget: - case CriteriaType.BeSpellTarget: - case CriteriaType.GainAura: - case CriteriaType.EquipItemInSlot: - case CriteriaType.RollNeed: - case CriteriaType.RollGreed: - case CriteriaType.TrackedWorldStateUIModified: - case CriteriaType.EarnHonorableKill: - case CriteriaType.CompleteDailyQuest: // only Children's Week achievements - case CriteriaType.UseItem: // only Children's Week achievements - case CriteriaType.DeliveredKillingBlow: - case CriteriaType.ReachLevel: - case CriteriaType.Login: - case CriteriaType.LootAnyItem: - case CriteriaType.ObtainAnyItem: - break; - default: - if (DataType != CriteriaDataType.Script) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` has data for non-supported criteria type (Entry: {0} Type: {1}), ignored.", criteria.Id, (CriteriaType)criteria.Entry.Type); - return false; - } - break; - } + foreach (CriteriaTree node in tree.Children) + WalkCriteriaTree(node, func); - switch (DataType) - { - case CriteriaDataType.None: - case CriteriaDataType.InstanceScript: - return true; - case CriteriaDataType.TCreature: - if (Creature.Id == 0 || Global.ObjectMgr.GetCreatureTemplate(Creature.Id) == null) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_CREATURE ({2}) has non-existing creature id in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Creature.Id); - return false; - } - return true; - case CriteriaDataType.TPlayerClassRace: - if (ClassRace.ClassId == 0 && ClassRace.RaceId == 0) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) must not have 0 in either value field, ignored.", - criteria.Id, criteria.Entry.Type, DataType); - return false; - } - if (ClassRace.ClassId != 0 && ((1 << (int)(ClassRace.ClassId - 1)) & (int)Class.ClassMaskAllPlayable) == 0) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) has non-existing class in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, ClassRace.ClassId); - return false; - } - if (!RaceMask.AllPlayable.HasRace((Race)ClassRace.RaceId)) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, ClassRace.RaceId); - return false; - } - return true; - case CriteriaDataType.TPlayerLessHealth: - if (Health.Percent < 1 || Health.Percent > 100) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH ({2}) has wrong percent value in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Health.Percent); - return false; - } - return true; - case CriteriaDataType.SAura: - case CriteriaDataType.TAura: - { - SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(Aura.SpellId, Difficulty.None); - if (spellEntry == null) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type {2} has wrong spell id in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Aura.SpellId); - return false; - } - if (spellEntry.GetEffects().Count <= Aura.EffectIndex) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type {2} has wrong spell effect index in value2 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Aura.EffectIndex); - return false; - } - if (spellEntry.GetEffect(Aura.EffectIndex).ApplyAuraName == 0) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type {2} has non-aura spell effect (ID: {3} Effect: {4}), ignores.", - criteria.Id, criteria.Entry.Type, DataType, Aura.SpellId, Aura.EffectIndex); - return false; - } - return true; - } - case CriteriaDataType.Value: - if (Value.ComparisonType >= (int)ComparisionType.Max) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_VALUE ({2}) has wrong ComparisionType in value2 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Value.ComparisonType); - return false; - } - return true; - case CriteriaDataType.TLevel: - if (Level.Min > SharedConst.GTMaxLevel) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_LEVEL ({2}) has wrong minlevel in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Level.Min); - return false; - } - return true; - case CriteriaDataType.TGender: - if (Gender.Gender > (int)Framework.Constants.Gender.None) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_GENDER ({2}) has wrong gender in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Gender.Gender); - return false; - } - return true; - case CriteriaDataType.Script: - if (ScriptId == 0) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_SCRIPT ({2}) does not have ScriptName set, ignored.", - criteria.Id, criteria.Entry.Type, DataType); - return false; - } - return true; - case CriteriaDataType.MapPlayerCount: - if (MapPlayers.MaxCount <= 0) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT ({2}) has wrong max players count in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, MapPlayers.MaxCount); - return false; - } - return true; - case CriteriaDataType.TTeam: - if (TeamId.Team != (int)Team.Alliance && TeamId.Team != (int)Team.Horde) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_TEAM ({2}) has unknown team in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, TeamId.Team); - return false; - } - return true; - case CriteriaDataType.SDrunk: - if (Drunk.State >= 4) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_DRUNK ({2}) has unknown drunken state in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Drunk.State); - return false; - } - return true; - case CriteriaDataType.Holiday: - if (!CliDB.HolidaysStorage.ContainsKey(Holiday.Id)) - { - Log.outError(LogFilter.Sql, "Table `criteria_data`(Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_HOLIDAY ({2}) has unknown holiday in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, Holiday.Id); - return false; - } - return true; - case CriteriaDataType.GameEvent: - { - var events = Global.GameEventMgr.GetEventMap(); - if (GameEvent.Id < 1 || GameEvent.Id >= events.Length) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_GAME_EVENT ({2}) has unknown game_event in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, GameEvent.Id); - return false; - } - return true; - } - case CriteriaDataType.BgLossTeamScore: - return true; // not check correctness node indexes - case CriteriaDataType.SEquippedItem: - if (EquippedItem.ItemQuality >= (uint)ItemQuality.Max) - { - Log.outError(LogFilter.Sql, "Table `achievement_criteria_requirement` (Entry: {0} Type: {1}) for requirement ACHIEVEMENT_CRITERIA_REQUIRE_S_EQUIPED_ITEM ({2}) has unknown quality state in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, EquippedItem.ItemQuality); - return false; - } - return true; - case CriteriaDataType.MapId: - if (!CliDB.MapStorage.ContainsKey(MapId.Id)) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_MAP_ID ({2}) contains an unknown map entry in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, MapId.Id); - return false; - } - return true; - case CriteriaDataType.SPlayerClassRace: - if (ClassRace.ClassId == 0 && ClassRace.RaceId == 0) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) must not have 0 in either value field, ignored.", - criteria.Id, criteria.Entry.Type, DataType); - return false; - } - if (ClassRace.ClassId != 0 && ((1 << (int)(ClassRace.ClassId - 1)) & (int)Class.ClassMaskAllPlayable) == 0) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) has non-existing class in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, ClassRace.ClassId); - return false; - } - if (ClassRace.RaceId != 0 && !RaceMask.AllPlayable.HasRace((Race)ClassRace.RaceId)) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, ClassRace.RaceId); - return false; - } - return true; - case CriteriaDataType.SKnownTitle: - if (!CliDB.CharTitlesStorage.ContainsKey(KnownTitle.Id)) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_KNOWN_TITLE ({2}) contains an unknown title_id in value1 ({3}), ignore.", - criteria.Id, criteria.Entry.Type, DataType, KnownTitle.Id); - return false; - } - return true; - case CriteriaDataType.SItemQuality: - if (itemQuality.Quality >= (uint)ItemQuality.Max) - { - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_ITEM_QUALITY ({2}) contains an unknown quality state value in value1 ({3}), ignored.", - criteria.Id, criteria.Entry.Type, DataType, itemQuality.Quality); - return false; - } - return true; - default: - Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) contains data of a non-supported data type ({2}), ignored.", criteria.Id, criteria.Entry.Type, DataType); - return false; + func(tree); } } - public bool Meets(uint criteriaId, Player source, WorldObject target, uint miscValue1 = 0, uint miscValue2 = 0) + public class ModifierTreeNode { - switch (DataType) + public ModifierTreeRecord Entry; + public List Children = new(); + } + + public class Criteria + { + public uint Id; + public CriteriaRecord Entry; + public ModifierTreeNode Modifier; + public CriteriaFlagsCu FlagsCu; + } + + public class CriteriaTree + { + public uint Id; + public CriteriaTreeRecord Entry; + public AchievementRecord Achievement; + public ScenarioStepRecord ScenarioStep; + public QuestObjective QuestObjective; + public Criteria Criteria; + public List Children = new(); + } + + public class CriteriaProgress + { + public ulong Counter; + public long Date; // latest update time. + public ObjectGuid PlayerGUID; // GUID of the player that completed this criteria (guild achievements) + public bool Changed; + } + + [StructLayout(LayoutKind.Explicit)] + public class CriteriaData + { + [FieldOffset(0)] + public CriteriaDataType DataType; + + [FieldOffset(4)] + public CreatureStruct Creature; + + [FieldOffset(4)] + public ClassRaceStruct ClassRace; + + [FieldOffset(4)] + public HealthStruct Health; + + [FieldOffset(4)] + public AuraStruct Aura; + + [FieldOffset(4)] + public ValueStruct Value; + + [FieldOffset(4)] + public LevelStruct Level; + + [FieldOffset(4)] + public GenderStruct Gender; + + [FieldOffset(4)] + public MapPlayersStruct MapPlayers; + + [FieldOffset(4)] + public TeamStruct TeamId; + + [FieldOffset(4)] + public DrunkStruct Drunk; + + [FieldOffset(4)] + public HolidayStruct Holiday; + + [FieldOffset(4)] + public BgLossTeamScoreStruct BattlegroundScore; + + [FieldOffset(4)] + public EquippedItemStruct EquippedItem; + + [FieldOffset(4)] + public MapIdStruct MapId; + + [FieldOffset(4)] + public KnownTitleStruct KnownTitle; + + [FieldOffset(4)] + public GameEventStruct GameEvent; + + [FieldOffset(4)] + public ItemQualityStruct itemQuality; + + [FieldOffset(4)] + public RawStruct Raw; + + [FieldOffset(12)] + public uint ScriptId; + + public CriteriaData() { - case CriteriaDataType.None: - return true; - case CriteriaDataType.TCreature: - if (target == null || !target.IsTypeId(TypeId.Unit)) - return false; - return target.GetEntry() == Creature.Id; - case CriteriaDataType.TPlayerClassRace: - if (target == null || !target.IsTypeId(TypeId.Player)) - return false; - if (ClassRace.ClassId != 0 && ClassRace.ClassId != (uint)target.ToPlayer().GetClass()) - return false; - if (ClassRace.RaceId != 0 && ClassRace.RaceId != (uint)target.ToPlayer().GetRace()) - return false; - return true; - case CriteriaDataType.SPlayerClassRace: - if (source == null || !source.IsTypeId(TypeId.Player)) - return false; - if (ClassRace.ClassId != 0 && ClassRace.ClassId != (uint)source.ToPlayer().GetClass()) - return false; - if (ClassRace.RaceId != 0 && ClassRace.RaceId != (uint)source.ToPlayer().GetRace()) - return false; - return true; - case CriteriaDataType.TPlayerLessHealth: - if (target == null || !target.IsTypeId(TypeId.Player)) - return false; - return !target.ToPlayer().HealthAbovePct((int)Health.Percent); - case CriteriaDataType.SAura: - return source.HasAuraEffect(Aura.SpellId, (byte)Aura.EffectIndex); - case CriteriaDataType.TAura: - { - if (target == null) - return false; - Unit unitTarget = target.ToUnit(); - if (unitTarget == null) - return false; - return unitTarget.HasAuraEffect(Aura.SpellId, Aura.EffectIndex); - } - case CriteriaDataType.Value: - return MathFunctions.CompareValues((ComparisionType)Value.ComparisonType, miscValue1, Value.Value); - case CriteriaDataType.TLevel: - if (target == null) - return false; - return target.GetLevelForTarget(source) >= Level.Min; - case CriteriaDataType.TGender: - { - if (target == null) - return false; - Unit unitTarget = target.ToUnit(); - if (unitTarget == null) - return false; - return unitTarget.GetGender() == (Gender)Gender.Gender; - } - case CriteriaDataType.Script: - { - Unit unitTarget = null; - if (target != null) - unitTarget = target.ToUnit(); - return Global.ScriptMgr.OnCriteriaCheck(ScriptId, source.ToPlayer(), unitTarget.ToUnit()); - } - case CriteriaDataType.MapPlayerCount: - return source.GetMap().GetPlayersCountExceptGMs() <= MapPlayers.MaxCount; - case CriteriaDataType.TTeam: - if (target == null || !target.IsTypeId(TypeId.Player)) - return false; - return target.ToPlayer().GetTeam() == (Team)TeamId.Team; - case CriteriaDataType.SDrunk: - return Player.GetDrunkenstateByValue(source.GetDrunkValue()) >= (DrunkenState)Drunk.State; - case CriteriaDataType.Holiday: - return Global.GameEventMgr.IsHolidayActive((HolidayIds)Holiday.Id); - case CriteriaDataType.GameEvent: - return Global.GameEventMgr.IsEventActive((ushort)GameEvent.Id); - case CriteriaDataType.BgLossTeamScore: - { - Battleground bg = source.GetBattleground(); - if (bg == null) - return false; + DataType = CriteriaDataType.None; - int score = (int)bg.GetTeamScore(bg.GetPlayerTeam(source.GetGUID()) == Team.Alliance ? BattleGroundTeamId.Horde : BattleGroundTeamId.Alliance); - return score >= BattlegroundScore.Min && score <= BattlegroundScore.Max; - } - case CriteriaDataType.InstanceScript: - { - if (!source.IsInWorld) - return false; - Map map = source.GetMap(); - if (!map.IsDungeon()) - { - Log.outError(LogFilter.Achievement, "Achievement system call AchievementCriteriaDataType.InstanceScript ({0}) for achievement criteria {1} for non-dungeon/non-raid map {2}", - CriteriaDataType.InstanceScript, criteriaId, map.GetId()); - return false; - } - InstanceScript instance = ((InstanceMap)map).GetInstanceScript(); - if (instance == null) - { - Log.outError(LogFilter.Achievement, "Achievement system call criteria_data_INSTANCE_SCRIPT ({0}) for achievement criteria {1} for map {2} but map does not have a instance script", - CriteriaDataType.InstanceScript, criteriaId, map.GetId()); - return false; - } - - Unit unitTarget = null; - if (target != null) - unitTarget = target.ToUnit(); - return instance.CheckAchievementCriteriaMeet(criteriaId, source, unitTarget, miscValue1); - } - case CriteriaDataType.SEquippedItem: - { - Criteria entry = Global.CriteriaMgr.GetCriteria(criteriaId); - - uint itemId = entry.Entry.Type == CriteriaType.EquipItemInSlot ? miscValue2 : miscValue1; - ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(itemId); - if (itemTemplate == null) - return false; - return itemTemplate.GetBaseItemLevel() >= EquippedItem.ItemLevel && (uint)itemTemplate.GetQuality() >= EquippedItem.ItemQuality; - } - case CriteriaDataType.MapId: - return source.GetMapId() == MapId.Id; - case CriteriaDataType.SKnownTitle: - { - CharTitlesRecord titleInfo = CliDB.CharTitlesStorage.LookupByKey(KnownTitle.Id); - if (titleInfo != null) - return source != null && source.HasTitle(titleInfo.MaskID); - - return false; - } - case CriteriaDataType.SItemQuality: - { - ItemTemplate pProto = Global.ObjectMgr.GetItemTemplate(miscValue1); - if (pProto == null) - return false; - return (uint)pProto.GetQuality() == itemQuality.Quality; - } - default: - break; + Raw.Value1 = 0; + Raw.Value2 = 0; + ScriptId = 0; } - return false; - } - #region Structs - // criteria_data_TYPE_NONE = 0 (no data) - // criteria_data_TYPE_T_CREATURE = 1 - public struct CreatureStruct - { - public uint Id; - } - // criteria_data_TYPE_T_PLAYER_CLASS_RACE = 2 - // criteria_data_TYPE_S_PLAYER_CLASS_RACE = 21 - public struct ClassRaceStruct - { - public uint ClassId; - public uint RaceId; - } - // criteria_data_TYPE_T_PLAYER_LESS_HEALTH = 3 - public struct HealthStruct - { - public uint Percent; - } - // criteria_data_TYPE_S_AURA = 5 - // criteria_data_TYPE_T_AURA = 7 - public struct AuraStruct - { - public uint SpellId; - public uint EffectIndex; - } - // criteria_data_TYPE_VALUE = 8 - public struct ValueStruct - { - public uint Value; - public uint ComparisonType; - } - // criteria_data_TYPE_T_LEVEL = 9 - public struct LevelStruct - { - public uint Min; - } - // criteria_data_TYPE_T_GENDER = 10 - public struct GenderStruct - { - public uint Gender; - } - // criteria_data_TYPE_SCRIPT = 11 (no data) - // criteria_data_TYPE_MAP_PLAYER_COUNT = 13 - public struct MapPlayersStruct - { - public uint MaxCount; - } - // criteria_data_TYPE_T_TEAM = 14 - public struct TeamStruct - { - public uint Team; - } - // criteria_data_TYPE_S_DRUNK = 15 - public struct DrunkStruct - { - public uint State; - } - // criteria_data_TYPE_HOLIDAY = 16 - public struct HolidayStruct - { - public uint Id; - } - // criteria_data_TYPE_BG_LOSS_TEAM_SCORE= 17 - public struct BgLossTeamScoreStruct - { - public uint Min; - public uint Max; - } - // criteria_data_INSTANCE_SCRIPT = 18 (no data) - // criteria_data_TYPE_S_EQUIPED_ITEM = 19 - public struct EquippedItemStruct - { - public uint ItemLevel; - public uint ItemQuality; - } - // criteria_data_TYPE_MAP_ID = 20 - public struct MapIdStruct - { - public uint Id; - } - // criteria_data_TYPE_KNOWN_TITLE = 23 - public struct KnownTitleStruct - { - public uint Id; - } - // CRITERIA_DATA_TYPE_S_ITEM_QUALITY = 24 - public struct ItemQualityStruct - { - public uint Quality; - } - // criteria_data_TYPE_GAME_EVENT = 25 - public struct GameEventStruct - { - public uint Id; - } - // raw - public struct RawStruct - { - public uint Value1; - public uint Value2; - } - #endregion -} + public CriteriaData(CriteriaDataType _dataType, uint _value1, uint _value2, uint _scriptId) + { + DataType = _dataType; -public class CriteriaDataSet -{ - uint _criteriaId; - List _storage = new(); + Raw.Value1 = _value1; + Raw.Value2 = _value2; + ScriptId = _scriptId; + } - public void Add(CriteriaData data) { _storage.Add(data); } - - public bool Meets(Player source, WorldObject target, uint miscValue = 0, uint miscValue2 = 0) - { - foreach (var data in _storage) - if (!data.Meets(_criteriaId, source, target, miscValue, miscValue2)) + public bool IsValid(Criteria criteria) + { + if (DataType >= CriteriaDataType.Max) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` for criteria (Entry: {0}) has wrong data type ({1}), ignored.", criteria.Id, DataType); return false; + } - return true; + switch (criteria.Entry.Type) + { + case CriteriaType.KillCreature: + case CriteriaType.KillAnyCreature: + case CriteriaType.WinBattleground: + case CriteriaType.MaxDistFallenWithoutDying: + case CriteriaType.CompleteQuest: // only hardcoded list + case CriteriaType.CastSpell: + case CriteriaType.WinAnyRankedArena: + case CriteriaType.DoEmote: + case CriteriaType.KillPlayer: + case CriteriaType.WinDuel: + case CriteriaType.GetLootByType: + case CriteriaType.LandTargetedSpellOnTarget: + case CriteriaType.BeSpellTarget: + case CriteriaType.GainAura: + case CriteriaType.EquipItemInSlot: + case CriteriaType.RollNeed: + case CriteriaType.RollGreed: + case CriteriaType.TrackedWorldStateUIModified: + case CriteriaType.EarnHonorableKill: + case CriteriaType.CompleteDailyQuest: // only Children's Week achievements + case CriteriaType.UseItem: // only Children's Week achievements + case CriteriaType.DeliveredKillingBlow: + case CriteriaType.ReachLevel: + case CriteriaType.Login: + case CriteriaType.LootAnyItem: + case CriteriaType.ObtainAnyItem: + break; + default: + if (DataType != CriteriaDataType.Script) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` has data for non-supported criteria type (Entry: {0} Type: {1}), ignored.", criteria.Id, (CriteriaType)criteria.Entry.Type); + return false; + } + break; + } + + switch (DataType) + { + case CriteriaDataType.None: + case CriteriaDataType.InstanceScript: + return true; + case CriteriaDataType.TCreature: + if (Creature.Id == 0 || Global.ObjectMgr.GetCreatureTemplate(Creature.Id) == null) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_CREATURE ({2}) has non-existing creature id in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Creature.Id); + return false; + } + return true; + case CriteriaDataType.TPlayerClassRace: + if (ClassRace.ClassId == 0 && ClassRace.RaceId == 0) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) must not have 0 in either value field, ignored.", + criteria.Id, criteria.Entry.Type, DataType); + return false; + } + if (ClassRace.ClassId != 0 && ((1 << (int)(ClassRace.ClassId - 1)) & (int)Class.ClassMaskAllPlayable) == 0) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) has non-existing class in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, ClassRace.ClassId); + return false; + } + if (!RaceMask.AllPlayable.HasRace((Race)ClassRace.RaceId)) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, ClassRace.RaceId); + return false; + } + return true; + case CriteriaDataType.TPlayerLessHealth: + if (Health.Percent < 1 || Health.Percent > 100) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH ({2}) has wrong percent value in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Health.Percent); + return false; + } + return true; + case CriteriaDataType.SAura: + case CriteriaDataType.TAura: + { + SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(Aura.SpellId, Difficulty.None); + if (spellEntry == null) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type {2} has wrong spell id in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Aura.SpellId); + return false; + } + if (spellEntry.GetEffects().Count <= Aura.EffectIndex) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type {2} has wrong spell effect index in value2 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Aura.EffectIndex); + return false; + } + if (spellEntry.GetEffect(Aura.EffectIndex).ApplyAuraName == 0) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type {2} has non-aura spell effect (ID: {3} Effect: {4}), ignores.", + criteria.Id, criteria.Entry.Type, DataType, Aura.SpellId, Aura.EffectIndex); + return false; + } + return true; + } + case CriteriaDataType.Value: + if (Value.ComparisonType >= (int)ComparisionType.Max) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_VALUE ({2}) has wrong ComparisionType in value2 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Value.ComparisonType); + return false; + } + return true; + case CriteriaDataType.TLevel: + if (Level.Min > SharedConst.GTMaxLevel) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_LEVEL ({2}) has wrong minlevel in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Level.Min); + return false; + } + return true; + case CriteriaDataType.TGender: + if (Gender.Gender > (int)Framework.Constants.Gender.None) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_GENDER ({2}) has wrong gender in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Gender.Gender); + return false; + } + return true; + case CriteriaDataType.Script: + if (ScriptId == 0) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_SCRIPT ({2}) does not have ScriptName set, ignored.", + criteria.Id, criteria.Entry.Type, DataType); + return false; + } + return true; + case CriteriaDataType.MapPlayerCount: + if (MapPlayers.MaxCount <= 0) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT ({2}) has wrong max players count in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, MapPlayers.MaxCount); + return false; + } + return true; + case CriteriaDataType.TTeam: + if (TeamId.Team != (int)Team.Alliance && TeamId.Team != (int)Team.Horde) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_TEAM ({2}) has unknown team in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, TeamId.Team); + return false; + } + return true; + case CriteriaDataType.SDrunk: + if (Drunk.State >= 4) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_DRUNK ({2}) has unknown drunken state in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Drunk.State); + return false; + } + return true; + case CriteriaDataType.Holiday: + if (!CliDB.HolidaysStorage.ContainsKey(Holiday.Id)) + { + Log.outError(LogFilter.Sql, "Table `criteria_data`(Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_HOLIDAY ({2}) has unknown holiday in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, Holiday.Id); + return false; + } + return true; + case CriteriaDataType.GameEvent: + { + var events = Global.GameEventMgr.GetEventMap(); + if (GameEvent.Id < 1 || GameEvent.Id >= events.Length) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_GAME_EVENT ({2}) has unknown game_event in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, GameEvent.Id); + return false; + } + return true; + } + case CriteriaDataType.BgLossTeamScore: + return true; // not check correctness node indexes + case CriteriaDataType.SEquippedItem: + if (EquippedItem.ItemQuality >= (uint)ItemQuality.Max) + { + Log.outError(LogFilter.Sql, "Table `achievement_criteria_requirement` (Entry: {0} Type: {1}) for requirement ACHIEVEMENT_CRITERIA_REQUIRE_S_EQUIPED_ITEM ({2}) has unknown quality state in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, EquippedItem.ItemQuality); + return false; + } + return true; + case CriteriaDataType.MapId: + if (!CliDB.MapStorage.ContainsKey(MapId.Id)) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_MAP_ID ({2}) contains an unknown map entry in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, MapId.Id); + return false; + } + return true; + case CriteriaDataType.SPlayerClassRace: + if (ClassRace.ClassId == 0 && ClassRace.RaceId == 0) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) must not have 0 in either value field, ignored.", + criteria.Id, criteria.Entry.Type, DataType); + return false; + } + if (ClassRace.ClassId != 0 && ((1 << (int)(ClassRace.ClassId - 1)) & (int)Class.ClassMaskAllPlayable) == 0) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) has non-existing class in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, ClassRace.ClassId); + return false; + } + if (ClassRace.RaceId != 0 && !RaceMask.AllPlayable.HasRace((Race)ClassRace.RaceId)) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, ClassRace.RaceId); + return false; + } + return true; + case CriteriaDataType.SKnownTitle: + if (!CliDB.CharTitlesStorage.ContainsKey(KnownTitle.Id)) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_KNOWN_TITLE ({2}) contains an unknown title_id in value1 ({3}), ignore.", + criteria.Id, criteria.Entry.Type, DataType, KnownTitle.Id); + return false; + } + return true; + case CriteriaDataType.SItemQuality: + if (itemQuality.Quality >= (uint)ItemQuality.Max) + { + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_ITEM_QUALITY ({2}) contains an unknown quality state value in value1 ({3}), ignored.", + criteria.Id, criteria.Entry.Type, DataType, itemQuality.Quality); + return false; + } + return true; + default: + Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) contains data of a non-supported data type ({2}), ignored.", criteria.Id, criteria.Entry.Type, DataType); + return false; + } + } + + public bool Meets(uint criteriaId, Player source, WorldObject target, uint miscValue1 = 0, uint miscValue2 = 0) + { + switch (DataType) + { + case CriteriaDataType.None: + return true; + case CriteriaDataType.TCreature: + if (target == null || !target.IsTypeId(TypeId.Unit)) + return false; + return target.GetEntry() == Creature.Id; + case CriteriaDataType.TPlayerClassRace: + if (target == null || !target.IsTypeId(TypeId.Player)) + return false; + if (ClassRace.ClassId != 0 && ClassRace.ClassId != (uint)target.ToPlayer().GetClass()) + return false; + if (ClassRace.RaceId != 0 && ClassRace.RaceId != (uint)target.ToPlayer().GetRace()) + return false; + return true; + case CriteriaDataType.SPlayerClassRace: + if (source == null || !source.IsTypeId(TypeId.Player)) + return false; + if (ClassRace.ClassId != 0 && ClassRace.ClassId != (uint)source.ToPlayer().GetClass()) + return false; + if (ClassRace.RaceId != 0 && ClassRace.RaceId != (uint)source.ToPlayer().GetRace()) + return false; + return true; + case CriteriaDataType.TPlayerLessHealth: + if (target == null || !target.IsTypeId(TypeId.Player)) + return false; + return !target.ToPlayer().HealthAbovePct((int)Health.Percent); + case CriteriaDataType.SAura: + return source.HasAuraEffect(Aura.SpellId, (byte)Aura.EffectIndex); + case CriteriaDataType.TAura: + { + if (target == null) + return false; + Unit unitTarget = target.ToUnit(); + if (unitTarget == null) + return false; + return unitTarget.HasAuraEffect(Aura.SpellId, Aura.EffectIndex); + } + case CriteriaDataType.Value: + return MathFunctions.CompareValues((ComparisionType)Value.ComparisonType, miscValue1, Value.Value); + case CriteriaDataType.TLevel: + if (target == null) + return false; + return target.GetLevelForTarget(source) >= Level.Min; + case CriteriaDataType.TGender: + { + if (target == null) + return false; + Unit unitTarget = target.ToUnit(); + if (unitTarget == null) + return false; + return unitTarget.GetGender() == (Gender)Gender.Gender; + } + case CriteriaDataType.Script: + { + Unit unitTarget = null; + if (target != null) + unitTarget = target.ToUnit(); + return Global.ScriptMgr.OnCriteriaCheck(ScriptId, source.ToPlayer(), unitTarget.ToUnit()); + } + case CriteriaDataType.MapPlayerCount: + return source.GetMap().GetPlayersCountExceptGMs() <= MapPlayers.MaxCount; + case CriteriaDataType.TTeam: + if (target == null || !target.IsTypeId(TypeId.Player)) + return false; + return target.ToPlayer().GetTeam() == (Team)TeamId.Team; + case CriteriaDataType.SDrunk: + return Player.GetDrunkenstateByValue(source.GetDrunkValue()) >= (DrunkenState)Drunk.State; + case CriteriaDataType.Holiday: + return Global.GameEventMgr.IsHolidayActive((HolidayIds)Holiday.Id); + case CriteriaDataType.GameEvent: + return Global.GameEventMgr.IsEventActive((ushort)GameEvent.Id); + case CriteriaDataType.BgLossTeamScore: + { + Battleground bg = source.GetBattleground(); + if (bg == null) + return false; + + int score = (int)bg.GetTeamScore(bg.GetPlayerTeam(source.GetGUID()) == Team.Alliance ? BattleGroundTeamId.Horde : BattleGroundTeamId.Alliance); + return score >= BattlegroundScore.Min && score <= BattlegroundScore.Max; + } + case CriteriaDataType.InstanceScript: + { + if (!source.IsInWorld) + return false; + Map map = source.GetMap(); + if (!map.IsDungeon()) + { + Log.outError(LogFilter.Achievement, "Achievement system call AchievementCriteriaDataType.InstanceScript ({0}) for achievement criteria {1} for non-dungeon/non-raid map {2}", + CriteriaDataType.InstanceScript, criteriaId, map.GetId()); + return false; + } + InstanceScript instance = ((InstanceMap)map).GetInstanceScript(); + if (instance == null) + { + Log.outError(LogFilter.Achievement, "Achievement system call criteria_data_INSTANCE_SCRIPT ({0}) for achievement criteria {1} for map {2} but map does not have a instance script", + CriteriaDataType.InstanceScript, criteriaId, map.GetId()); + return false; + } + + Unit unitTarget = null; + if (target != null) + unitTarget = target.ToUnit(); + return instance.CheckAchievementCriteriaMeet(criteriaId, source, unitTarget, miscValue1); + } + case CriteriaDataType.SEquippedItem: + { + Criteria entry = Global.CriteriaMgr.GetCriteria(criteriaId); + + uint itemId = entry.Entry.Type == CriteriaType.EquipItemInSlot ? miscValue2 : miscValue1; + ItemTemplate itemTemplate = Global.ObjectMgr.GetItemTemplate(itemId); + if (itemTemplate == null) + return false; + return itemTemplate.GetBaseItemLevel() >= EquippedItem.ItemLevel && (uint)itemTemplate.GetQuality() >= EquippedItem.ItemQuality; + } + case CriteriaDataType.MapId: + return source.GetMapId() == MapId.Id; + case CriteriaDataType.SKnownTitle: + { + CharTitlesRecord titleInfo = CliDB.CharTitlesStorage.LookupByKey(KnownTitle.Id); + if (titleInfo != null) + return source != null && source.HasTitle(titleInfo.MaskID); + + return false; + } + case CriteriaDataType.SItemQuality: + { + ItemTemplate pProto = Global.ObjectMgr.GetItemTemplate(miscValue1); + if (pProto == null) + return false; + return (uint)pProto.GetQuality() == itemQuality.Quality; + } + default: + break; + } + return false; + } + + #region Structs + // criteria_data_TYPE_NONE = 0 (no data) + // criteria_data_TYPE_T_CREATURE = 1 + public struct CreatureStruct + { + public uint Id; + } + // criteria_data_TYPE_T_PLAYER_CLASS_RACE = 2 + // criteria_data_TYPE_S_PLAYER_CLASS_RACE = 21 + public struct ClassRaceStruct + { + public uint ClassId; + public uint RaceId; + } + // criteria_data_TYPE_T_PLAYER_LESS_HEALTH = 3 + public struct HealthStruct + { + public uint Percent; + } + // criteria_data_TYPE_S_AURA = 5 + // criteria_data_TYPE_T_AURA = 7 + public struct AuraStruct + { + public uint SpellId; + public uint EffectIndex; + } + // criteria_data_TYPE_VALUE = 8 + public struct ValueStruct + { + public uint Value; + public uint ComparisonType; + } + // criteria_data_TYPE_T_LEVEL = 9 + public struct LevelStruct + { + public uint Min; + } + // criteria_data_TYPE_T_GENDER = 10 + public struct GenderStruct + { + public uint Gender; + } + // criteria_data_TYPE_SCRIPT = 11 (no data) + // criteria_data_TYPE_MAP_PLAYER_COUNT = 13 + public struct MapPlayersStruct + { + public uint MaxCount; + } + // criteria_data_TYPE_T_TEAM = 14 + public struct TeamStruct + { + public uint Team; + } + // criteria_data_TYPE_S_DRUNK = 15 + public struct DrunkStruct + { + public uint State; + } + // criteria_data_TYPE_HOLIDAY = 16 + public struct HolidayStruct + { + public uint Id; + } + // criteria_data_TYPE_BG_LOSS_TEAM_SCORE= 17 + public struct BgLossTeamScoreStruct + { + public uint Min; + public uint Max; + } + // criteria_data_INSTANCE_SCRIPT = 18 (no data) + // criteria_data_TYPE_S_EQUIPED_ITEM = 19 + public struct EquippedItemStruct + { + public uint ItemLevel; + public uint ItemQuality; + } + // criteria_data_TYPE_MAP_ID = 20 + public struct MapIdStruct + { + public uint Id; + } + // criteria_data_TYPE_KNOWN_TITLE = 23 + public struct KnownTitleStruct + { + public uint Id; + } + // CRITERIA_DATA_TYPE_S_ITEM_QUALITY = 24 + public struct ItemQualityStruct + { + public uint Quality; + } + // criteria_data_TYPE_GAME_EVENT = 25 + public struct GameEventStruct + { + public uint Id; + } + // raw + public struct RawStruct + { + public uint Value1; + public uint Value2; + } + #endregion } - public void SetCriteriaId(uint id) { _criteriaId = id; } -} + public class CriteriaDataSet + { + uint _criteriaId; + List _storage = new(); + + public void Add(CriteriaData data) { _storage.Add(data); } + + public bool Meets(Player source, WorldObject target, uint miscValue = 0, uint miscValue2 = 0) + { + foreach (var data in _storage) + if (!data.Meets(_criteriaId, source, target, miscValue, miscValue2)) + return false; + + return true; + } + + public void SetCriteriaId(uint id) { _criteriaId = id; } + } } diff --git a/Source/Game/Calendar/CalendarManager.cs b/Source/Game/Calendar/CalendarManager.cs index a844b3ecd..7be3348ea 100644 --- a/Source/Game/Calendar/CalendarManager.cs +++ b/Source/Game/Calendar/CalendarManager.cs @@ -539,7 +539,7 @@ namespace Game CalendarInviteRemoved packet = new(); packet.ClearPending = true; // FIXME packet.EventID = calendarEvent.EventId; - packet.Flags = flags; + packet.Flags = (ushort)flags; packet.InviteGuid = invite.InviteeGuid; SendPacketToAllEventRelatives(packet, calendarEvent); diff --git a/Source/Game/Conditions/ConditionManager.cs b/Source/Game/Conditions/ConditionManager.cs index 187850b4b..eb243fe61 100644 --- a/Source/Game/Conditions/ConditionManager.cs +++ b/Source/Game/Conditions/ConditionManager.cs @@ -2400,7 +2400,7 @@ namespace Game { var getTraitNodeEntryRank = ushort? (int traitNodeEntryId) => { - foreach (var traitConfig in player.m_activePlayerData.TraitConfigs) + foreach (var (_, (traitConfig, _)) in player.m_activePlayerData.TraitConfigs) { if ((TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat) { diff --git a/Source/Game/DataStorage/CliDB.cs b/Source/Game/DataStorage/CliDB.cs index 2183552c4..0fe8a3ea8 100644 --- a/Source/Game/DataStorage/CliDB.cs +++ b/Source/Game/DataStorage/CliDB.cs @@ -198,6 +198,7 @@ namespace Game.DataStorage ItemChildEquipmentStorage = ReadDB2("ItemChildEquipment.db2", HotfixStatements.SEL_ITEM_CHILD_EQUIPMENT); ItemClassStorage = ReadDB2("ItemClass.db2", HotfixStatements.SEL_ITEM_CLASS, HotfixStatements.SEL_ITEM_CLASS_LOCALE); ItemContextPickerEntryStorage = ReadDB2("ItemContextPickerEntry.db2", HotfixStatements.SEL_ITEM_CONTEXT_PICKER_ENTRY); + ItemCreationContextStorage = ReadDB2("ItemCreationContext.db2", HotfixStatements.SEL_ITEM_CREATION_CONTEXT); ItemCurrencyCostStorage = ReadDB2("ItemCurrencyCost.db2", HotfixStatements.SEL_ITEM_CURRENCY_COST); ItemDamageAmmoStorage = ReadDB2("ItemDamageAmmo.db2", HotfixStatements.SEL_ITEM_DAMAGE_AMMO); ItemDamageOneHandStorage = ReadDB2("ItemDamageOneHand.db2", HotfixStatements.SEL_ITEM_DAMAGE_ONE_HAND); @@ -216,7 +217,9 @@ namespace Game.DataStorage ItemModifiedAppearanceStorage = ReadDB2("ItemModifiedAppearance.db2", HotfixStatements.SEL_ITEM_MODIFIED_APPEARANCE); ItemModifiedAppearanceExtraStorage = ReadDB2("ItemModifiedAppearanceExtra.db2", HotfixStatements.SEL_ITEM_MODIFIED_APPEARANCE_EXTRA); ItemNameDescriptionStorage = ReadDB2("ItemNameDescription.db2", HotfixStatements.SEL_ITEM_NAME_DESCRIPTION, HotfixStatements.SEL_ITEM_NAME_DESCRIPTION_LOCALE); + ItemOffsetCurveStorage = ReadDB2("ItemOffsetCurve.db2", HotfixStatements.SEL_ITEM_OFFSET_CURVE); ItemPriceBaseStorage = ReadDB2("ItemPriceBase.db2", HotfixStatements.SEL_ITEM_PRICE_BASE); + ItemScalingConfigStorage = ReadDB2("ItemScalingConfig.db2", HotfixStatements.SEL_ITEM_SCALING_CONFIG); ItemSearchNameStorage = ReadDB2("ItemSearchName.db2", HotfixStatements.SEL_ITEM_SEARCH_NAME, HotfixStatements.SEL_ITEM_SEARCH_NAME_LOCALE); ItemSetStorage = ReadDB2("ItemSet.db2", HotfixStatements.SEL_ITEM_SET, HotfixStatements.SEL_ITEM_SET_LOCALE); ItemSetSpellStorage = ReadDB2("ItemSetSpell.db2", HotfixStatements.SEL_ITEM_SET_SPELL); @@ -376,6 +379,7 @@ namespace Game.DataStorage TraitNodeXTraitCostStorage = ReadDB2("TraitNodeXTraitCost.db2", HotfixStatements.SEL_TRAIT_NODE_X_TRAIT_COST); TraitNodeXTraitNodeEntryStorage = ReadDB2("TraitNodeXTraitNodeEntry.db2", HotfixStatements.SEL_TRAIT_NODE_X_TRAIT_NODE_ENTRY); TraitSubTreeStorage = ReadDB2("TraitSubTree.db2", HotfixStatements.SEL_TRAIT_SUB_TREE, HotfixStatements.SEL_TRAIT_SUB_TREE_LOCALE); + TraitSystemStorage = ReadDB2("TraitSystem.db2", HotfixStatements.SEL_TRAIT_SYSTEM); TraitTreeStorage = ReadDB2("TraitTree.db2", HotfixStatements.SEL_TRAIT_TREE); TraitTreeLoadoutStorage = ReadDB2("TraitTreeLoadout.db2", HotfixStatements.SEL_TRAIT_TREE_LOADOUT); TraitTreeLoadoutEntryStorage = ReadDB2("TraitTreeLoadoutEntry.db2", HotfixStatements.SEL_TRAIT_TREE_LOADOUT_ENTRY); @@ -604,6 +608,7 @@ namespace Game.DataStorage public static DB6Storage ItemBonusTreeStorage; public static DB6Storage ItemBonusTreeNodeStorage; public static DB6Storage ItemContextPickerEntryStorage; + public static DB6Storage ItemCreationContextStorage; public static DB6Storage ItemClassStorage; public static DB6Storage ItemChildEquipmentStorage; public static DB6Storage ItemCurrencyCostStorage; @@ -624,7 +629,9 @@ namespace Game.DataStorage public static DB6Storage ItemModifiedAppearanceStorage; public static DB6Storage ItemModifiedAppearanceExtraStorage; public static DB6Storage ItemNameDescriptionStorage; + public static DB6Storage ItemOffsetCurveStorage; public static DB6Storage ItemPriceBaseStorage; + public static DB6Storage ItemScalingConfigStorage; public static DB6Storage ItemSearchNameStorage; public static DB6Storage ItemSetStorage; public static DB6Storage ItemSetSpellStorage; @@ -784,6 +791,7 @@ namespace Game.DataStorage public static DB6Storage TraitNodeXTraitCostStorage; public static DB6Storage TraitNodeXTraitNodeEntryStorage; public static DB6Storage TraitSubTreeStorage; + public static DB6Storage TraitSystemStorage; public static DB6Storage TraitTreeStorage; public static DB6Storage TraitTreeLoadoutStorage; public static DB6Storage TraitTreeLoadoutEntryStorage; diff --git a/Source/Game/DataStorage/Structs/A_Records.cs b/Source/Game/DataStorage/Structs/A_Records.cs index 158257225..607a14de3 100644 --- a/Source/Game/DataStorage/Structs/A_Records.cs +++ b/Source/Game/DataStorage/Structs/A_Records.cs @@ -123,7 +123,7 @@ namespace Game.DataStorage public byte FactionGroupMask; public float AmbientMultiplier; public int MountFlags; - public short PvpCombatWorldStateID; + public int PvpCombatWorldStateID; public byte WildBattlePetLevelMin; public byte WildBattlePetLevelMax; public byte WindSettingsID; diff --git a/Source/Game/DataStorage/Structs/B_Records.cs b/Source/Game/DataStorage/Structs/B_Records.cs index 3e7f70728..7b0b1477b 100644 --- a/Source/Game/DataStorage/Structs/B_Records.cs +++ b/Source/Game/DataStorage/Structs/B_Records.cs @@ -132,7 +132,7 @@ namespace Game.DataStorage public int LanguageID; public int ConditionID; public ushort EmotesID; - public ushort Flags; + public int Flags; public uint ChatBubbleDurationMs; public int VoiceOverPriorityID; public uint[] SoundKitID = new uint[2]; diff --git a/Source/Game/DataStorage/Structs/C_Records.cs b/Source/Game/DataStorage/Structs/C_Records.cs index 23aa57eea..6778911a7 100644 --- a/Source/Game/DataStorage/Structs/C_Records.cs +++ b/Source/Game/DataStorage/Structs/C_Records.cs @@ -334,13 +334,13 @@ namespace Game.DataStorage public byte OrderIndex; public sbyte PetTalentType; public sbyte Role; - public uint Flags; + public int Flags; public int SpellIconFileID; public sbyte PrimaryStatPriority; public int AnimReplacements; public uint[] MasterySpellID = new uint[PlayerConst.MaxMasterySpells]; - public bool HasFlag(ChrSpecializationFlag chrSpecializationFlag) { return (Flags & (uint)chrSpecializationFlag) != 0; } + public bool HasFlag(ChrSpecializationFlag chrSpecializationFlag) { return (Flags & (int)chrSpecializationFlag) != 0; } public ChrSpecializationRole GetRole() { return (ChrSpecializationRole)Role; } public bool IsPetSpecialization() @@ -394,6 +394,8 @@ namespace Game.DataStorage public int DamageItemLevelCurveID; public int HealthPrimaryStatCurveID; public int DamagePrimaryStatCurveID; + public int PrimaryStatScalingModPlayerDataElementCharacterID; + public float PrimaryStatScalingModPlayerDataElementCharacterMultiplier; public int MinLevel; public int MaxLevel; public int MinLevelType; @@ -698,7 +700,7 @@ namespace Game.DataStorage { public uint Id; public byte Type; - public byte Flags; + public int Flags; } public sealed class CurvePointRecord @@ -707,6 +709,6 @@ namespace Game.DataStorage public Vector2 PreSLSquishPos; public uint Id; public uint CurveID; - public byte OrderIndex; + public uint OrderIndex; } } diff --git a/Source/Game/DataStorage/Structs/I_Records.cs b/Source/Game/DataStorage/Structs/I_Records.cs index bc5988475..2b2811f07 100644 --- a/Source/Game/DataStorage/Structs/I_Records.cs +++ b/Source/Game/DataStorage/Structs/I_Records.cs @@ -43,7 +43,7 @@ namespace Game.DataStorage public byte SheatheType; public sbyte SoundOverrideSubclassID; public int IconFileDataID; - public byte ItemGroupSoundsID; + public uint ItemGroupSoundsID; public int ContentTuningID; public int ModifiedCraftingReagentItemID; public int CraftingQualityID; @@ -141,6 +141,8 @@ namespace Game.DataStorage public uint IblGroupPointsModSetID; public int MinMythicPlusLevel; public int MaxMythicPlusLevel; + public int ItemCreationContextGroupID; + public int Flags; public uint ParentItemBonusTreeID; } @@ -173,6 +175,13 @@ namespace Game.DataStorage public uint ItemContextPickerID; } + public sealed class ItemCreationContextRecord + { + public uint Id; + public byte ItemContext; + public uint ItemCreationContextGroupID; + } + public sealed class ItemCurrencyCostRecord { public uint Id; @@ -306,6 +315,13 @@ namespace Game.DataStorage public int Color; } + public sealed class ItemOffsetCurveRecord + { + public uint Id; + public int CurveID; + public int Offset; + } + public sealed class ItemPriceBaseRecord { public uint Id; @@ -314,6 +330,15 @@ namespace Game.DataStorage public float Weapon; } + public sealed class ItemScalingConfigRecord + { + public uint Id; + public int ItemOffsetCurveID; + public int ItemLevel; + public int RequiredLevel; + public int Unknown1125; + } + public sealed class ItemSearchNameRecord { public uint Id; @@ -389,6 +414,8 @@ namespace Game.DataStorage public int ModifiedCraftingReagentItemID; public uint ContentTuningID; public uint PlayerLevelToItemLevelCurveID; + public int ItemLevelOffsetCurveID; + public int ItemLevelOffsetItemLevel; public ushort ItemNameDescriptionID; public ushort RequiredTransmogHoliday; public ushort RequiredHoliday; diff --git a/Source/Game/DataStorage/Structs/P_Records.cs b/Source/Game/DataStorage/Structs/P_Records.cs index 023f33248..8cd6083ed 100644 --- a/Source/Game/DataStorage/Structs/P_Records.cs +++ b/Source/Game/DataStorage/Structs/P_Records.cs @@ -146,7 +146,7 @@ namespace Game.DataStorage public uint[] Time = new uint[2]; public uint[] AuraSpellID = new uint[4]; public byte[] AuraStacks = new byte[4]; - public ushort[] Achievement = new ushort[4]; + public uint[] Achievement = new uint[4]; public ushort[] AreaID = new ushort[4]; public byte[] LfgStatus = new byte[4]; public byte[] LfgCompare = new byte[4]; @@ -165,6 +165,7 @@ namespace Game.DataStorage public uint Id; public int StorageIndex; public int Type; + public int Unknown1125; public PlayerDataElementType GetElementType() { return (PlayerDataElementType)Type; } } @@ -174,6 +175,7 @@ namespace Game.DataStorage public uint Id; public int StorageIndex; public int Type; + public int Unknown1125; public PlayerDataElementType GetElementType() { return (PlayerDataElementType)Type; } } @@ -183,6 +185,7 @@ namespace Game.DataStorage public uint Id; public int StorageIndex; public int Unknown1107; + public int Unknown1125; } public sealed class PlayerDataFlagCharacterRecord @@ -190,6 +193,7 @@ namespace Game.DataStorage public uint Id; public int StorageIndex; public int Unknown1107; + public int Unknown1125; } public sealed class PowerDisplayRecord diff --git a/Source/Game/DataStorage/Structs/S_Records.cs b/Source/Game/DataStorage/Structs/S_Records.cs index 5e97690af..a86d71eed 100644 --- a/Source/Game/DataStorage/Structs/S_Records.cs +++ b/Source/Game/DataStorage/Structs/S_Records.cs @@ -43,8 +43,8 @@ namespace Game.DataStorage public sealed class SceneScriptRecord { public uint Id; - public ushort FirstSceneScriptID; - public ushort NextSceneScriptID; + public uint FirstSceneScriptID; + public uint NextSceneScriptID; public int Unknown915; } @@ -244,10 +244,10 @@ namespace Game.DataStorage public uint Id; public byte DifficultyID; public ushort Category; - public sbyte DefenseType; + public int DefenseType; public sbyte DispelType; public sbyte Mechanic; - public sbyte PreventionType; + public int PreventionType; public ushort StartRecoveryCategory; public ushort ChargeCategory; public uint SpellID; @@ -361,7 +361,7 @@ namespace Game.DataStorage { public uint Id; public byte DifficultyID; - public short InterruptFlags; + public int InterruptFlags; public int[] AuraInterruptFlags = new int[2]; public int[] ChannelInterruptFlags = new int[2]; public uint SpellID; diff --git a/Source/Game/DataStorage/Structs/T_Records.cs b/Source/Game/DataStorage/Structs/T_Records.cs index 619d6ad50..948040a5e 100644 --- a/Source/Game/DataStorage/Structs/T_Records.cs +++ b/Source/Game/DataStorage/Structs/T_Records.cs @@ -143,6 +143,7 @@ namespace Game.DataStorage public uint Id; public int Amount; public int TraitCurrencyID; + public int CurveID; } public sealed class TraitCurrencyRecord @@ -152,6 +153,8 @@ namespace Game.DataStorage public int CurrencyTypesID; public int Flags; public int Icon; + public int PlayerDataElementAccountID; + public int PlayerDataElementCharacterID; public TraitCurrencyType GetCurrencyType() { return (TraitCurrencyType)Type; } } @@ -294,11 +297,23 @@ namespace Game.DataStorage { public LocalizedString Name; public LocalizedString Description; - public uint ID; + public uint Id; public int UiTextureAtlasElementID; public uint TraitTreeID; // Parent tree } + public sealed class TraitSystemRecord + { + public uint Id; + public int Flags; + public int WidgetSetID; + public int TraitChangeSpell; + public int ItemID; + public int VariationType; + + public TraitSystemVariationType GetVariationType() { return (TraitSystemVariationType)VariationType; } + } + public sealed class TraitTreeRecord { public uint Id; diff --git a/Source/Game/DataStorage/Structs/U_Records.cs b/Source/Game/DataStorage/Structs/U_Records.cs index ab9a42749..ccec2ece9 100644 --- a/Source/Game/DataStorage/Structs/U_Records.cs +++ b/Source/Game/DataStorage/Structs/U_Records.cs @@ -40,6 +40,7 @@ namespace Game.DataStorage public int AreaID; public int WmoDoodadPlacementID; public int WmoGroupID; + public int Unknown1125; } public sealed class UiMapLinkRecord diff --git a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs index cffd59985..3712b9d35 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs @@ -169,7 +169,7 @@ namespace Game.Entities } VisualAnim visualAnim = areaTriggerData.ModifyValue(m_areaTriggerData.VisualAnim); - SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.AnimationDataID), GetCreateProperties().AnimId); + SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.AnimationDataID), (ushort)GetCreateProperties().AnimId); SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.AnimKitID), GetCreateProperties().AnimKitId); if (GetCreateProperties() != null && GetCreateProperties().Flags.HasFlag(AreaTriggerCreatePropertiesFlag.VisualAnimIsDecay)) SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.IsDecay), true); diff --git a/Source/Game/Entities/Creature/Trainer.cs b/Source/Game/Entities/Creature/Trainer.cs index 1e4c7276e..3b14ee20a 100644 --- a/Source/Game/Entities/Creature/Trainer.cs +++ b/Source/Game/Entities/Creature/Trainer.cs @@ -36,7 +36,7 @@ namespace Game.Entities TrainerList trainerList = new(); trainerList.TrainerGUID = npc.GetGUID(); - trainerList.TrainerType = (int)_type; + trainerList.TrainerType = (sbyte)_type; trainerList.TrainerID = (int)_id; trainerList.Greeting = GetGreeting(locale); diff --git a/Source/Game/Entities/Object/Update/UpdateField.cs b/Source/Game/Entities/Object/Update/UpdateField.cs index 56da13a55..87882cb4b 100644 --- a/Source/Game/Entities/Object/Update/UpdateField.cs +++ b/Source/Game/Entities/Object/Update/UpdateField.cs @@ -15,6 +15,11 @@ namespace Game.Entities T GetValue(); } + public interface IsUpdateFieldStructureTag + { + void WriteCreate(WorldPacket data, T owner, Player receiver); + void WriteUpdate(WorldPacket data, bool ignoreChangesMask, T owner, Player receiver); + } public interface IHasChangesMask { void ClearChangesMask(); @@ -184,25 +189,18 @@ namespace Game.Entities public class DynamicUpdateField where T : new() { - public List _values; - public List _updateMask; + public List _values = new(); + public List _updateMask = new(); public int BlockBit; public int Bit; public DynamicUpdateField() { - _values = new List(); - _updateMask = new List(); - BlockBit = -1; Bit = -1; } - public DynamicUpdateField(int blockBit, int bit) { - _values = new List(); - _updateMask = new List(); - BlockBit = blockBit; Bit = bit; } @@ -353,6 +351,81 @@ namespace Game.Entities } } + public enum MapUpdateFieldState + { + Unchanged = 0, + Changed = 1, + Deleted = 2 + } + + public class MapUpdateField where V : new() + { + Dictionary _values = new(); + public int BlockBit; + public int Bit; + + public MapUpdateField(int blockBit, int bit) + { + BlockBit = blockBit; + Bit = bit; + } + + public bool Empty() + { + return _values.Empty(); + } + + public int Size() + { + return _values.Count; + } + + public void TryAdd(K key) + { + if (!_values.ContainsKey(key)) + _values[key] = (new V(), MapUpdateFieldState.Changed); + } + + public void Remove(K key) + { + _values.Remove(key); + } + + public void MarkKeyForRemoval(K key) + { + var itr = _values.LookupByKey(key); + if (itr.Item1 != null) + itr.Item2 = MapUpdateFieldState.Deleted; + } + + public (V, MapUpdateFieldState) Get(K key) + { + if (_values.TryGetValue(key, out var value)) + return value; + + return default; + } + + public (K, V) FindIf(Predicate predicate) + { + var itr = _values.First(pair => { return predicate(pair.Value.Item1); }); + if (itr.Key != null) + return (itr.Key, itr.Value.Item1); + + return default; + } + + public IEnumerator> GetEnumerator() + { + foreach (var obj in _values) + yield return obj; + } + + public List GetKeys() { return _values.Keys.ToList(); } + + public List<(V, MapUpdateFieldState)> GetValues() { return _values.Values.ToList(); } + } + public class VariantUpdateField(int blockBit, int bit) { public object _value; @@ -435,6 +508,33 @@ namespace Game.Entities public void ClearChangesMask(UpdateFieldString updateField) { } + public void ClearChangesMask(MapUpdateField field) where V : new() + { + foreach (var key in field.GetKeys()) + { + var value = field.Get(key); + switch (value.Item2) + { + case MapUpdateFieldState.Unchanged: + break; + case MapUpdateFieldState.Changed: + if (typeof(HasChangesMask).IsAssignableFrom(typeof(K))) + ((IHasChangesMask)key).ClearChangesMask(); + + if (typeof(HasChangesMask).IsAssignableFrom(typeof(V))) + ((IHasChangesMask)value.Item1).ClearChangesMask(); + + value.Item2 = MapUpdateFieldState.Unchanged; + break; + case MapUpdateFieldState.Deleted: + field.Remove(key); + continue; + default: + break; + } + } + } + public void ClearChangesMask(OptionalUpdateField updateField) where U : new() { if (typeof(IHasChangesMask).IsAssignableFrom(typeof(U)) && updateField.HasValue()) @@ -488,6 +588,19 @@ namespace Game.Entities return updateField; } + public MapUpdateField ModifyValue(MapUpdateField updateField) where V : new() + { + MarkChanged(updateField); + return updateField; + } + + public V ModifyValue(MapUpdateField updateField, K key) where V : new() + { + MarkChanged(updateField); + updateField.TryAdd(key); + return updateField.Get(key).Item1; + } + public OptionalUpdateField ModifyValue(OptionalUpdateField updateField) where U : new() { MarkChanged(updateField); @@ -565,6 +678,14 @@ namespace Game.Entities _changesMask.Set(updateField.Bit); } + public void MarkChanged(MapUpdateField updateField) where V : new() + { + if (updateField.BlockBit >= 0) + _changesMask.Set(updateField.BlockBit); + + _changesMask.Set(updateField.Bit); + } + public void MarkChanged(OptionalUpdateField updateField) where U : new() { _changesMask.Set(updateField.BlockBit); @@ -613,6 +734,60 @@ namespace Game.Entities data.WriteBits(0xFFFFFFFFu, size % 32); } + public void WriteMapFieldCreate(MapUpdateField map, WorldPacket data, T owner, Player receiver) where V : new() + { + data.WriteInt32(map.Size()); + foreach (var (k, (v, _)) in map) + { + if (typeof(IsUpdateFieldStructureTag).IsAssignableFrom(typeof(K))) + ((IsUpdateFieldStructureTag)k).WriteCreate(data, owner, receiver); + else + data.Write(k); + + if (typeof(IsUpdateFieldStructureTag).IsAssignableFrom(typeof(V))) + ((IsUpdateFieldStructureTag)v).WriteCreate(data, owner, receiver); + else + data.Write(v); + } + } + + public void WriteMapFieldUpdate(MapUpdateField map, WorldPacket data, bool ignoreChangesMask, T owner, Player receiver) where V : new() + { + data.WriteUInt8((byte)(ignoreChangesMask ? 1 : 0)); + if (ignoreChangesMask) + WriteMapFieldCreate(map, data, owner, receiver); + else + { + ushort changesCount = 0; + WorldPacket tempBuffer = new(); + + foreach (var (k, (v, state)) in map) + { + if (state == MapUpdateFieldState.Unchanged) + continue; + + ++changesCount; + + if (typeof(IsUpdateFieldStructureTag).IsAssignableFrom(typeof(K))) + ((IsUpdateFieldStructureTag)k).WriteUpdate(tempBuffer, true /*ignoreChangesMask*/, owner, receiver); + else + tempBuffer.Write(k); + + tempBuffer.WriteUInt8((byte)state); + if (state == MapUpdateFieldState.Deleted) + continue; + + if (typeof(IsUpdateFieldStructureTag).IsAssignableFrom(typeof(V))) + ((IsUpdateFieldStructureTag)v).WriteUpdate(tempBuffer, true /*ignoreChangesMask*/, owner, receiver); // client bug replaces unchanged values with 0/default so send everything as if it changed + else + tempBuffer.Write(v); + } + + data.WriteUInt16(changesCount); + data.WriteBytes(tempBuffer); + } + } + public UpdateMask GetStaticUpdateMask() { return new UpdateMask(ChangeMaskLength); diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index 1653f25ee..e8b3ba325 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -1134,7 +1134,7 @@ namespace Game.Entities } } - public class PassiveSpellHistory : IEquatable + public class PassiveSpellHistory : IEquatable { public int SpellID; public int AuraSpellID; @@ -2737,17 +2737,17 @@ namespace Game.Entities public class QuestLog() : HasChangesMask(30) { - public UpdateField EndTime = new(0, 1); - public UpdateField QuestID = new(0, 2); - public UpdateField StateFlags = new(0, 3); + public UpdateField QuestID = new(0, 1); + public UpdateField StateFlags = new(0, 2); + public UpdateField EndTime = new(0, 3); public UpdateField ObjectiveFlags = new(0, 4); public UpdateFieldArray ObjectiveProgress = new(24, 5, 6); public void WriteCreate(WorldPacket data, Player owner, Player receiver) { - data.WriteInt64(EndTime); data.WriteUInt32(QuestID); - data.WriteUInt32(StateFlags); + data.WriteUInt16(StateFlags); + data.WriteInt64(EndTime); data.WriteUInt32(ObjectiveFlags); for (int i = 0; i < 24; ++i) { @@ -2799,9 +2799,9 @@ namespace Game.Entities public override void ClearChangesMask() { - ClearChangesMask(EndTime); ClearChangesMask(QuestID); ClearChangesMask(StateFlags); + ClearChangesMask(EndTime); ClearChangesMask(ObjectiveFlags); ClearChangesMask(ObjectiveProgress); _changesMask.ResetAll(); @@ -4352,8 +4352,8 @@ namespace Game.Entities public override void ClearChangesMask() { - ClearChangesMask(ProjectID); ClearChangesMask(FirstCompleted); + ClearChangesMask(ProjectID); ClearChangesMask(CompletionCount); _changesMask.ResetAll(); } @@ -4693,7 +4693,7 @@ namespace Game.Entities } } - public class TraitConfig() : HasChangesMask(14) + public class TraitConfig() : HasChangesMask(15), IsUpdateFieldStructureTag { public DynamicUpdateField Entries = new(0, 1); public DynamicUpdateField SubTrees = new(0, 2); @@ -4705,6 +4705,7 @@ namespace Game.Entities public UpdateField CombatConfigFlags = new(8, 10); public UpdateField LocalIdentifier = new(8, 11); public UpdateField TraitSystemID = new(12, 13); + public UpdateField VariationID = new(12, 14); public void WriteCreate(WorldPacket data, Player owner, Player receiver) { @@ -4725,6 +4726,7 @@ namespace Game.Entities if (Type == 3) { data.WriteUInt32(TraitSystemID); + data.WriteInt32(VariationID); } for (int i = 0; i < Entries.Size(); ++i) { @@ -4745,7 +4747,7 @@ namespace Game.Entities if (ignoreChangesMask) changesMask.SetAll(); - data.WriteBits(changesMask.GetBlock(0), 14); + data.WriteBits(changesMask.GetBlock(0), 15); if (changesMask[0]) { @@ -4839,6 +4841,13 @@ namespace Game.Entities data.WriteUInt32(TraitSystemID); } } + if (changesMask[14]) + { + if (Type == 3) + { + data.WriteInt32(VariationID); + } + } } if (changesMask[4]) { @@ -4863,6 +4872,7 @@ namespace Game.Entities ClearChangesMask(CombatConfigFlags); ClearChangesMask(LocalIdentifier); ClearChangesMask(TraitSystemID); + ClearChangesMask(VariationID); _changesMask.ResetAll(); } } @@ -5814,7 +5824,7 @@ namespace Game.Entities } } - public class DelveData : IEquatable + public class DelveData : IEquatable { public List Owners = new(); public int Field_0; @@ -5873,6 +5883,7 @@ namespace Game.Entities public long Unknown_1120_4; public ObjectGuid KeystoneOwnerGUID; public ObjectGuid LeaverGUID; + public long InstanceAbandonVoteCooldown; public uint IsActive; public uint HasRestrictions; public uint CanVoteAbandon; @@ -5885,6 +5896,7 @@ namespace Game.Entities data.WriteInt64(Unknown_1120_4); data.WritePackedGuid(KeystoneOwnerGUID); data.WritePackedGuid(LeaverGUID); + data.WriteInt64(InstanceAbandonVoteCooldown); data.WriteBits(IsActive, 1); data.WriteBits(HasRestrictions, 1); data.WriteBits(CanVoteAbandon, 1); @@ -5899,6 +5911,7 @@ namespace Game.Entities data.WriteInt64(Unknown_1120_4); data.WritePackedGuid(KeystoneOwnerGUID); data.WritePackedGuid(LeaverGUID); + data.WriteInt64(InstanceAbandonVoteCooldown); data.WriteBits(IsActive, 1); data.WriteBits(HasRestrictions, 1); data.WriteBits(CanVoteAbandon, 1); @@ -5913,6 +5926,7 @@ namespace Game.Entities && Unknown_1120_4 == right.Unknown_1120_4 && KeystoneOwnerGUID == right.KeystoneOwnerGUID && LeaverGUID == right.LeaverGUID + && InstanceAbandonVoteCooldown == right.InstanceAbandonVoteCooldown && IsActive == right.IsActive && HasRestrictions == right.HasRestrictions && CanVoteAbandon == right.CanVoteAbandon; @@ -5949,9 +5963,9 @@ namespace Game.Entities public UpdateField SortBagsRightToLeft = new(0, 4); public UpdateField InsertItemsLeftToRight = new(0, 5); public UpdateField HasPerksProgramPendingReward = new(0, 6); - public UpdateFieldArray> ResearchSites = new(1, 43, 44); - public UpdateFieldArray> ResearchSiteProgress = new(1, 45, 46); - public UpdateFieldArray> Research = new(1, 47, 48); + public UpdateFieldArray> ResearchSites = new(1, 42, 43); + public UpdateFieldArray> ResearchSiteProgress = new(1, 44, 45); + public UpdateFieldArray> Research = new(1, 46, 47); public DynamicUpdateField KnownTitles = new(0, 7); public DynamicUpdateField CharacterDataElements = new(0, 8); public DynamicUpdateField AccountDataElements = new(0, 9); @@ -5976,103 +5990,103 @@ namespace Game.Entities public DynamicUpdateField ReplayedQuests = new(0, 30); public DynamicUpdateField TaskQuests = new(0, 31); public DynamicUpdateField DisabledSpells = new(32, 33); - public DynamicUpdateField PersonalCraftingOrderCounts = new(32, 36); - public DynamicUpdateField NpcCraftingOrders = new(32, 37); - public DynamicUpdateField CategoryCooldownMods = new(32, 38); - public DynamicUpdateField WeeklySpellUses = new(32, 39); - public DynamicUpdateField TrackedCollectableSources = new(32, 40); + public DynamicUpdateField PersonalCraftingOrderCounts = new(32, 35); + public DynamicUpdateField NpcCraftingOrders = new(32, 36); + public DynamicUpdateField CategoryCooldownMods = new(32, 37); + public DynamicUpdateField WeeklySpellUses = new(32, 38); + public DynamicUpdateField TrackedCollectableSources = new(32, 39); public DynamicUpdateField PvpInfo = new(0, 10); public DynamicUpdateField CharacterRestrictions = new(0, 24); - public DynamicUpdateField TraitConfigs = new(32, 34); - public DynamicUpdateField CraftingOrders = new(32, 35); - public DynamicUpdateField CharacterBankTabSettings = new(32, 41); - public DynamicUpdateField AccountBankTabSettings = new(32, 42); - public UpdateField FarsightObject = new(32, 49); - public UpdateField SummonedBattlePetGUID = new(32, 50); - public UpdateField Coinage = new(32, 51); - public UpdateField AccountBankCoinage = new(32, 52); - public UpdateField XP = new(32, 53); - public UpdateField NextLevelXP = new(32, 54); - public UpdateField TrialXP = new(32, 55); - public UpdateField Skill = new(32, 56); - public UpdateField CharacterPoints = new(32, 57); - public UpdateField MaxTalentTiers = new(32, 58); - public UpdateField TrackCreatureMask = new(32, 59); - public UpdateField MainhandExpertise = new(32, 60); - public UpdateField OffhandExpertise = new(32, 61); - public UpdateField RangedExpertise = new(32, 62); - public UpdateField CombatRatingExpertise = new(32, 63); - public UpdateField BlockPercentage = new(32, 64); - public UpdateField DodgePercentage = new(32, 65); - public UpdateField DodgePercentageFromAttribute = new(32, 66); - public UpdateField ParryPercentage = new(32, 67); - public UpdateField ParryPercentageFromAttribute = new(32, 68); - public UpdateField CritPercentage = new(32, 69); - public UpdateField RangedCritPercentage = new(70, 71); - public UpdateField OffhandCritPercentage = new(70, 72); - public UpdateField SpellCritPercentage = new(70, 73); - public UpdateField ShieldBlock = new(70, 74); - public UpdateField ShieldBlockCritPercentage = new(70, 75); - public UpdateField Mastery = new(70, 76); - public UpdateField Speed = new(70, 77); - public UpdateField Avoidance = new(70, 78); - public UpdateField Sturdiness = new(70, 79); - public UpdateField Versatility = new(70, 80); - public UpdateField VersatilityBonus = new(70, 81); - public UpdateField PvpPowerDamage = new(70, 82); - public UpdateField PvpPowerHealing = new(70, 83); - public UpdateField BitVectors = new(70, 84); - public UpdateField ModHealingDonePos = new(70, 85); - public UpdateField ModHealingPercent = new(70, 86); - public UpdateField ModPeriodicHealingDonePercent = new(70, 87); - public UpdateField ModSpellPowerPercent = new(70, 88); - public UpdateField ModResiliencePercent = new(70, 89); - public UpdateField OverrideSpellPowerByAPPercent = new(70, 90); - public UpdateField OverrideAPBySpellPowerPercent = new(70, 91); - public UpdateField ModTargetResistance = new(70, 92); - public UpdateField ModTargetPhysicalResistance = new(70, 93); - public UpdateField LocalFlags = new(70, 94); - public UpdateField GrantableLevels = new(70, 95); - public UpdateField MultiActionBars = new(70, 96); - public UpdateField LifetimeMaxRank = new(70, 97); - public UpdateField NumRespecs = new(70, 98); - public UpdateField PvpMedals = new(70, 99); - public UpdateField TodayHonorableKills = new(70, 100); - public UpdateField YesterdayHonorableKills = new(70, 101); - public UpdateField LifetimeHonorableKills = new(102, 103); - public UpdateField WatchedFactionIndex = new(102, 104); - public UpdateField MaxLevel = new(102, 105); - public UpdateField ScalingPlayerLevelDelta = new(102, 106); - public UpdateField MaxCreatureScalingLevel = new(102, 107); - public UpdateField PetSpellPower = new(102, 108); - public UpdateField UiHitModifier = new(102, 109); - public UpdateField UiSpellHitModifier = new(102, 110); - public UpdateField HomeRealmTimeOffset = new(102, 111); - public UpdateField ModPetHaste = new(102, 112); - public UpdateField JailersTowerLevelMax = new(102, 113); - public UpdateField JailersTowerLevel = new(102, 114); - public UpdateField LocalRegenFlags = new(102, 115); - public UpdateField AuraVision = new(102, 116); - public UpdateField NumBackpackSlots = new(102, 117); - public UpdateField OverrideSpellsID = new(102, 118); - public UpdateField LootSpecID = new(102, 119); - public UpdateField OverrideZonePVPType = new(102, 120); - public UpdateField Honor = new(102, 121); - public UpdateField HonorNextLevel = new(102, 122); - public UpdateField PerksProgramCurrency = new(102, 123); - public UpdateField NumBankSlots = new(102, 124); - public UpdateField NumCharacterBankTabs = new(102, 125); - public UpdateField NumAccountBankTabs = new(102, 126); - public UpdateField ResearchHistory = new(102, 127); - public UpdateField FrozenPerksVendorItem = new(102, 128); - public UpdateField Field_1410 = new(102, 130); - public OptionalUpdateField QuestSession = new(102, 129); - public UpdateField UiChromieTimeExpansionID = new(102, 131); - public UpdateField TimerunningSeasonID = new(102, 132); - public UpdateField TransportServerTime = new(102, 133); - public UpdateField WeeklyRewardsPeriodSinceOrigin = new(134, 135); // week count since Cfg_RegionsEntry::ChallengeOrigin - public UpdateField DEBUGSoulbindConduitRank = new(134, 136); - public UpdateField DungeonScore = new(134, 137); + public DynamicUpdateField CraftingOrders = new(32, 34); + public DynamicUpdateField CharacterBankTabSettings = new(32, 40); + public DynamicUpdateField AccountBankTabSettings = new(32, 41); + public UpdateField FarsightObject = new(32, 48); + public UpdateField SummonedBattlePetGUID = new(32, 49); + public UpdateField Coinage = new(32, 50); + public UpdateField AccountBankCoinage = new(32, 51); + public UpdateField XP = new(32, 52); + public UpdateField NextLevelXP = new(32, 53); + public UpdateField TrialXP = new(32, 54); + public UpdateField Skill = new(32, 55); + public UpdateField CharacterPoints = new(32, 56); + public UpdateField MaxTalentTiers = new(32, 57); + public UpdateField TrackCreatureMask = new(32, 58); + public UpdateField MainhandExpertise = new(32, 59); + public UpdateField OffhandExpertise = new(32, 60); + public UpdateField RangedExpertise = new(32, 61); + public UpdateField CombatRatingExpertise = new(32, 62); + public UpdateField BlockPercentage = new(32, 63); + public UpdateField DodgePercentage = new(32, 64); + public UpdateField DodgePercentageFromAttribute = new(32, 65); + public UpdateField ParryPercentage = new(32, 66); + public UpdateField ParryPercentageFromAttribute = new(32, 67); + public UpdateField CritPercentage = new(32, 68); + public UpdateField RangedCritPercentage = new(32, 69); + public UpdateField OffhandCritPercentage = new(70, 71); + public UpdateField SpellCritPercentage = new(70, 72); + public UpdateField ShieldBlock = new(70, 73); + public UpdateField ShieldBlockCritPercentage = new(70, 74); + public UpdateField Mastery = new(70, 75); + public UpdateField Speed = new(70, 76); + public UpdateField Avoidance = new(70, 77); + public UpdateField Sturdiness = new(70, 78); + public UpdateField Versatility = new(70, 79); + public UpdateField VersatilityBonus = new(70, 80); + public UpdateField PvpPowerDamage = new(70, 81); + public UpdateField PvpPowerHealing = new(70, 82); + public UpdateField BitVectors = new(70, 83); + public UpdateField ModHealingDonePos = new(70, 84); + public UpdateField ModHealingPercent = new(70, 85); + public UpdateField ModPeriodicHealingDonePercent = new(70, 86); + public UpdateField ModSpellPowerPercent = new(70, 87); + public UpdateField ModResiliencePercent = new(70, 88); + public UpdateField OverrideSpellPowerByAPPercent = new(70, 89); + public UpdateField OverrideAPBySpellPowerPercent = new(70, 90); + public UpdateField ModTargetResistance = new(70, 91); + public UpdateField ModTargetPhysicalResistance = new(70, 92); + public UpdateField LocalFlags = new(70, 93); + public UpdateField GrantableLevels = new(70, 94); + public UpdateField MultiActionBars = new(70, 95); + public UpdateField LifetimeMaxRank = new(70, 96); + public UpdateField NumRespecs = new(70, 97); + public UpdateField PvpMedals = new(70, 98); + public UpdateField TodayHonorableKills = new(70, 99); + public UpdateField YesterdayHonorableKills = new(70, 100); + public UpdateField LifetimeHonorableKills = new(70, 101); + public UpdateField WatchedFactionIndex = new(102, 103); + public UpdateField MaxLevel = new(102, 104); + public UpdateField ScalingPlayerLevelDelta = new(102, 105); + public UpdateField MaxCreatureScalingLevel = new(102, 106); + public UpdateField PetSpellPower = new(102, 107); + public UpdateField UiHitModifier = new(102, 108); + public UpdateField UiSpellHitModifier = new(102, 109); + public UpdateField HomeRealmTimeOffset = new(102, 110); + public UpdateField ModPetHaste = new(102, 111); + public UpdateField JailersTowerLevelMax = new(102, 112); + public UpdateField JailersTowerLevel = new(102, 113); + public UpdateField LocalRegenFlags = new(102, 114); + public UpdateField AuraVision = new(102, 115); + public UpdateField NumBackpackSlots = new(102, 116); + public UpdateField OverrideSpellsID = new(102, 117); + public UpdateField LootSpecID = new(102, 118); + public UpdateField OverrideZonePVPType = new(102, 119); + public UpdateField Honor = new(102, 120); + public UpdateField HonorNextLevel = new(102, 121); + public UpdateField PerksProgramCurrency = new(102, 122); + public UpdateField NumBankSlots = new(102, 123); + public UpdateField NumCharacterBankTabs = new(102, 124); + public UpdateField NumAccountBankTabs = new(102, 125); + public UpdateField ResearchHistory = new(102, 126); + public UpdateField FrozenPerksVendorItem = new(102, 127); + public UpdateField Field_1410 = new(102, 129); + public OptionalUpdateField QuestSession = new(102, 128); + public UpdateField UiChromieTimeExpansionID = new(102, 130); + public UpdateField TimerunningSeasonID = new(102, 131); + public UpdateField TransportServerTime = new(102, 132); + public UpdateField WeeklyRewardsPeriodSinceOrigin = new(102, 133); // week count since Cfg_RegionsEntry::ChallengeOrigin + public UpdateField DEBUGSoulbindConduitRank = new(134, 135); + public UpdateField DungeonScore = new(134, 136); + public MapUpdateField TraitConfigs = new(134, 137); public UpdateField ActiveCombatTraitConfigID = new(134, 138); public UpdateField ItemUpgradeHighOnehandWeaponItemID = new(134, 139); public UpdateField ItemUpgradeHighFingerItemID = new(134, 140); @@ -6269,7 +6283,6 @@ namespace Game.Entities data.WriteInt32(TransportServerTime); data.WriteUInt32(WeeklyRewardsPeriodSinceOrigin); data.WriteInt16(DEBUGSoulbindConduitRank); - data.WriteInt32(TraitConfigs.Size()); data.WriteUInt32(ActiveCombatTraitConfigID); data.WriteInt32(CraftingOrders.Size()); data.WriteInt32(PersonalCraftingOrderCounts.Size()); @@ -6427,6 +6440,7 @@ namespace Game.Entities FrozenPerksVendorItem.GetValue().Write(data); Field_1410.GetValue().WriteCreate(data, owner, receiver); DungeonScore.GetValue().Write(data); + WriteMapFieldCreate(TraitConfigs, data, owner, receiver); for (int i = 0; i < PvpInfo.Size(); ++i) { PvpInfo[i].WriteCreate(data, owner, receiver); @@ -6435,10 +6449,6 @@ namespace Game.Entities { CharacterRestrictions[i].WriteCreate(data, owner, receiver); } - for (int i = 0; i < TraitConfigs.Size(); ++i) - { - TraitConfigs[i].WriteCreate(data, owner, receiver); - } for (int i = 0; i < CraftingOrders.Size(); ++i) { CraftingOrders[i].WriteCreate(data, owner, receiver); @@ -6537,11 +6547,11 @@ namespace Game.Entities WriteCompleteDynamicFieldUpdateMask(PvpInfo.Size(), data); } } - if (changesMask[43]) + if (changesMask[42]) { for (int i = 0; i < 1; ++i) { - if (changesMask[44]) + if (changesMask[43]) { if (!ignoreNestedChangesMask) ResearchSites[i].WriteUpdateMask(data); @@ -6550,11 +6560,11 @@ namespace Game.Entities } } } - if (changesMask[45]) + if (changesMask[44]) { for (int i = 0; i < 1; ++i) { - if (changesMask[46]) + if (changesMask[45]) { if (!ignoreNestedChangesMask) ResearchSiteProgress[i].WriteUpdateMask(data); @@ -6563,11 +6573,11 @@ namespace Game.Entities } } } - if (changesMask[47]) + if (changesMask[46]) { for (int i = 0; i < 1; ++i) { - if (changesMask[48]) + if (changesMask[47]) { if (!ignoreNestedChangesMask) Research[i].WriteUpdateMask(data); @@ -6576,11 +6586,11 @@ namespace Game.Entities } } } - if (changesMask[43]) + if (changesMask[42]) { for (int i = 0; i < 1; ++i) { - if (changesMask[44]) + if (changesMask[43]) { for (int j = 0; j < ResearchSites[i].Size(); ++j) { @@ -6592,11 +6602,11 @@ namespace Game.Entities } } } - if (changesMask[45]) + if (changesMask[44]) { for (int i = 0; i < 1; ++i) { - if (changesMask[46]) + if (changesMask[45]) { for (int j = 0; j < ResearchSiteProgress[i].Size(); ++j) { @@ -6608,11 +6618,11 @@ namespace Game.Entities } } } - if (changesMask[47]) + if (changesMask[46]) { for (int i = 0; i < 1; ++i) { - if (changesMask[48]) + if (changesMask[47]) { for (int j = 0; j < Research[i].Size(); ++j) { @@ -6785,48 +6795,41 @@ namespace Game.Entities WriteCompleteDynamicFieldUpdateMask(DisabledSpells.Size(), data); } if (changesMask[34]) - { - if (!ignoreNestedChangesMask) - TraitConfigs.WriteUpdateMask(data); - else - WriteCompleteDynamicFieldUpdateMask(TraitConfigs.Size(), data); - } - if (changesMask[35]) { if (!ignoreNestedChangesMask) CraftingOrders.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(CraftingOrders.Size(), data); } - if (changesMask[36]) + if (changesMask[35]) { if (!ignoreNestedChangesMask) PersonalCraftingOrderCounts.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(PersonalCraftingOrderCounts.Size(), data); } - if (changesMask[37]) + if (changesMask[36]) { if (!ignoreNestedChangesMask) NpcCraftingOrders.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(NpcCraftingOrders.Size(), data); } - if (changesMask[38]) + if (changesMask[37]) { if (!ignoreNestedChangesMask) CategoryCooldownMods.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(CategoryCooldownMods.Size(), data); } - if (changesMask[39]) + if (changesMask[38]) { if (!ignoreNestedChangesMask) WeeklySpellUses.WriteUpdateMask(data); else WriteCompleteDynamicFieldUpdateMask(WeeklySpellUses.Size(), data); } - if (changesMask[40]) + if (changesMask[39]) { if (!ignoreNestedChangesMask) TrackedCollectableSources.WriteUpdateMask(data); @@ -7080,7 +7083,7 @@ namespace Game.Entities } } } - if (changesMask[36]) + if (changesMask[35]) { for (int i = 0; i < PersonalCraftingOrderCounts.Size(); ++i) { @@ -7090,7 +7093,7 @@ namespace Game.Entities } } } - if (changesMask[37]) + if (changesMask[36]) { for (int i = 0; i < NpcCraftingOrders.Size(); ++i) { @@ -7100,7 +7103,7 @@ namespace Game.Entities } } } - if (changesMask[38]) + if (changesMask[37]) { for (int i = 0; i < CategoryCooldownMods.Size(); ++i) { @@ -7110,7 +7113,7 @@ namespace Game.Entities } } } - if (changesMask[39]) + if (changesMask[38]) { for (int i = 0; i < WeeklySpellUses.Size(); ++i) { @@ -7120,7 +7123,7 @@ namespace Game.Entities } } } - if (changesMask[40]) + if (changesMask[39]) { for (int i = 0; i < TrackedCollectableSources.Size(); ++i) { @@ -7134,14 +7137,14 @@ namespace Game.Entities data.FlushBits(); if (changesMask[32]) { - if (changesMask[41]) + if (changesMask[40]) { if (!ignoreNestedChangesMask) CharacterBankTabSettings.WriteUpdateMask(data, 3); else WriteCompleteDynamicFieldUpdateMask(CharacterBankTabSettings.Size(), data, 3); } - if (changesMask[42]) + if (changesMask[41]) { if (!ignoreNestedChangesMask) AccountBankTabSettings.WriteUpdateMask(data, 3); @@ -7176,16 +7179,6 @@ namespace Game.Entities if (changesMask[32]) { if (changesMask[34]) - { - for (int i = 0; i < TraitConfigs.Size(); ++i) - { - if (TraitConfigs.HasChanged(i) || ignoreNestedChangesMask) - { - TraitConfigs[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); - } - } - } - if (changesMask[35]) { for (int i = 0; i < CraftingOrders.Size(); ++i) { @@ -7195,7 +7188,7 @@ namespace Game.Entities } } } - if (changesMask[41]) + if (changesMask[40]) { for (int i = 0; i < CharacterBankTabSettings.Size(); ++i) { @@ -7205,7 +7198,7 @@ namespace Game.Entities } } } - if (changesMask[42]) + if (changesMask[41]) { for (int i = 0; i < AccountBankTabSettings.Size(); ++i) { @@ -7215,336 +7208,336 @@ namespace Game.Entities } } } - if (changesMask[49]) + if (changesMask[48]) { data.WritePackedGuid(FarsightObject); } - if (changesMask[50]) + if (changesMask[49]) { data.WritePackedGuid(SummonedBattlePetGUID); } - if (changesMask[51]) + if (changesMask[50]) { data.WriteUInt64(Coinage); } - if (changesMask[52]) + if (changesMask[51]) { data.WriteUInt64(AccountBankCoinage); } - if (changesMask[53]) + if (changesMask[52]) { data.WriteUInt32(XP); } - if (changesMask[54]) + if (changesMask[53]) { data.WriteUInt32(NextLevelXP); } - if (changesMask[55]) + if (changesMask[54]) { data.WriteInt32(TrialXP); } - if (changesMask[56]) + if (changesMask[55]) { Skill.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } - if (changesMask[57]) + if (changesMask[56]) { data.WriteUInt32(CharacterPoints); } - if (changesMask[58]) + if (changesMask[57]) { data.WriteUInt32(MaxTalentTiers); } - if (changesMask[59]) + if (changesMask[58]) { data.WriteUInt32(TrackCreatureMask); } - if (changesMask[60]) + if (changesMask[59]) { data.WriteFloat(MainhandExpertise); } - if (changesMask[61]) + if (changesMask[60]) { data.WriteFloat(OffhandExpertise); } - if (changesMask[62]) + if (changesMask[61]) { data.WriteFloat(RangedExpertise); } - if (changesMask[63]) + if (changesMask[62]) { data.WriteFloat(CombatRatingExpertise); } - if (changesMask[64]) + if (changesMask[63]) { data.WriteFloat(BlockPercentage); } - if (changesMask[65]) + if (changesMask[64]) { data.WriteFloat(DodgePercentage); } - if (changesMask[66]) + if (changesMask[65]) { data.WriteFloat(DodgePercentageFromAttribute); } - if (changesMask[67]) + if (changesMask[66]) { data.WriteFloat(ParryPercentage); } - if (changesMask[68]) + if (changesMask[67]) { data.WriteFloat(ParryPercentageFromAttribute); } - if (changesMask[69]) + if (changesMask[68]) { data.WriteFloat(CritPercentage); } + if (changesMask[69]) + { + data.WriteFloat(RangedCritPercentage); + } } if (changesMask[70]) { if (changesMask[71]) { - data.WriteFloat(RangedCritPercentage); + data.WriteFloat(OffhandCritPercentage); } if (changesMask[72]) { - data.WriteFloat(OffhandCritPercentage); + data.WriteFloat(SpellCritPercentage); } if (changesMask[73]) { - data.WriteFloat(SpellCritPercentage); + data.WriteUInt32(ShieldBlock); } if (changesMask[74]) { - data.WriteUInt32(ShieldBlock); + data.WriteFloat(ShieldBlockCritPercentage); } if (changesMask[75]) { - data.WriteFloat(ShieldBlockCritPercentage); + data.WriteFloat(Mastery); } if (changesMask[76]) { - data.WriteFloat(Mastery); + data.WriteFloat(Speed); } if (changesMask[77]) { - data.WriteFloat(Speed); + data.WriteFloat(Avoidance); } if (changesMask[78]) { - data.WriteFloat(Avoidance); + data.WriteFloat(Sturdiness); } if (changesMask[79]) { - data.WriteFloat(Sturdiness); + data.WriteInt32(Versatility); } if (changesMask[80]) { - data.WriteInt32(Versatility); + data.WriteFloat(VersatilityBonus); } if (changesMask[81]) { - data.WriteFloat(VersatilityBonus); + data.WriteFloat(PvpPowerDamage); } if (changesMask[82]) { - data.WriteFloat(PvpPowerDamage); + data.WriteFloat(PvpPowerHealing); } if (changesMask[83]) { - data.WriteFloat(PvpPowerHealing); + BitVectors.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } if (changesMask[84]) { - BitVectors.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); + data.WriteInt32(ModHealingDonePos); } if (changesMask[85]) { - data.WriteInt32(ModHealingDonePos); + data.WriteFloat(ModHealingPercent); } if (changesMask[86]) { - data.WriteFloat(ModHealingPercent); + data.WriteFloat(ModPeriodicHealingDonePercent); } if (changesMask[87]) { - data.WriteFloat(ModPeriodicHealingDonePercent); + data.WriteFloat(ModSpellPowerPercent); } if (changesMask[88]) { - data.WriteFloat(ModSpellPowerPercent); + data.WriteFloat(ModResiliencePercent); } if (changesMask[89]) { - data.WriteFloat(ModResiliencePercent); + data.WriteFloat(OverrideSpellPowerByAPPercent); } if (changesMask[90]) { - data.WriteFloat(OverrideSpellPowerByAPPercent); + data.WriteFloat(OverrideAPBySpellPowerPercent); } if (changesMask[91]) { - data.WriteFloat(OverrideAPBySpellPowerPercent); + data.WriteInt32(ModTargetResistance); } if (changesMask[92]) { - data.WriteInt32(ModTargetResistance); + data.WriteInt32(ModTargetPhysicalResistance); } if (changesMask[93]) { - data.WriteInt32(ModTargetPhysicalResistance); + data.WriteUInt32(LocalFlags); } if (changesMask[94]) { - data.WriteUInt32(LocalFlags); + data.WriteUInt8(GrantableLevels); } if (changesMask[95]) { - data.WriteUInt8(GrantableLevels); + data.WriteUInt8(MultiActionBars); } if (changesMask[96]) { - data.WriteUInt8(MultiActionBars); + data.WriteUInt8(LifetimeMaxRank); } if (changesMask[97]) { - data.WriteUInt8(LifetimeMaxRank); + data.WriteUInt8(NumRespecs); } if (changesMask[98]) { - data.WriteUInt8(NumRespecs); + data.WriteUInt32(PvpMedals); } if (changesMask[99]) { - data.WriteUInt32(PvpMedals); + data.WriteUInt16(TodayHonorableKills); } if (changesMask[100]) { - data.WriteUInt16(TodayHonorableKills); + data.WriteUInt16(YesterdayHonorableKills); } if (changesMask[101]) { - data.WriteUInt16(YesterdayHonorableKills); + data.WriteUInt32(LifetimeHonorableKills); } } if (changesMask[102]) { if (changesMask[103]) { - data.WriteUInt32(LifetimeHonorableKills); + data.WriteUInt32(WatchedFactionIndex); } if (changesMask[104]) { - data.WriteUInt32(WatchedFactionIndex); + data.WriteUInt32(MaxLevel); } if (changesMask[105]) { - data.WriteUInt32(MaxLevel); + data.WriteInt32(ScalingPlayerLevelDelta); } if (changesMask[106]) { - data.WriteInt32(ScalingPlayerLevelDelta); + data.WriteInt32(MaxCreatureScalingLevel); } if (changesMask[107]) { - data.WriteInt32(MaxCreatureScalingLevel); + data.WriteUInt32(PetSpellPower); } if (changesMask[108]) { - data.WriteUInt32(PetSpellPower); + data.WriteFloat(UiHitModifier); } if (changesMask[109]) { - data.WriteFloat(UiHitModifier); + data.WriteFloat(UiSpellHitModifier); } if (changesMask[110]) { - data.WriteFloat(UiSpellHitModifier); + data.WriteInt32(HomeRealmTimeOffset); } if (changesMask[111]) { - data.WriteInt32(HomeRealmTimeOffset); + data.WriteFloat(ModPetHaste); } if (changesMask[112]) { - data.WriteFloat(ModPetHaste); + data.WriteInt8(JailersTowerLevelMax); } if (changesMask[113]) { - data.WriteInt8(JailersTowerLevelMax); + data.WriteInt8(JailersTowerLevel); } if (changesMask[114]) { - data.WriteInt8(JailersTowerLevel); + data.WriteUInt8(LocalRegenFlags); } if (changesMask[115]) { - data.WriteUInt8(LocalRegenFlags); + data.WriteUInt8(AuraVision); } if (changesMask[116]) { - data.WriteUInt8(AuraVision); + data.WriteUInt8(NumBackpackSlots); } if (changesMask[117]) { - data.WriteUInt8(NumBackpackSlots); + data.WriteUInt32(OverrideSpellsID); } if (changesMask[118]) { - data.WriteUInt32(OverrideSpellsID); + data.WriteUInt16(LootSpecID); } if (changesMask[119]) { - data.WriteUInt16(LootSpecID); + data.WriteUInt32(OverrideZonePVPType); } if (changesMask[120]) { - data.WriteUInt32(OverrideZonePVPType); + data.WriteUInt32(Honor); } if (changesMask[121]) { - data.WriteUInt32(Honor); + data.WriteUInt32(HonorNextLevel); } if (changesMask[122]) { - data.WriteUInt32(HonorNextLevel); + data.WriteInt32(PerksProgramCurrency); } if (changesMask[123]) { - data.WriteInt32(PerksProgramCurrency); + data.WriteUInt8(NumBankSlots); } if (changesMask[124]) { - data.WriteUInt8(NumBankSlots); + data.WriteUInt8(NumCharacterBankTabs); } if (changesMask[125]) - { - data.WriteUInt8(NumCharacterBankTabs); - } - if (changesMask[126]) { data.WriteUInt8(NumAccountBankTabs); } - if (changesMask[131]) + if (changesMask[130]) { data.WriteInt32(UiChromieTimeExpansionID); } - if (changesMask[132]) + if (changesMask[131]) { data.WriteInt32(TimerunningSeasonID); } - if (changesMask[133]) + if (changesMask[132]) { data.WriteInt32(TransportServerTime); } + if (changesMask[133]) + { + data.WriteUInt32(WeeklyRewardsPeriodSinceOrigin); + } } if (changesMask[134]) { if (changesMask[135]) - { - data.WriteUInt32(WeeklyRewardsPeriodSinceOrigin); - } - if (changesMask[136]) { data.WriteInt16(DEBUGSoulbindConduitRank); } @@ -7595,32 +7588,36 @@ namespace Game.Entities data.FlushBits(); if (changesMask[102]) { - if (changesMask[127]) + if (changesMask[126]) { ResearchHistory.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } - if (changesMask[129]) + if (changesMask[128]) { if (QuestSession.HasValue()) { QuestSession.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } } - if (changesMask[128]) + if (changesMask[127]) { FrozenPerksVendorItem.GetValue().Write(data); } - if (changesMask[130]) + if (changesMask[129]) { Field_1410.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } } if (changesMask[134]) { - if (changesMask[137]) + if (changesMask[136]) { DungeonScore.GetValue().Write(data); } + if (changesMask[137]) + { + WriteMapFieldUpdate(TraitConfigs, data, ignoreNestedChangesMask, owner, receiver); + } if (changesMask[145]) { if (PetStable.HasValue()) @@ -7656,7 +7653,7 @@ namespace Game.Entities { if (changesMask[151 + i]) { - data.WritePackedGuid(InvSlots[i]); + data .WritePackedGuid(InvSlots[i]); } } } @@ -7814,7 +7811,6 @@ namespace Game.Entities ClearChangesMask(TrackedCollectableSources); ClearChangesMask(PvpInfo); ClearChangesMask(CharacterRestrictions); - ClearChangesMask(TraitConfigs); ClearChangesMask(CraftingOrders); ClearChangesMask(CharacterBankTabSettings); ClearChangesMask(AccountBankTabSettings); @@ -7904,6 +7900,7 @@ namespace Game.Entities ClearChangesMask(WeeklyRewardsPeriodSinceOrigin); ClearChangesMask(DEBUGSoulbindConduitRank); ClearChangesMask(DungeonScore); + ClearChangesMask(TraitConfigs); ClearChangesMask(ActiveCombatTraitConfigID); ClearChangesMask(ItemUpgradeHighOnehandWeaponItemID); ClearChangesMask(ItemUpgradeHighFingerItemID); @@ -8636,16 +8633,21 @@ namespace Game.Entities public class VisualAnim() : HasChangesMask(0, TypeId.AreaTrigger, 5) { public UpdateField IsDecay = new(0, 1); - public UpdateField AnimationDataID = new(0, 2); + public OptionalUpdateField AnimationDataID = new(0, 2); public UpdateField AnimKitID = new(0, 3); public UpdateField AnimProgress = new(0, 4); public void WriteCreate(WorldPacket data, AreaTrigger owner, Player receiver) { - data.WriteInt32(AnimationDataID); + data.WriteBits(AnimationDataID.HasValue(), 1); + data.WriteBit(IsDecay); + data.FlushBits(); data.WriteUInt32(AnimKitID); data.WriteUInt32(AnimProgress); - data.WriteBit(IsDecay); + if (AnimationDataID.HasValue()) + { + data.WriteUInt16(AnimationDataID); + } data.FlushBits(); } @@ -8663,14 +8665,11 @@ namespace Game.Entities { data.WriteBit(IsDecay); } + data.WriteBits(AnimationDataID.HasValue(), 1); } data.FlushBits(); if (changesMask[0]) { - if (changesMask[2]) - { - data.WriteInt32(AnimationDataID); - } if (changesMask[3]) { data.WriteUInt32(AnimKitID); @@ -8679,6 +8678,13 @@ namespace Game.Entities { data.WriteUInt32(AnimProgress); } + if (changesMask[2]) + { + if (AnimationDataID.HasValue()) + { + data.WriteInt32(AnimationDataID); + } + } } data.FlushBits(); } diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 2f6c5cab2..b66aaccc2 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -844,6 +844,12 @@ namespace Game.Entities updateField.RemoveValue(index); } + public void RemoveMapUpdateFieldValue(MapUpdateField setter, K key) where V : new() + { + AddToObjectUpdateIfNeeded(); + setter.MarkKeyForRemoval(key); + } + public void ClearDynamicUpdateFieldValues(DynamicUpdateField updateField) where T : new() { AddToObjectUpdateIfNeeded(); diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index 95bd62eb5..e3005dfab 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -1175,8 +1175,8 @@ namespace Game.Entities if (!configsResult.IsEmpty()) { - // 0 1 2 3 4 5 6 7 - // SELECT traitConfigId, type, chrSpecializationId, combatConfigFlags, localIdentifier, skillLineId, traitSystemId, `name` FROM character_trait_config WHERE guid = ? + // 0 1 2 3 4 5 6 7 8 + // SELECT traitConfigId, type, chrSpecializationId, combatConfigFlags, localIdentifier, skillLineId, traitSystemId, variationId, `name` FROM character_trait_config WHERE guid = ? do { TraitConfigPacket traitConfig = new(); @@ -1194,12 +1194,13 @@ namespace Game.Entities break; case TraitConfigType.Generic: traitConfig.TraitSystemID = configsResult.Read(6); + traitConfig.VariationID = configsResult.Read(7); break; default: break; } - traitConfig.Name = configsResult.Read(7); + traitConfig.Name = configsResult.Read(8); foreach (var grantedEntry in TraitMgr.GetGrantedTraitEntriesForConfig(traitConfig, this)) traitConfig.Entries.Add(new TraitEntryPacket(grantedEntry)); @@ -1242,23 +1243,23 @@ namespace Game.Entities bool hasConfigForSpec(int specId) { - return m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => + return m_activePlayerData.TraitConfigs.FindIf(traitConfig => { return traitConfig.Type == (int)TraitConfigType.Combat && traitConfig.ChrSpecializationID == specId && (traitConfig.CombatConfigFlags & (int)TraitCombatConfigFlags.ActiveForSpec) != 0; - }) >= 0; + }).Item1 != 0; } int findFreeLocalIdentifier(int specId) { int index = 1; - while (m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => + while (m_activePlayerData.TraitConfigs.FindIf(traitConfig => { return traitConfig.Type == (int)TraitConfigType.Combat && traitConfig.ChrSpecializationID == specId && traitConfig.LocalIdentifier == index; - }) >= 0) + }).Item1 != 0) ++index; return index; @@ -1283,23 +1284,22 @@ namespace Game.Entities } } - int activeConfig = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => + TraitConfig activeTraitConfig = m_activePlayerData.TraitConfigs.FindIf(traitConfig => { return traitConfig.Type == (int)TraitConfigType.Combat && traitConfig.ChrSpecializationID == (int)GetPrimarySpecialization() && (traitConfig.CombatConfigFlags & (int)TraitCombatConfigFlags.ActiveForSpec) != 0; - }); + }).Item2; - if (activeConfig >= 0) + if (activeTraitConfig != null) { - TraitConfig activeTraitConfig = m_activePlayerData.TraitConfigs[activeConfig]; SetActiveCombatTraitConfigID(activeTraitConfig.ID); int activeSubTree = activeTraitConfig.SubTrees.FindIndexIf(subTree => subTree.Active != 0); if (activeSubTree >= 0) SetCurrentCombatTraitConfigSubTreeID(activeTraitConfig.SubTrees[activeSubTree].TraitSubTreeID); } - foreach (TraitConfig traitConfig in m_activePlayerData.TraitConfigs) + foreach (var (id, (traitConfig, _)) in m_activePlayerData.TraitConfigs) { switch ((TraitConfigType)(int)traitConfig.Type) { @@ -1315,7 +1315,7 @@ namespace Game.Entities break; } - ApplyTraitConfig(traitConfig.ID, true); + ApplyTraitConfig(id, true); } } @@ -2138,16 +2138,16 @@ namespace Game.Entities TraitConfig traitConfig = GetTraitConfig((int)(uint)m_activePlayerData.ActiveCombatTraitConfigID); if (traitConfig != null) { - int usedSavedTraitConfigIndex = m_activePlayerData.TraitConfigs.FindIndexIf(savedConfig => + int usedSavedTraitConfigId = m_activePlayerData.TraitConfigs.FindIf(savedConfig => { return (TraitConfigType)(int)savedConfig.Type == TraitConfigType.Combat && ((TraitCombatConfigFlags)(int)savedConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None && ((TraitCombatConfigFlags)(int)savedConfig.CombatConfigFlags & TraitCombatConfigFlags.SharedActionBars) == TraitCombatConfigFlags.None && savedConfig.LocalIdentifier == traitConfig.LocalIdentifier; - }); + }).Item1; - if (usedSavedTraitConfigIndex >= 0) - traitConfigId = m_activePlayerData.TraitConfigs[usedSavedTraitConfigIndex].ID; + if (usedSavedTraitConfigId != 0) + traitConfigId = usedSavedTraitConfigId; } PreparedStatement stmt; @@ -2480,6 +2480,7 @@ namespace Game.Entities stmt.AddValue(5, traitConfig.LocalIdentifier); stmt.AddNull(6); stmt.AddNull(7); + stmt.AddNull(8); break; case TraitConfigType.Profession: stmt.AddNull(3); @@ -2487,6 +2488,7 @@ namespace Game.Entities stmt.AddNull(5); stmt.AddValue(6, traitConfig.SkillLineID); stmt.AddNull(7); + stmt.AddNull(8); break; case TraitConfigType.Generic: stmt.AddNull(3); @@ -2494,12 +2496,13 @@ namespace Game.Entities stmt.AddNull(5); stmt.AddNull(6); stmt.AddValue(7, traitConfig.TraitSystemID); + stmt.AddValue(8, traitConfig.VariationID); break; default: break; } - stmt.AddValue(8, traitConfig.Name); + stmt.AddValue(9, traitConfig.Name); trans.Append(stmt); foreach (var traitEntry in traitConfig.Entries) diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 277b4baa5..359337ab5 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -2337,7 +2337,7 @@ namespace Game.Entities { var questLogField = m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.QuestLog, slot); SetUpdateFieldValue(questLogField.ModifyValue(questLogField.QuestID), quest_id); - SetUpdateFieldValue(questLogField.ModifyValue(questLogField.StateFlags), 0u); + SetUpdateFieldValue(questLogField.ModifyValue(questLogField.StateFlags), (ushort)0); SetUpdateFieldValue(questLogField.ModifyValue(questLogField.EndTime), 0u); SetUpdateFieldValue(questLogField.ModifyValue(questLogField.ObjectiveFlags), 0u); @@ -2358,13 +2358,13 @@ namespace Game.Entities public void SetQuestSlotState(ushort slot, QuestSlotStateMask state) { QuestLog questLogField = m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.QuestLog, slot); - SetUpdateFieldFlagValue(questLogField.ModifyValue(questLogField.StateFlags), (uint)state); + SetUpdateFieldFlagValue(questLogField.ModifyValue(questLogField.StateFlags), (ushort)state); } public void RemoveQuestSlotState(ushort slot, QuestSlotStateMask state) { QuestLog questLogField = m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.QuestLog, slot); - RemoveUpdateFieldFlagValue(questLogField.ModifyValue(questLogField.StateFlags), (uint)state); + RemoveUpdateFieldFlagValue(questLogField.ModifyValue(questLogField.StateFlags), (ushort)state); } public void SetQuestSlotEndTime(ushort slot, long endTime) diff --git a/Source/Game/Entities/Player/Player.Talents.cs b/Source/Game/Entities/Player/Player.Talents.cs index e07a6c7a3..5d13b1c99 100644 --- a/Source/Game/Entities/Player/Player.Talents.cs +++ b/Source/Game/Entities/Player/Player.Talents.cs @@ -358,19 +358,19 @@ namespace Game.Entities SetActiveTalentGroup(spec.OrderIndex); SetPrimarySpecialization(spec.Id); - int specTraitConfigIndex = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => + var specTraitConfig = m_activePlayerData.TraitConfigs.FindIf(traitConfig => { return (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat && traitConfig.ChrSpecializationID == spec.Id && ((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) != TraitCombatConfigFlags.None; - }); - if (specTraitConfigIndex >= 0) + }).Item2; + + if (specTraitConfig != null) { - TraitConfig activeTraitConfig = m_activePlayerData.TraitConfigs[specTraitConfigIndex]; - SetActiveCombatTraitConfigID(activeTraitConfig.ID); - int activeSubTree = activeTraitConfig.SubTrees.FindIndexIf(subTree => subTree.Active != 0); + SetActiveCombatTraitConfigID(specTraitConfig.ID); + int activeSubTree = specTraitConfig.SubTrees.FindIndexIf(subTree => subTree.Active != 0); if (activeSubTree >= 0) - SetCurrentCombatTraitConfigSubTreeID(activeTraitConfig.SubTrees[activeSubTree].TraitSubTreeID); + SetCurrentCombatTraitConfigSubTreeID(specTraitConfig.SubTrees[activeSubTree].TraitSubTreeID); else SetCurrentCombatTraitConfigSubTreeID(0); } @@ -497,16 +497,16 @@ namespace Game.Entities TraitConfig traitConfig = GetTraitConfig((int)(uint)m_activePlayerData.ActiveCombatTraitConfigID); if (traitConfig != null) { - int usedSavedTraitConfigIndex = m_activePlayerData.TraitConfigs.FindIndexIf(savedConfig => + var usedSavedTraitConfigId = m_activePlayerData.TraitConfigs.FindIf(savedConfig => { return (TraitConfigType)(int)savedConfig.Type == TraitConfigType.Combat && ((TraitCombatConfigFlags)(int)savedConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None && ((TraitCombatConfigFlags)(int)savedConfig.CombatConfigFlags & TraitCombatConfigFlags.SharedActionBars) == TraitCombatConfigFlags.None && savedConfig.LocalIdentifier == traitConfig.LocalIdentifier; - }); + }).Item1; - if (usedSavedTraitConfigIndex >= 0) - traitConfigId = (uint)(int)m_activePlayerData.TraitConfigs[usedSavedTraitConfigIndex].ID; + if (usedSavedTraitConfigId != 0) + traitConfigId = (uint)usedSavedTraitConfigId; } // load them asynchronously @@ -873,45 +873,38 @@ namespace Game.Entities public void CreateTraitConfig(TraitConfigPacket traitConfig) { int configId = TraitMgr.GenerateNewTraitConfigId(); - bool hasConfigId(int id) - { - return m_activePlayerData.TraitConfigs.FindIndexIf(config => config.ID == id) >= 0; - } + bool hasConfigId(int id) => m_activePlayerData.TraitConfigs.Get(id).Item1 != null; while (hasConfigId(configId)) configId = TraitMgr.GenerateNewTraitConfigId(); traitConfig.ID = configId; - int traitConfigIndex = m_activePlayerData.TraitConfigs.Size(); AddTraitConfig(traitConfig); + TraitConfig entrySetter = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, configId); foreach (TraitEntry grantedEntry in TraitMgr.GetGrantedTraitEntriesForConfig(traitConfig, this)) { var entryIndex = traitConfig.Entries.Find(entry => entry.TraitNodeID == grantedEntry.TraitNodeID && entry.TraitNodeEntryID == grantedEntry.TraitNodeEntryID); if (entryIndex == null) - { - TraitConfig value = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, traitConfigIndex); - AddDynamicUpdateFieldValue(value.ModifyValue(value.Entries), grantedEntry); - } + AddDynamicUpdateFieldValue(entrySetter.ModifyValue(entrySetter.Entries), grantedEntry); } - m_traitConfigStates[(int)configId] = PlayerSpellState.Changed; + m_traitConfigStates[configId] = PlayerSpellState.Changed; } void AddTraitConfig(TraitConfigPacket traitConfig) { - var setter = new TraitConfig(); - setter.ModifyValue(setter.ID).SetValue(traitConfig.ID); - setter.ModifyValue(setter.Name).SetValue(traitConfig.Name); - setter.ModifyValue(setter.Type).SetValue((int)traitConfig.Type); - setter.ModifyValue(setter.SkillLineID).SetValue((int)traitConfig.SkillLineID); - setter.ModifyValue(setter.ChrSpecializationID).SetValue(traitConfig.ChrSpecializationID); - setter.ModifyValue(setter.CombatConfigFlags).SetValue((int)traitConfig.CombatConfigFlags); - setter.ModifyValue(setter.LocalIdentifier).SetValue(traitConfig.LocalIdentifier); - setter.ModifyValue(setter.TraitSystemID).SetValue(traitConfig.TraitSystemID); - AddDynamicUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs), setter); + var setter = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, traitConfig.ID); + SetUpdateFieldValue(setter.ModifyValue(setter.ID), traitConfig.ID); + SetUpdateFieldValue(setter.ModifyValue(setter.Name), traitConfig.Name); + SetUpdateFieldValue(setter.ModifyValue(setter.Type), (int)traitConfig.Type); + SetUpdateFieldValue(setter.ModifyValue(setter.SkillLineID), (int)traitConfig.SkillLineID); + SetUpdateFieldValue(setter.ModifyValue(setter.ChrSpecializationID), traitConfig.ChrSpecializationID); + SetUpdateFieldValue(setter.ModifyValue(setter.CombatConfigFlags), (int)traitConfig.CombatConfigFlags); + SetUpdateFieldValue(setter.ModifyValue(setter.LocalIdentifier), traitConfig.LocalIdentifier); + SetUpdateFieldValue(setter.ModifyValue(setter.TraitSystemID), traitConfig.TraitSystemID); foreach (TraitEntryPacket traitEntry in traitConfig.Entries) { @@ -945,17 +938,13 @@ namespace Game.Entities public TraitConfig GetTraitConfig(int configId) { - int index = m_activePlayerData.TraitConfigs.FindIndexIf(config => config.ID == configId); - if (index < 0) - return null; - - return m_activePlayerData.TraitConfigs[index]; + return m_activePlayerData.TraitConfigs.Get(configId).Item1; } public void UpdateTraitConfig(TraitConfigPacket newConfig, int savedConfigId, bool withCastTime) { - int index = m_activePlayerData.TraitConfigs.FindIndexIf(config => config.ID == newConfig.ID); - if (index < 0) + var oldConfig = m_activePlayerData.TraitConfigs.Get(newConfig.ID).Item1; + if (oldConfig == null) return; if (withCastTime) @@ -966,14 +955,14 @@ namespace Game.Entities bool isActiveConfig = true; bool loadActionButtons = false; - switch ((TraitConfigType)(int)m_activePlayerData.TraitConfigs[index].Type) + switch ((TraitConfigType)(int)oldConfig.Type) { case TraitConfigType.Combat: isActiveConfig = newConfig.ID == m_activePlayerData.ActiveCombatTraitConfigID; - loadActionButtons = m_activePlayerData.TraitConfigs[index].LocalIdentifier != newConfig.LocalIdentifier; + loadActionButtons = oldConfig.LocalIdentifier != newConfig.LocalIdentifier; break; case TraitConfigType.Profession: - isActiveConfig = HasSkill((uint)(int)m_activePlayerData.TraitConfigs[index].SkillLineID); + isActiveConfig = HasSkill((uint)(int)oldConfig.SkillLineID); break; default: break; @@ -981,7 +970,7 @@ namespace Game.Entities Action finalizeTraitConfigUpdate = () => { - TraitConfig newTraitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, index); + TraitConfig newTraitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, newConfig.ID); SetUpdateFieldValue(newTraitConfig.ModifyValue(newTraitConfig.LocalIdentifier), newConfig.LocalIdentifier); ApplyTraitEntryChanges(newConfig.ID, newConfig, isActiveConfig, true); @@ -1007,11 +996,11 @@ namespace Game.Entities void ApplyTraitEntryChanges(int editedConfigId, TraitConfigPacket newConfig, bool applyTraits, bool consumeCurrencies) { - int editedIndex = m_activePlayerData.TraitConfigs.FindIndexIf(config => config.ID == editedConfigId); - if (editedIndex < 0) + var editedConfig = m_activePlayerData.TraitConfigs.Get(editedConfigId).Item1; + if (editedConfig == null) return; - TraitConfig editedConfig = m_activePlayerData.TraitConfigs[editedIndex]; + var configSetter = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedConfigId); // remove traits not found in new config SortedSet entryIndicesToRemove = new(Comparer.Create((a, b) => -a.CompareTo(b))); @@ -1029,10 +1018,7 @@ namespace Game.Entities } foreach (int indexToRemove in entryIndicesToRemove) - { - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedIndex); - RemoveDynamicUpdateFieldValue(traitConfig.ModifyValue(traitConfig.Entries), indexToRemove); - } + RemoveDynamicUpdateFieldValue(configSetter.ModifyValue(configSetter.Entries), indexToRemove); List costEntries = new(); @@ -1045,14 +1031,13 @@ namespace Game.Entities if (consumeCurrencies) costEntries.Add(newEntry); - TraitConfig newTraitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedIndex); TraitEntry newUfEntry = new(); newUfEntry.TraitNodeID = newEntry.TraitNodeID; newUfEntry.TraitNodeEntryID = newEntry.TraitNodeEntryID; newUfEntry.Rank = newEntry.Rank; newUfEntry.GrantedRanks = newEntry.GrantedRanks; - AddDynamicUpdateFieldValue(newTraitConfig.ModifyValue(newTraitConfig.Entries), newUfEntry); + AddDynamicUpdateFieldValue(configSetter.ModifyValue(configSetter.Entries), newUfEntry); if (applyTraits) { @@ -1069,11 +1054,10 @@ namespace Game.Entities costEntries.Add(newEntry); } - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedIndex); - TraitEntry traitEntry = traitConfig.ModifyValue(traitConfig.Entries, oldEntryIndex); + TraitEntry traitEntry = configSetter.ModifyValue(configSetter.Entries, oldEntryIndex); traitEntry.Rank = newEntry.Rank; traitEntry.GrantedRanks = newEntry.GrantedRanks; - SetUpdateFieldValue(traitConfig.Entries, oldEntryIndex, traitEntry); + SetUpdateFieldValue(configSetter.Entries, oldEntryIndex, traitEntry); if (applyTraits) ApplyTraitEntry(newEntry.TraitNodeEntryID, newEntry.Rank, newEntry.GrantedRanks, true); @@ -1126,19 +1110,17 @@ namespace Game.Entities newUfSubTree.Active = newSubTree.Active ? 1 : 0u; newUfSubTree.Entries = subTreeEntries; - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedIndex); - AddDynamicUpdateFieldValue(traitConfig.ModifyValue(traitConfig.SubTrees), newUfSubTree); + AddDynamicUpdateFieldValue(configSetter.ModifyValue(configSetter.SubTrees), newUfSubTree); } else { - bool wasActive = m_activePlayerData.TraitConfigs[editedIndex].SubTrees[oldSubTreeIndex].Active != 0; + bool wasActive = configSetter.SubTrees[oldSubTreeIndex].Active != 0; - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedIndex); - TraitSubTreeCache traitSubTreeCache = traitConfig.ModifyValue(traitConfig.SubTrees, oldSubTreeIndex); + TraitSubTreeCache traitSubTreeCache = configSetter.ModifyValue(configSetter.SubTrees, oldSubTreeIndex); traitSubTreeCache.Active = newSubTree.Active ? 1 : 0u; traitSubTreeCache.Entries = subTreeEntries; - SetUpdateFieldValue(traitConfig.ModifyValue(traitConfig.SubTrees, oldSubTreeIndex), traitSubTreeCache); + SetUpdateFieldValue(configSetter.ModifyValue(configSetter.SubTrees, oldSubTreeIndex), traitSubTreeCache); if (applyTraits && wasActive != newSubTree.Active) @@ -1163,16 +1145,13 @@ namespace Game.Entities public void RenameTraitConfig(int editedConfigId, string newName) { - int editedIndex = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => - { - return traitConfig.ID == editedConfigId - && (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat - && ((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None; - }); - if (editedIndex < 0) + TraitConfig editedConfig = m_activePlayerData.TraitConfigs.Get(editedConfigId).Item1; + if (editedConfig == null + || (TraitConfigType)(int)editedConfig.Type != TraitConfigType.Combat + || ((TraitCombatConfigFlags)(int)editedConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) != TraitCombatConfigFlags.None) return; - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedIndex); + TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, editedConfigId); SetUpdateFieldValue(traitConfig.ModifyValue(traitConfig.Name), newName); m_traitConfigStates[editedConfigId] = PlayerSpellState.Changed; @@ -1180,17 +1159,14 @@ namespace Game.Entities public void DeleteTraitConfig(int deletedConfigId) { - int deletedIndex = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => - { - return traitConfig.ID == deletedConfigId - && (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat - && ((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None; - }); - if (deletedIndex < 0) + TraitConfig deletedConfig = m_activePlayerData.TraitConfigs.Get(deletedConfigId).Item1; + if (deletedConfig == null + || (TraitConfigType)(int)deletedConfig.Type != TraitConfigType.Combat + || ((TraitCombatConfigFlags)(int)deletedConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) != TraitCombatConfigFlags.None) return; - RemoveDynamicUpdateFieldValue(m_values.ModifyValue(m_activePlayerData) - .ModifyValue(m_activePlayerData.TraitConfigs), deletedIndex); + RemoveMapUpdateFieldValue(m_values.ModifyValue(m_activePlayerData) + .ModifyValue(m_activePlayerData.TraitConfigs), deletedConfigId); m_traitConfigStates[deletedConfigId] = PlayerSpellState.Removed; } @@ -1238,27 +1214,24 @@ namespace Game.Entities public void SetTraitConfigUseStarterBuild(int traitConfigId, bool useStarterBuild) { - int configIndex = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => - { - return traitConfig.ID == traitConfigId - && (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat - && ((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) != TraitCombatConfigFlags.None; - }); - if (configIndex < 0) + TraitConfig config = m_activePlayerData.TraitConfigs.Get(traitConfigId).Item1; + if (config == null + || (TraitConfigType)(int)config.Type != TraitConfigType.Combat + || ((TraitCombatConfigFlags)(int)config.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None) return; - bool currentlyUsesStarterBuild = ((TraitCombatConfigFlags)(int)m_activePlayerData.TraitConfigs[configIndex].CombatConfigFlags).HasFlag(TraitCombatConfigFlags.StarterBuild); + bool currentlyUsesStarterBuild = ((TraitCombatConfigFlags)(int)config.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.StarterBuild); if (currentlyUsesStarterBuild == useStarterBuild) return; if (useStarterBuild) { - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, configIndex); + TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, traitConfigId); SetUpdateFieldFlagValue(traitConfig.ModifyValue(traitConfig.CombatConfigFlags), (int)TraitCombatConfigFlags.StarterBuild); } else { - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, configIndex); + TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, traitConfigId); RemoveUpdateFieldFlagValue(traitConfig.ModifyValue(traitConfig.CombatConfigFlags), (int)TraitCombatConfigFlags.StarterBuild); } @@ -1267,20 +1240,17 @@ namespace Game.Entities public void SetTraitConfigUseSharedActionBars(int traitConfigId, bool usesSharedActionBars, bool isLastSelectedSavedConfig) { - int configIndex = m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => - { - return traitConfig.ID == traitConfigId - && (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat - && ((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None; - }); - if (configIndex < 0) + TraitConfig config = m_activePlayerData.TraitConfigs.Get(traitConfigId).Item1; + if (config == null + || (TraitConfigType)(int)config.Type != TraitConfigType.Combat + || ((TraitCombatConfigFlags)(int)config.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) != TraitCombatConfigFlags.None) return; - bool currentlyUsesSharedActionBars = ((TraitCombatConfigFlags)(int)m_activePlayerData.TraitConfigs[configIndex].CombatConfigFlags).HasFlag(TraitCombatConfigFlags.SharedActionBars); + bool currentlyUsesSharedActionBars = ((TraitCombatConfigFlags)(int)config.CombatConfigFlags).HasFlag(TraitCombatConfigFlags.SharedActionBars); if (currentlyUsesSharedActionBars == usesSharedActionBars) return; - TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, configIndex); + TraitConfig traitConfig = m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TraitConfigs, traitConfigId); if (usesSharedActionBars) { SetUpdateFieldFlagValue(traitConfig.ModifyValue(traitConfig.CombatConfigFlags), (int)TraitCombatConfigFlags.SharedActionBars); diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 6d40bffda..a0481d0c2 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -1247,7 +1247,7 @@ namespace Game.Entities RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2.AbandonVehicle); } - public void SendPlaySpellVisual(Unit target, uint spellVisualId, ushort missReason, ushort reflectStatus, float travelSpeed, bool speedAsTime = false, float launchDelay = 0f) + public void SendPlaySpellVisual(Unit target, uint spellVisualId, byte missReason, byte reflectStatus, float travelSpeed, bool speedAsTime = false, float launchDelay = 0f) { PlaySpellVisual playSpellVisual = new(); playSpellVisual.Source = GetGUID(); @@ -1262,7 +1262,7 @@ namespace Game.Entities SendMessageToSet(playSpellVisual, true); } - public void SendPlaySpellVisual(Position targetPosition, uint spellVisualId, ushort missReason, ushort reflectStatus, float travelSpeed, bool speedAsTime = false, float launchDelay = 0f) + public void SendPlaySpellVisual(Position targetPosition, uint spellVisualId, byte missReason, byte reflectStatus, float travelSpeed, bool speedAsTime = false, float launchDelay = 0f) { PlaySpellVisual playSpellVisual = new(); playSpellVisual.Source = GetGUID(); diff --git a/Source/Game/Guilds/Guild.cs b/Source/Game/Guilds/Guild.cs index 56bf3a774..d7e0cdf2e 100644 --- a/Source/Game/Guilds/Guild.cs +++ b/Source/Game/Guilds/Guild.cs @@ -226,7 +226,6 @@ namespace Game.Guilds memberData.RaceID = (byte)member.GetRace(); memberData.Authenticated = false; - memberData.SorEligible = false; memberData.Name = member.GetName(); memberData.Note = member.GetPublicNote(); @@ -3091,7 +3090,7 @@ namespace Game.Guilds newsEvent.MemberGuid = GetPlayerGuid(); newsEvent.CompletedDate.SetUtcTimeFromUnixTime(GetTimestamp()); newsEvent.Flags = GetFlags(); - newsEvent.Type = (int)GetNewsType(); + newsEvent.Type = (sbyte)GetNewsType(); //for (public byte i = 0; i < 2; i++) // newsEvent.Data[i] = diff --git a/Source/Game/Handlers/AuthenticationHandler.cs b/Source/Game/Handlers/AuthenticationHandler.cs index c2e7fe195..de81f9a9f 100644 --- a/Source/Game/Handlers/AuthenticationHandler.cs +++ b/Source/Game/Handlers/AuthenticationHandler.cs @@ -120,6 +120,20 @@ namespace Game features.EuropaTicketSystemStatus = europaTicketConfig; SendPacket(features); + + MirrorVarSingle[] vars = + { + new MirrorVarSingle("raidLockoutExtendEnabled", "1"), + new MirrorVarSingle("bypassItemLevelScalingCode", "0"), + new MirrorVarSingle("shop2Enabled", "0"), + new MirrorVarSingle("bpayStoreEnable", "0"), + new MirrorVarSingle("recentAlliesEnabledClient", "0"), + new MirrorVarSingle("browserEnabled", "0"), + }; + + MirrorVars variables = new(); + variables.Variables = vars; + SendPacket(variables); } } } diff --git a/Source/Game/Handlers/CharacterHandler.cs b/Source/Game/Handlers/CharacterHandler.cs index 8a117130d..fd1e9b478 100644 --- a/Source/Game/Handlers/CharacterHandler.cs +++ b/Source/Game/Handlers/CharacterHandler.cs @@ -1145,7 +1145,7 @@ namespace Game // START OF DUMMY VALUES features.ComplaintStatus = (byte)ComplaintStatus.EnabledWithAutoIgnore; features.CfgRealmID = 2; - features.CfgRealmRecID = 0; + features.CfgRealmRecID = (int)Global.RealmMgr.GetCurrentRealmId().Index; features.CommercePricePollTimeSeconds = 300; features.VoiceEnabled = false; @@ -1184,6 +1184,14 @@ namespace Game features.GameRules.Add(rule); } + features.AddonChatThrottle.MaxTries = 10; + features.AddonChatThrottle.TriesRestoredPerSecond = 1; + features.AddonChatThrottle.UsedTriesPerMessage = 1; + features.GuildChatThrottle.UsedTriesPerMessage = 1; + features.GuildChatThrottle.TriesRestoredPerSecond = 20; + features.GroupChatThrottle.UsedTriesPerMessage = 1; + features.GroupChatThrottle.TriesRestoredPerSecond = 20; + SendPacket(features); } diff --git a/Source/Game/Handlers/TraitHandler.cs b/Source/Game/Handlers/TraitHandler.cs index 1528bbb68..eb6611a94 100644 --- a/Source/Game/Handlers/TraitHandler.cs +++ b/Source/Game/Handlers/TraitHandler.cs @@ -137,10 +137,10 @@ namespace Game if ((classTalentsRequestNewConfig.Config.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) != (int)TraitCombatConfigFlags.None) return; - long configCount = _player.m_activePlayerData.TraitConfigs._values.Count(traitConfig => + long configCount = _player.m_activePlayerData.TraitConfigs.GetValues().Count(traitConfig => { - return (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat - && ((TraitCombatConfigFlags)(int)traitConfig.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None; + return (TraitConfigType)(int)traitConfig.Item1.Type == TraitConfigType.Combat + && ((TraitCombatConfigFlags)(int)traitConfig.Item1.CombatConfigFlags & TraitCombatConfigFlags.ActiveForSpec) == TraitCombatConfigFlags.None; }); if (configCount >= TraitMgr.MAX_COMBAT_TRAIT_CONFIGS) return; @@ -148,12 +148,12 @@ namespace Game int findFreeLocalIdentifier() { int index = 1; - while (_player.m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => + while (_player.m_activePlayerData.TraitConfigs.FindIf(traitConfig => { return (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat && traitConfig.ChrSpecializationID == (int)_player.GetPrimarySpecialization() && traitConfig.LocalIdentifier == index; - }) >= 0) + }).Item1 != 0) ++index; return index; @@ -219,12 +219,12 @@ namespace Game TraitConfigPacket newConfigState = new(traitConfig); int freeLocalIdentifier = 1; - while (_player.m_activePlayerData.TraitConfigs.FindIndexIf(traitConfig => + while (_player.m_activePlayerData.TraitConfigs.FindIf(traitConfig => { return (TraitConfigType)(int)traitConfig.Type == TraitConfigType.Combat && traitConfig.ChrSpecializationID == (int)_player.GetPrimarySpecialization() && traitConfig.LocalIdentifier == freeLocalIdentifier; - }) >= 0) + }).Item1 != 0) ++freeLocalIdentifier; TraitMgr.InitializeStarterBuildTraitConfig(newConfigState, _player); diff --git a/Source/Game/Networking/Packets/CalendarPackets.cs b/Source/Game/Networking/Packets/CalendarPackets.cs index c2f1e5de1..a1fe4eb4c 100644 --- a/Source/Game/Networking/Packets/CalendarPackets.cs +++ b/Source/Game/Networking/Packets/CalendarPackets.cs @@ -299,7 +299,7 @@ namespace Game.Networking.Packets _worldPacket.WritePackedGuid(InviteGuid); _worldPacket.WriteUInt64(EventID); Date.Write(_worldPacket); - _worldPacket.WriteUInt32((uint)Flags); + _worldPacket.WriteUInt16((ushort)Flags); _worldPacket.WriteUInt8((byte)Status); ResponseTime.Write(_worldPacket); @@ -324,7 +324,7 @@ namespace Game.Networking.Packets { _worldPacket.WritePackedGuid(InviteGuid); _worldPacket.WriteUInt64(EventID); - _worldPacket.WriteUInt32(Flags); + _worldPacket.WriteUInt16(Flags); _worldPacket.WriteBit(ClearPending); _worldPacket.FlushBits(); @@ -332,7 +332,7 @@ namespace Game.Networking.Packets public ObjectGuid InviteGuid; public ulong EventID; - public uint Flags; + public ushort Flags; public bool ClearPending; } @@ -364,7 +364,7 @@ namespace Game.Networking.Packets { _worldPacket.WriteUInt64(EventID); Date.Write(_worldPacket); - _worldPacket.WriteUInt32((uint)Flags); + _worldPacket.WriteUInt16((ushort)Flags); _worldPacket.WriteUInt8((byte)Status); } @@ -653,12 +653,12 @@ namespace Game.Networking.Packets { _worldPacket.WriteUInt64(EventID); _worldPacket.WritePackedTime(Date); - _worldPacket.WriteUInt32(Flags); + _worldPacket.WriteUInt16(Flags); _worldPacket.WriteUInt8(Status); } public ulong EventID; - public uint Flags; + public ushort Flags; public long Date; public byte Status; } diff --git a/Source/Game/Networking/Packets/CharacterPackets.cs b/Source/Game/Networking/Packets/CharacterPackets.cs index 8ed00dbc5..4d0ce8794 100644 --- a/Source/Game/Networking/Packets/CharacterPackets.cs +++ b/Source/Game/Networking/Packets/CharacterPackets.cs @@ -124,7 +124,7 @@ namespace Game.Networking.Packets if (fields.Read(18) != 0) Flags |= CharacterFlags.LockedByBilling; - if (WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed) && !string.IsNullOrEmpty(fields.Read(28))) + if (WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed) && !string.IsNullOrEmpty(fields.Read(29))) Flags |= CharacterFlags.Declined; if (atLoginFlags.HasAnyFlag(AtLoginFlags.Customize)) @@ -168,19 +168,20 @@ namespace Game.Networking.Packets StringArray equipment = new(fields.Read(17), ' '); ListPosition = fields.Read(19); - LastActiveTime = fields.Read(20); + CreateTime = fields.Read(20); + LastActiveTime = fields.Read(21); - var spec = Global.DB2Mgr.GetChrSpecializationByIndex(ClassId, fields.Read(21)); + var spec = Global.DB2Mgr.GetChrSpecializationByIndex(ClassId, fields.Read(22)); if (spec != null) SpecID = (short)spec.Id; - LastLoginVersion = fields.Read(22); + LastLoginVersion = fields.Read(23); - PersonalTabard.EmblemStyle = fields.Read(23); - PersonalTabard.EmblemColor = fields.Read(24); - PersonalTabard.BorderStyle = fields.Read(25); - PersonalTabard.BorderColor = fields.Read(26); - PersonalTabard.BackgroundColor = fields.Read(27); + PersonalTabard.EmblemStyle = fields.Read(24); + PersonalTabard.EmblemColor = fields.Read(25); + PersonalTabard.BorderStyle = fields.Read(26); + PersonalTabard.BorderColor = fields.Read(27); + PersonalTabard.BackgroundColor = fields.Read(28); int equipmentFieldsPerSlot = 5; @@ -226,6 +227,7 @@ namespace Game.Networking.Packets visualItem.Write(data); data.WriteInt32(SaveVersion); + data.WriteInt64(CreateTime); data.WriteInt64(LastActiveTime); data.WriteInt32(LastLoginVersion); PersonalTabard.Write(data); @@ -272,6 +274,7 @@ namespace Game.Networking.Packets public CharacterFlags4 Flags4; // Character flag4 @see enum CharacterFlags4 public bool FirstLogin; public byte CantLoginReason; + public long CreateTime; public long LastActiveTime; public short SpecID; public int SaveVersion; @@ -520,7 +523,7 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt8((byte)Code); + _worldPacket.WriteUInt32((uint)Code); _worldPacket.WritePackedGuid(Guid); } @@ -546,7 +549,7 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt8((byte)Code); + _worldPacket.WriteUInt32((uint)Code); } public ResponseCodes Code; @@ -572,7 +575,7 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt8((byte)Result); + _worldPacket.WriteUInt32((uint)Result); _worldPacket.WriteBit(Guid.HasValue); _worldPacket.WriteBits(Name.GetByteCount(), 6); _worldPacket.FlushBits(); @@ -658,7 +661,7 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt8((byte)Result); + _worldPacket.WriteUInt32((uint)Result); _worldPacket.WritePackedGuid(Guid); _worldPacket.WriteBit(Display != null); _worldPacket.FlushBits(); @@ -1173,11 +1176,11 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt8(Result); + _worldPacket.WriteUInt32(Result); _worldPacket.WritePackedGuid(CharGUID); } - public byte Result; + public uint Result; public ObjectGuid CharGUID; } diff --git a/Source/Game/Networking/Packets/CombatLogPackets.cs b/Source/Game/Networking/Packets/CombatLogPackets.cs index 4ebfea257..e92ac0d56 100644 --- a/Source/Game/Networking/Packets/CombatLogPackets.cs +++ b/Source/Game/Networking/Packets/CombatLogPackets.cs @@ -62,6 +62,7 @@ namespace Game.Networking.Packets _worldPacket.WriteInt32(Absorbed); _worldPacket.WriteInt32(Resisted); _worldPacket.WriteInt32(ShieldBlock); + _worldPacket.WriteInt32(Flags); _worldPacket.WriteInt32(WorldTextViewers.Count); _worldPacket.WriteInt32(Supporters.Count); @@ -69,7 +70,6 @@ namespace Game.Networking.Packets supportInfo.Write(_worldPacket); _worldPacket.WriteBit(Periodic); - _worldPacket.WriteBits(Flags, 7); _worldPacket.WriteBit(false); // Debug info WriteLogDataBit(); _worldPacket.WriteBit(ContentTuning != null); @@ -657,7 +657,7 @@ namespace Game.Networking.Packets public int OriginalHeal; public ContentTuningParams ContentTuning; } - + //Structs public struct SpellLogEffectPowerDrainParams { diff --git a/Source/Game/Networking/Packets/GuildPackets.cs b/Source/Game/Networking/Packets/GuildPackets.cs index 69e8fa721..faa95b45c 100644 --- a/Source/Game/Networking/Packets/GuildPackets.cs +++ b/Source/Game/Networking/Packets/GuildPackets.cs @@ -1619,12 +1619,12 @@ namespace Game.Networking.Packets data.WriteUInt8(Gender); data.WriteUInt64(GuildClubMemberID); data.WriteUInt8(RaceID); + data.WriteInt32(TimerunningSeasonID); data.WriteBits(Name.GetByteCount(), 6); data.WriteBits(Note.GetByteCount(), 8); data.WriteBits(OfficerNote.GetByteCount(), 8); data.WriteBit(Authenticated); - data.WriteBit(SorEligible); data.FlushBits(); DungeonScore.Write(data); @@ -1653,8 +1653,8 @@ namespace Game.Networking.Packets public byte Gender; public ulong GuildClubMemberID; public byte RaceID; + public int TimerunningSeasonID; public bool Authenticated; - public bool SorEligible; public GuildRosterProfessionData[] Profession = new GuildRosterProfessionData[2]; public DungeonScoreSummary DungeonScore = new(); } @@ -1758,7 +1758,7 @@ namespace Game.Networking.Packets { data.WriteInt32(Id); CompletedDate.Write(data); - data.WriteInt32(Type); + data.WriteInt8(Type); data.WriteInt32(Flags); for (byte i = 0; i < 2; i++) @@ -1779,7 +1779,7 @@ namespace Game.Networking.Packets public int Id; public WowTime CompletedDate; - public int Type; + public sbyte Type; public int Flags; public int[] Data = new int[2]; public ObjectGuid MemberGuid; diff --git a/Source/Game/Networking/Packets/ItemPackets.cs b/Source/Game/Networking/Packets/ItemPackets.cs index 1889992a5..906eedf61 100644 --- a/Source/Game/Networking/Packets/ItemPackets.cs +++ b/Source/Game/Networking/Packets/ItemPackets.cs @@ -133,14 +133,14 @@ namespace Game.Networking.Packets public override void Write() { _worldPacket.WritePackedGuid(ItemGUID); - _worldPacket.WriteUInt8(Result); + _worldPacket.WriteUInt32(Result); _worldPacket.WriteBit(Contents != null); _worldPacket.FlushBits(); if (Contents != null) Contents.Write(_worldPacket); } - public byte Result; + public uint Result; public ObjectGuid ItemGUID; public ItemPurchaseContents Contents; } diff --git a/Source/Game/Networking/Packets/LFGPackets.cs b/Source/Game/Networking/Packets/LFGPackets.cs index ad27e9d67..bfc228a8d 100644 --- a/Source/Game/Networking/Packets/LFGPackets.cs +++ b/Source/Game/Networking/Packets/LFGPackets.cs @@ -167,7 +167,7 @@ namespace Game.Networking.Packets Ticket.Write(_worldPacket); _worldPacket.WriteUInt8(SubType); - _worldPacket.WriteUInt8(Reason); + _worldPacket.WriteUInt32(Reason); _worldPacket.WriteInt32(Slots.Count); _worldPacket.WriteUInt8(RequestedRoles); _worldPacket.WriteInt32(SuspendedPlayers.Count); @@ -190,7 +190,7 @@ namespace Game.Networking.Packets public RideTicket Ticket = new(); public byte SubType; - public byte Reason; + public uint Reason; public List Slots = new(); public byte RequestedRoles; public List SuspendedPlayers = new(); diff --git a/Source/Game/Networking/Packets/MailPackets.cs b/Source/Game/Networking/Packets/MailPackets.cs index 5027e2be8..f45a4e136 100644 --- a/Source/Game/Networking/Packets/MailPackets.cs +++ b/Source/Game/Networking/Packets/MailPackets.cs @@ -212,12 +212,10 @@ namespace Game.Networking.Packets public override void Read() { } } - public class MailQueryNextTimeResult : ServerPacket + public class MailQueryNextTimeResult() : ServerPacket(ServerOpcodes.MailQueryNextTimeResult) { - public MailQueryNextTimeResult() : base(ServerOpcodes.MailQueryNextTimeResult) - { - Next = new List(); - } + public float NextMailTime; + public List Next = new(); public override void Write() { @@ -229,14 +227,11 @@ namespace Game.Networking.Packets _worldPacket.WritePackedGuid(entry.SenderGuid); _worldPacket.WriteFloat(entry.TimeLeft); _worldPacket.WriteInt32(entry.AltSenderID); - _worldPacket.WriteInt8(entry.AltSenderType); + _worldPacket.WriteInt32(entry.AltSenderType); _worldPacket.WriteInt32(entry.StationeryID); } } - public float NextMailTime; - public List Next; - public class MailNextTimeEntry { public MailNextTimeEntry(Mail mail) @@ -266,7 +261,7 @@ namespace Game.Networking.Packets public ObjectGuid SenderGuid; public float TimeLeft; public int AltSenderID; - public sbyte AltSenderType; + public int AltSenderType; public int StationeryID; } } diff --git a/Source/Game/Networking/Packets/MiscPackets.cs b/Source/Game/Networking/Packets/MiscPackets.cs index b3565b8cc..06a6ee56b 100644 --- a/Source/Game/Networking/Packets/MiscPackets.cs +++ b/Source/Game/Networking/Packets/MiscPackets.cs @@ -189,10 +189,8 @@ namespace Game.Networking.Packets public ObjectGuid Selection; // Target } - public class SetupCurrency : ServerPacket + public class SetupCurrency() : ServerPacket(ServerOpcodes.SetupCurrency, ConnectionType.Instance) { - public SetupCurrency() : base(ServerOpcodes.SetupCurrency, ConnectionType.Instance) { } - public override void Write() { _worldPacket.WriteInt32(Data.Count); @@ -201,6 +199,7 @@ namespace Game.Networking.Packets { _worldPacket.WriteUInt32(data.Type); _worldPacket.WriteUInt32(data.Quantity); + _worldPacket.WriteUInt8(data.Flags); _worldPacket.WriteBit(data.WeeklyQuantity.HasValue); _worldPacket.WriteBit(data.MaxWeeklyQuantity.HasValue); @@ -209,7 +208,6 @@ namespace Game.Networking.Packets _worldPacket.WriteBit(data.TotalEarned.HasValue); _worldPacket.WriteBit(data.NextRechargeTime.HasValue); _worldPacket.WriteBit(data.RechargeCycleStartTime.HasValue); - _worldPacket.WriteBits(data.Flags, 5); _worldPacket.FlushBits(); if (data.WeeklyQuantity.HasValue) diff --git a/Source/Game/Networking/Packets/MovementPackets.cs b/Source/Game/Networking/Packets/MovementPackets.cs index fdcc4aeea..1681e4955 100644 --- a/Source/Game/Networking/Packets/MovementPackets.cs +++ b/Source/Game/Networking/Packets/MovementPackets.cs @@ -1520,27 +1520,13 @@ namespace Game.Networking.Packets public void Write(WorldPacket data) { data.WriteUInt32(Flags); + data.WriteUInt8((byte)Face); data.WriteInt32(Elapsed); data.WriteUInt32(MoveTime); data.WriteUInt32(FadeObjectTime); data.WriteUInt8(Mode); data.WritePackedGuid(TransportGUID); data.WriteInt8(VehicleSeat); - data.WriteBits((byte)Face, 2); - data.WriteBits(Points.Count, 16); - data.WriteBit(VehicleExitVoluntary); - data.WriteBit(TaxiSmoothing); - data.WriteBits(PackedDeltas.Count, 16); - data.WriteBit(SplineFilter != null); - data.WriteBit(SpellEffectExtraData.HasValue); - data.WriteBit(JumpExtraData.HasValue); - data.WriteBit(TurnData != null); - data.WriteBit(AnimTierTransition.HasValue); - data.WriteBit(Unknown901 != null); - data.FlushBits(); - - if (SplineFilter != null) - SplineFilter.Write(data); switch (Face) { @@ -1556,6 +1542,21 @@ namespace Game.Networking.Packets break; } + data.WriteBits(Points.Count, 16); + data.WriteBit(VehicleExitVoluntary); + data.WriteBit(TaxiSmoothing); + data.WriteBits(PackedDeltas.Count, 16); + data.WriteBit(SplineFilter != null); + data.WriteBit(SpellEffectExtraData.HasValue); + data.WriteBit(JumpExtraData.HasValue); + data.WriteBit(TurnData != null); + data.WriteBit(AnimTierTransition.HasValue); + data.WriteBit(Unknown901 != null); + data.FlushBits(); + + if (SplineFilter != null) + SplineFilter.Write(data); + foreach (Vector3 pos in Points) data.WriteVector3(pos); diff --git a/Source/Game/Networking/Packets/NPCPackets.cs b/Source/Game/Networking/Packets/NPCPackets.cs index 1fa23c185..6d23fe0ca 100644 --- a/Source/Game/Networking/Packets/NPCPackets.cs +++ b/Source/Game/Networking/Packets/NPCPackets.cs @@ -164,7 +164,7 @@ namespace Game.Networking.Packets public override void Write() { _worldPacket.WritePackedGuid(TrainerGUID); - _worldPacket.WriteInt32(TrainerType); + _worldPacket.WriteInt8(TrainerType); _worldPacket.WriteInt32(TrainerID); _worldPacket.WriteInt32(Spells.Count); @@ -188,7 +188,7 @@ namespace Game.Networking.Packets } public ObjectGuid TrainerGUID; - public int TrainerType; + public sbyte TrainerType; public int TrainerID = 1; public List Spells = new(); public string Greeting; @@ -339,7 +339,7 @@ namespace Game.Networking.Packets { public int GossipOptionID; public GossipOptionNpc OptionNPC; - public byte OptionFlags; + public int OptionFlags; public ulong OptionCost; public uint OptionLanguage; public GossipOptionFlags Flags; @@ -355,8 +355,8 @@ namespace Game.Networking.Packets public void Write(WorldPacket data) { data.WriteInt32(GossipOptionID); + data.WriteInt32(OptionFlags); data.WriteUInt8((byte)OptionNPC); - data.WriteInt8((sbyte)OptionFlags); data.WriteUInt64(OptionCost); data.WriteUInt32(OptionLanguage); data.WriteInt32((int)Flags); diff --git a/Source/Game/Networking/Packets/PartyPackets.cs b/Source/Game/Networking/Packets/PartyPackets.cs index b367e49c7..2546fbde3 100644 --- a/Source/Game/Networking/Packets/PartyPackets.cs +++ b/Source/Game/Networking/Packets/PartyPackets.cs @@ -1195,7 +1195,7 @@ namespace Game.Networking.Packets for (byte i = 0; i < 2; i++) data.WriteUInt8(PartyType[i]); - data.WriteInt16((short)Status); + data.WriteUInt32((uint)Status); data.WriteUInt8(PowerType); data.WriteInt16((short)PowerDisplayID); data.WriteInt32(CurrentHealth); @@ -1387,6 +1387,7 @@ namespace Game.Networking.Packets public long Unknown_1120_4; public ObjectGuid KeystoneOwnerGUID; public ObjectGuid LeaverGUID; + public long InstanceAbandonVoteCooldown; public bool IsActive; public bool HasRestrictions; public bool CanVoteAbandon; @@ -1399,6 +1400,7 @@ namespace Game.Networking.Packets data.WriteInt64(Unknown_1120_4); data.WritePackedGuid(KeystoneOwnerGUID); data.WritePackedGuid(LeaverGUID); + data.WriteInt64(InstanceAbandonVoteCooldown); data.WriteBit(IsActive); data.WriteBit(HasRestrictions); data.WriteBit(CanVoteAbandon); diff --git a/Source/Game/Networking/Packets/PetPackets.cs b/Source/Game/Networking/Packets/PetPackets.cs index 458378ea3..1fce90ec8 100644 --- a/Source/Game/Networking/Packets/PetPackets.cs +++ b/Source/Game/Networking/Packets/PetPackets.cs @@ -183,7 +183,7 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt8((byte)Result); + _worldPacket.WriteUInt32((uint)Result); _worldPacket.WritePackedGuid(RenameData.PetGUID); _worldPacket.WriteInt32(RenameData.PetNumber); @@ -317,8 +317,8 @@ namespace Game.Networking.Packets public override void Write() { + _worldPacket.WriteInt32((int)Response); _worldPacket.WriteUInt32(SpellID); - _worldPacket.WriteUInt8((byte)Response); } public uint SpellID; @@ -345,10 +345,10 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt8(Result); + _worldPacket.WriteUInt32(Result); } - public byte Result; + public uint Result; } class PetMode : ServerPacket diff --git a/Source/Game/Networking/Packets/PetitionPackets.cs b/Source/Game/Networking/Packets/PetitionPackets.cs index 7e0a32273..99ef5d49a 100644 --- a/Source/Game/Networking/Packets/PetitionPackets.cs +++ b/Source/Game/Networking/Packets/PetitionPackets.cs @@ -294,7 +294,7 @@ namespace Game.Networking.Packets data.WriteInt32(AllowedMinLevel); data.WriteInt32(AllowedMaxLevel); data.WriteInt32(NumChoices); - data.WriteInt32(StaticType); + data.WriteInt8(StaticType); data.WriteUInt32(Muid); data.WriteBits(Title.GetByteCount(), 8); @@ -327,7 +327,7 @@ namespace Game.Networking.Packets public int AllowedMinLevel; public int AllowedMaxLevel; public int NumChoices; - public int StaticType; + public sbyte StaticType; public uint Muid = 0; public StringArray Choicetext = new(10); } diff --git a/Source/Game/Networking/Packets/QuestPackets.cs b/Source/Game/Networking/Packets/QuestPackets.cs index ece36a484..734fe3615 100644 --- a/Source/Game/Networking/Packets/QuestPackets.cs +++ b/Source/Game/Networking/Packets/QuestPackets.cs @@ -270,7 +270,7 @@ namespace Game.Networking.Packets _worldPacket.WriteInt32(ObjectID); _worldPacket.WriteUInt16(Count); _worldPacket.WriteUInt16(Required); - _worldPacket.WriteUInt8(ObjectiveType); + _worldPacket.WriteUInt32(ObjectiveType); } public ObjectGuid VictimGUID; @@ -278,7 +278,7 @@ namespace Game.Networking.Packets public uint QuestID; public ushort Count; public ushort Required; - public byte ObjectiveType; + public uint ObjectiveType; } class QuestUpdateAddCreditSimple : ServerPacket @@ -289,7 +289,7 @@ namespace Game.Networking.Packets { _worldPacket.WriteUInt32(QuestID); _worldPacket.WriteInt32(ObjectID); - _worldPacket.WriteUInt8((byte)ObjectiveType); + _worldPacket.WriteUInt32((uint)ObjectiveType); } public uint QuestID; @@ -748,7 +748,7 @@ namespace Game.Networking.Packets public override void Write() { _worldPacket.WritePackedGuid(SenderGUID); - _worldPacket.WriteUInt8((byte)Result); + _worldPacket.WriteUInt32((uint)Result); _worldPacket.WriteBits(QuestTitle.GetByteCount(), 9); _worldPacket.FlushBits(); @@ -769,7 +769,7 @@ namespace Game.Networking.Packets { SenderGUID = _worldPacket.ReadPackedGuid(); QuestID = _worldPacket.ReadUInt32(); - Result = (QuestPushReason)_worldPacket.ReadUInt8(); + Result = (QuestPushReason)_worldPacket.ReadUInt32(); } public ObjectGuid SenderGUID; diff --git a/Source/Game/Networking/Packets/SpellPackets.cs b/Source/Game/Networking/Packets/SpellPackets.cs index ce67b2d26..7959dabeb 100644 --- a/Source/Game/Networking/Packets/SpellPackets.cs +++ b/Source/Game/Networking/Packets/SpellPackets.cs @@ -736,9 +736,9 @@ namespace Game.Networking.Packets _worldPacket.WriteVector3(TargetPosition); _worldPacket.WriteUInt32(SpellVisualID); _worldPacket.WriteFloat(TravelSpeed); - _worldPacket.WriteUInt16(HitReason); - _worldPacket.WriteUInt16(MissReason); - _worldPacket.WriteUInt16(ReflectStatus); + _worldPacket.WriteUInt8(HitReason); + _worldPacket.WriteUInt8(MissReason); + _worldPacket.WriteUInt8(ReflectStatus); _worldPacket.WriteFloat(LaunchDelay); _worldPacket.WriteFloat(MinDuration); _worldPacket.WriteBit(SpeedAsTime); @@ -751,9 +751,9 @@ namespace Game.Networking.Packets public Vector3 TargetPosition; // Overrides missile destination for SpellVisual::SpellVisualMissileSetID public uint SpellVisualID; public float TravelSpeed; - public ushort HitReason; - public ushort MissReason; - public ushort ReflectStatus; + public byte HitReason; + public byte MissReason; + public byte ReflectStatus; public float LaunchDelay; public float MinDuration; public bool SpeedAsTime; @@ -1686,6 +1686,7 @@ namespace Game.Networking.Packets data.WriteInt32(ContentTuningID); data.WriteVector3(DstLocation); data.WriteBit(CastUnit.HasValue); + data.WriteBit(CastItem.HasValue); data.WriteBit(Duration.HasValue); data.WriteBit(Remaining.HasValue); data.WriteBit(TimeMod.HasValue); @@ -1699,6 +1700,9 @@ namespace Game.Networking.Packets if (CastUnit.HasValue) data.WritePackedGuid(CastUnit.Value); + if (CastItem.HasValue) + data.WritePackedGuid(CastItem.Value); + if (Duration.HasValue) data.WriteInt32(Duration.Value); @@ -1725,6 +1729,7 @@ namespace Game.Networking.Packets public int ContentTuningID; ContentTuningParams ContentTuning; public ObjectGuid? CastUnit; + public ObjectGuid? CastItem; public int? Duration; public int? Remaining; float? TimeMod; @@ -1776,8 +1781,10 @@ namespace Game.Networking.Packets { public void Read(WorldPacket data) { - data.ResetBitPos(); - Flags = (SpellCastTargetFlags)data.ReadBits(28); + Flags = (SpellCastTargetFlags)data.ReadUInt32(); + Unit = data.ReadPackedGuid(); + Item = data.ReadPackedGuid(); + if (data.HasBit()) SrcLocation = new(); @@ -1789,9 +1796,6 @@ namespace Game.Networking.Packets uint nameLength = data.ReadBits(7); - Unit = data.ReadPackedGuid(); - Item = data.ReadPackedGuid(); - if (SrcLocation != null) SrcLocation.Read(data); @@ -1809,7 +1813,10 @@ namespace Game.Networking.Packets public void Write(WorldPacket data) { - data.WriteBits((uint)Flags, 28); + data.WriteUInt32((uint)Flags); + data.WritePackedGuid(Unit); + data.WritePackedGuid(Item); + data.WriteBit(SrcLocation != null); data.WriteBit(DstLocation != null); data.WriteBit(Orientation.HasValue); @@ -1817,9 +1824,6 @@ namespace Game.Networking.Packets data.WriteBits(Name.GetByteCount(), 7); data.FlushBits(); - data.WritePackedGuid(Unit); - data.WritePackedGuid(Item); - if (SrcLocation != null) SrcLocation.Write(data); @@ -1914,6 +1918,7 @@ namespace Game.Networking.Packets public void Read(WorldPacket data) { CastID = data.ReadPackedGuid(); + SendCastFlags = data.ReadUInt32(); Misc[0] = data.ReadUInt32(); Misc[1] = data.ReadUInt32(); SpellID = data.ReadUInt32(); @@ -1931,19 +1936,19 @@ namespace Game.Networking.Packets for (var i = 0; i < optionalCurrenciesCount; ++i) OptionalCurrencies[i].Read(data); - SendCastFlags = data.ReadBits(6); + Target.Read(data); + + data.ResetBitPos(); bool hasMoveUpdate = data.HasBit(); var weightCount = data.ReadBits(2); bool hasCraftingOrderID = data.HasBit(); - Target.Read(data); + for (var i = 0; i < optionalReagentsCount; ++i) + OptionalReagents[i].Read(data); if (hasCraftingOrderID) CraftingOrderID = data.ReadUInt64(); - for (var i = 0; i < optionalReagentsCount; ++i) - OptionalReagents[i].Read(data); - for (var i = 0; i < removedModificationsCount; ++i) RemovedModifications[i].Read(data); @@ -2046,7 +2051,7 @@ namespace Game.Networking.Packets public void Write(WorldPacket data) { data.WriteUInt32(Points); - data.WriteUInt8((byte)Type); + data.WriteUInt32((uint)Type); data.WritePackedGuid(BeaconGUID); } } diff --git a/Source/Game/Networking/Packets/SystemPackets.cs b/Source/Game/Networking/Packets/SystemPackets.cs index fd1ec0d6f..8eade5b70 100644 --- a/Source/Game/Networking/Packets/SystemPackets.cs +++ b/Source/Game/Networking/Packets/SystemPackets.cs @@ -46,6 +46,10 @@ namespace Game.Networking.Packets _worldPacket.WriteInt32(AddonChatThrottle.MaxTries); _worldPacket.WriteInt32(AddonChatThrottle.TriesRestoredPerSecond); _worldPacket.WriteInt32(AddonChatThrottle.UsedTriesPerMessage); + _worldPacket.WriteInt32(GuildChatThrottle.UsedTriesPerMessage); + _worldPacket.WriteInt32(GuildChatThrottle.TriesRestoredPerSecond); + _worldPacket.WriteInt32(GroupChatThrottle.UsedTriesPerMessage); + _worldPacket.WriteInt32(GroupChatThrottle.TriesRestoredPerSecond); _worldPacket.WriteFloat(AddonPerformanceMsgWarning); _worldPacket.WriteFloat(AddonPerformanceMsgError); @@ -202,7 +206,9 @@ namespace Game.Networking.Packets public int ActiveTimerunningSeasonID; public int RemainingTimerunningSeasonSeconds; public string Unknown1027; // related to movement lua functions used by keybinds - public AddonChatThrottleParams AddonChatThrottle; + public ChatThrottleParams AddonChatThrottle; + public ChatThrottleParams GuildChatThrottle; + public ChatThrottleParams GroupChatThrottle; public uint RealmPvpTypeOverride; ///< Use Cfg_Configs value = 0, ForceEnabled = 1, ForceDisabled = 2 public float AddonPerformanceMsgWarning; public float AddonPerformanceMsgError; @@ -288,7 +294,7 @@ namespace Game.Networking.Packets public uint RewardsVersion; } - public struct AddonChatThrottleParams + public struct ChatThrottleParams { public int MaxTries; public int TriesRestoredPerSecond; @@ -362,6 +368,8 @@ namespace Game.Networking.Packets _worldPacket.WriteInt32(GameRules.Count); _worldPacket.WriteInt32(ActiveTimerunningSeasonID); _worldPacket.WriteInt32(RemainingTimerunningSeasonSeconds); + _worldPacket.WriteInt32((int)TimerunningConversionMinCharacterAge.TotalSeconds); + _worldPacket.WriteInt32(TimerunningConversionMaxSeasonID); _worldPacket.WriteInt16(MaxPlayerGuidLookupsPerRequest); _worldPacket.WriteInt16(NameLookupTelemetryInterval); _worldPacket.WriteUInt32((uint)NotFoundCacheTimeSeconds.TotalSeconds); @@ -429,6 +437,8 @@ namespace Game.Networking.Packets public List GameRules = new(); public int ActiveTimerunningSeasonID; public int RemainingTimerunningSeasonSeconds; + public TimeSpan TimerunningConversionMinCharacterAge = TimeSpan.FromDays(1); + public int TimerunningConversionMaxSeasonID = -1; public short MaxPlayerGuidLookupsPerRequest = 50; public short NameLookupTelemetryInterval = 600; public TimeSpan NotFoundCacheTimeSeconds = TimeSpan.FromSeconds(10); @@ -439,6 +449,18 @@ namespace Game.Networking.Packets public string RealmHiddenAlert; } + class MirrorVars() : ServerPacket(ServerOpcodes.MirrorVars) + { + public MirrorVarSingle[] Variables; + + public override void Write() + { + _worldPacket.WriteInt32(Variables.Length); + foreach (MirrorVarSingle variable in Variables) + variable.Write(_worldPacket); + } + } + public class SetTimeZoneInformation : ServerPacket { public SetTimeZoneInformation() : base(ServerOpcodes.SetTimeZoneInformation) { } @@ -524,4 +546,29 @@ namespace Game.Networking.Packets data.WriteString(Text); } } + + public struct MirrorVarSingle + { + public string Name; + public string Value; + public int UpdateType; + + public MirrorVarSingle(string name, string value, int updateType = 0) + { + Name = name; + Value = value; + UpdateType = updateType; + } + + public void Write(WorldPacket data) + { + data.WriteBits(UpdateType, 1); + data.WriteBits(Name.GetByteCount(), 24); + data.WriteBits(Value.GetByteCount(), 24); + data.FlushBits(); + + data.WriteCString(Name); + data.WriteCString(Value); + } + } } diff --git a/Source/Game/Networking/Packets/TalentPackets.cs b/Source/Game/Networking/Packets/TalentPackets.cs index dfc64e939..91fefa32a 100644 --- a/Source/Game/Networking/Packets/TalentPackets.cs +++ b/Source/Game/Networking/Packets/TalentPackets.cs @@ -224,6 +224,7 @@ namespace Game.Networking.Packets public List GlyphIDs = new(); public sbyte Role; public int PrimarySpecialization; + public bool Unused1125; public void Write(WorldPacket data) { @@ -241,6 +242,9 @@ namespace Game.Networking.Packets foreach (ushort id in GlyphIDs) data.WriteUInt16(id); + + data.WriteBit(Unused1125); + data.FlushBits(); } } diff --git a/Source/Game/Networking/Packets/TokenPackets.cs b/Source/Game/Networking/Packets/TokenPackets.cs index 03c73c191..3464d9049 100644 --- a/Source/Game/Networking/Packets/TokenPackets.cs +++ b/Source/Game/Networking/Packets/TokenPackets.cs @@ -32,8 +32,8 @@ namespace Game.Networking.Packets { _worldPacket.WriteUInt64(auctionableTokenAuctionable.Id); _worldPacket.WriteInt64(auctionableTokenAuctionable.LastUpdate); - _worldPacket.WriteUInt64(auctionableTokenAuctionable.Price); _worldPacket.WriteUInt32(auctionableTokenAuctionable.Status); + _worldPacket.WriteUInt64(auctionableTokenAuctionable.Price); _worldPacket.WriteUInt32(auctionableTokenAuctionable.DurationLeft); } } @@ -70,15 +70,15 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WriteUInt64(PriceGuarantee); _worldPacket.WriteUInt32(ClientToken); _worldPacket.WriteUInt32((uint)ServerToken); + _worldPacket.WriteUInt64(PriceGuarantee); _worldPacket.WriteUInt32(PriceLockDurationSeconds); } - public ulong PriceGuarantee; public uint ClientToken; public TokenResult ServerToken; + public ulong PriceGuarantee; public uint PriceLockDurationSeconds; } } diff --git a/Source/Game/Networking/Packets/TraitPackets.cs b/Source/Game/Networking/Packets/TraitPackets.cs index f921af854..f395e94e9 100644 --- a/Source/Game/Networking/Packets/TraitPackets.cs +++ b/Source/Game/Networking/Packets/TraitPackets.cs @@ -130,6 +130,7 @@ namespace Game.Networking.Packets TraitNodeEntryID = ufEntry.TraitNodeEntryID; Rank = ufEntry.Rank; GrantedRanks = ufEntry.GrantedRanks; + BonusRanks = ufEntry.BonusRanks; } public void Read(WorldPacket data) @@ -205,6 +206,7 @@ namespace Game.Networking.Packets public int LocalIdentifier; // Local to specialization public uint SkillLineID; public uint TraitSystemID; + public int VariationID; public List Entries = new(); public List SubTrees = new(); public string Name = ""; @@ -220,6 +222,7 @@ namespace Game.Networking.Packets LocalIdentifier = ufConfig.LocalIdentifier; SkillLineID = (uint)(int)ufConfig.SkillLineID; TraitSystemID = ufConfig.TraitSystemID; + VariationID = ufConfig.VariationID; foreach (TraitEntry ufEntry in ufConfig.Entries) Entries.Add(new TraitEntryPacket(ufEntry)); foreach (var ufSubTree in ufConfig.SubTrees) @@ -246,6 +249,7 @@ namespace Game.Networking.Packets break; case TraitConfigType.Generic: TraitSystemID = data.ReadUInt32(); + VariationID = data.ReadInt32(); break; default: break; @@ -289,6 +293,7 @@ namespace Game.Networking.Packets break; case TraitConfigType.Generic: data.WriteUInt32(TraitSystemID); + data.WriteInt32(VariationID); break; default: break; diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 4ce7d4309..9e2865e3b 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -262,6 +262,9 @@ namespace Game.Spells else if (!auraData.Flags.HasFlag(AuraFlags.NoCaster)) auraData.CastUnit = aura.GetCasterGUID(); + if (!aura.GetCastItemGUID().IsEmpty()) + auraData.CastItem = aura.GetCastItemGUID(); + if (auraData.Flags.HasFlag(AuraFlags.Duration)) { auraData.Duration = aura.GetMaxDuration(); diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index cc6596779..8d2ff2135 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -5935,13 +5935,29 @@ namespace Game.Spells return; newConfig.TraitSystemID = CliDB.TraitTreeStorage.LookupByKey(effectInfo.MiscValue).TraitSystemID; - int existingConfigForSystem = target.m_activePlayerData.TraitConfigs.FindIndexIf(config => + TraitSystemRecord traitSystem = CliDB.TraitSystemStorage.LookupByKey(newConfig.TraitSystemID); + if (traitSystem == null) + return; + + switch (traitSystem.GetVariationType()) + { + case TraitSystemVariationType.None: + newConfig.VariationID = 0; + break; + case TraitSystemVariationType.Spec: + newConfig.VariationID = (int)target.GetPrimarySpecialization(); + break; + default: + return; + } + + int existingConfigIdForSystem = target.m_activePlayerData.TraitConfigs.FindIf(config => { return config.Type == (int)TraitConfigType.Generic && config.TraitSystemID == newConfig.TraitSystemID; - }); + }).Item1; - if (existingConfigForSystem < 0) + if (existingConfigIdForSystem == 0) target.CreateTraitConfig(newConfig); } diff --git a/Source/Game/Spells/TraitManager.cs b/Source/Game/Spells/TraitManager.cs index b890667b0..ea28f705a 100644 --- a/Source/Game/Spells/TraitManager.cs +++ b/Source/Game/Spells/TraitManager.cs @@ -139,7 +139,7 @@ namespace Game if (tree != null) tree.SubTrees.Add(subTree); - _traitSubTrees[(int)traitSubTree.ID] = subTree; + _traitSubTrees[(int)traitSubTree.Id] = subTree; } foreach (var (_, traitNodeGroup) in CliDB.TraitNodeGroupStorage) @@ -470,6 +470,12 @@ namespace Game } } break; + case TraitCurrencyType.TraitSourcedPlayerDataElement: + if (currency.PlayerDataElementAccountID != 0) + currencies[currency.Id] += player.GetDataElementAccount((uint)currency.CurrencyTypesID); + else if (currency.PlayerDataElementCharacterID != 0) + currencies[currency.Id] += player.GetDataElementCharacter((uint)currency.CurrencyTypesID); + break; default: break; }