diff --git a/Source/BNetServer/Managers/LoginServiceManager.cs b/Source/BNetServer/Managers/LoginServiceManager.cs index 46e286b06..047bbdd49 100644 --- a/Source/BNetServer/Managers/LoginServiceManager.cs +++ b/Source/BNetServer/Managers/LoginServiceManager.cs @@ -64,6 +64,11 @@ namespace BNetServer { return certificate; } + + public bool UsesDevWildcardCertificate() + { + return certificate.Subject.Contains("*.*"); + } } public class BnetServiceHandler diff --git a/Source/BNetServer/Networking/Services/Authentication.cs b/Source/BNetServer/Networking/Services/Authentication.cs index f172118f1..88bcad75f 100644 --- a/Source/BNetServer/Networking/Services/Authentication.cs +++ b/Source/BNetServer/Networking/Services/Authentication.cs @@ -57,7 +57,7 @@ namespace BNetServer.Networking ChallengeExternalRequest externalChallenge = new(); externalChallenge.PayloadType = "web_auth_url"; - externalChallenge.Payload = ByteString.CopyFromUtf8($"https://{Global.LoginService.GetHostnameForClient(GetRemoteIpAddress())}:{Global.LoginService.GetPort()}/bnetserver/login/"); + externalChallenge.Payload = ByteString.CopyFromUtf8($"http{(!Global.LoginServiceMgr.UsesDevWildcardCertificate() ? "s" : "")}://{Global.LoginService.GetHostnameForClient(GetRemoteIpAddress())}:{Global.LoginService.GetPort()}/bnetserver/login/"); SendRequest((uint)OriginalHash.ChallengeListener, 3, externalChallenge); return BattlenetRpcErrorCode.Ok; diff --git a/Source/BNetServer/Networking/Session.cs b/Source/BNetServer/Networking/Session.cs index 9322ec2bb..35dc4a76a 100644 --- a/Source/BNetServer/Networking/Session.cs +++ b/Source/BNetServer/Networking/Session.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; namespace BNetServer.Networking { - public partial class Session : SSLSocket + public partial class Session : SocketBase { AccountInfo accountInfo; GameAccountInfo gameAccountInfo; @@ -34,7 +34,7 @@ namespace BNetServer.Networking AsyncCallbackProcessor queryProcessor; Dictionary> responseCallbacks; - public Session(Socket socket) : base(socket) + public Session(Socket socket) : base(socket, true) { clientSecret = new byte[32]; queryProcessor = new AsyncCallbackProcessor(); @@ -294,4 +294,4 @@ namespace BNetServer.Networking public ulong CharacterGUID; public uint LastPlayedTime; } -} +} \ No newline at end of file diff --git a/Source/BNetServer/REST/LoginHttpSession.cs b/Source/BNetServer/REST/LoginHttpSession.cs index 409d3d5d5..89ba4c68a 100644 --- a/Source/BNetServer/REST/LoginHttpSession.cs +++ b/Source/BNetServer/REST/LoginHttpSession.cs @@ -16,11 +16,11 @@ namespace BNetServer.REST public BnetSRP6Base Srp; } - public class LoginHttpSession : SslSocket + public class LoginHttpSession : BaseHttpSocket { public static string SESSION_ID_COOKIE = "JSESSIONID"; - public LoginHttpSession(Socket socket) : base(socket) { } + public LoginHttpSession(Socket socket) : base(socket, !Global.LoginServiceMgr.UsesDevWildcardCertificate()) { } public override void Start() { @@ -56,7 +56,10 @@ namespace BNetServer.REST } } - await AsyncHandshake(Global.LoginServiceMgr.GetCertificate()); + if (!Global.LoginServiceMgr.UsesDevWildcardCertificate()) + await AsyncHandshake(Global.LoginServiceMgr.GetCertificate()); + else + await AsyncRead(); } public override RequestHandlerResult RequestHandler(RequestContext context) diff --git a/Source/BNetServer/REST/LoginRESTService.cs b/Source/BNetServer/REST/LoginRESTService.cs index 0bfdc400b..343c394fe 100644 --- a/Source/BNetServer/REST/LoginRESTService.cs +++ b/Source/BNetServer/REST/LoginRESTService.cs @@ -132,7 +132,7 @@ namespace BNetServer.REST RequestHandlerResult HandleGetForm(LoginHttpSession session, RequestContext context) { FormInputs form = _formInputs; - form.SrpUrl = $"https://{GetHostnameForClient(session.GetRemoteIpAddress())}:{_port}/bnetserver/login/srp/"; + form.SrpUrl = $"http{(!Global.LoginServiceMgr.UsesDevWildcardCertificate() ? "s" : "")}://{GetHostnameForClient(session.GetRemoteIpAddress())}:{_port}/bnetserver/login/srp/"; context.response.ContentType = "application/json;charset=utf-8"; context.response.Content = JsonSerializer.Serialize(form); diff --git a/Source/Framework/Constants/Authentication/BattlenetConst.cs b/Source/Framework/Constants/Authentication/BattlenetConst.cs index 610018292..568b97b4d 100644 --- a/Source/Framework/Constants/Authentication/BattlenetConst.cs +++ b/Source/Framework/Constants/Authentication/BattlenetConst.cs @@ -13,44 +13,28 @@ namespace Framework.Constants NotStarted = 0x00000005, InProgress = 0x00000006, InvalidArgs = 0x00000007, - InvalidSubscriber = 0x00000008, - WaitingForDependency = 0x00000009, NoAuth = 0x0000000a, ParentalControlRestriction = 0x0000000b, NoGameAccount = 0x0000000c, NotImplemented = 0x0000000d, - ObjectRemoved = 0x0000000e, - InvalidEntityId = 0x0000000f, - InvalidEntityAccountId = 0x00000010, - InvalidEntityGameAccountId = 0x00000011, InvalidAgentId = 0x00000013, InvalidTargetId = 0x00000014, - ModuleNotLoaded = 0x00000015, - ModuleNoEntryPoint = 0x00000016, - ModuleSignatureIncorrect = 0x00000017, - ModuleCreateFailed = 0x00000018, NoProgram = 0x00000019, ApiNotReady = 0x0000001b, BadVersion = 0x0000001c, AttributeTooManyAttributesSet = 0x0000001d, AttributeMaxSizeExceeded = 0x0000001e, AttributeQuotaExceeded = 0x0000001f, - ServerPoolServerDisappeared = 0x00000020, ServerIsPrivate = 0x00000021, Disabled = 0x00000022, - ModuleNotFound = 0x00000024, ServerBusy = 0x00000025, NoBattletag = 0x00000026, - IncompleteProfanityFilters = 0x00000027, InvalidRegion = 0x00000028, ExistsAlready = 0x00000029, - InvalidServerThumbprint = 0x0000002a, PhoneLock = 0x0000002b, Squelched = 0x0000002c, TargetOffline = 0x0000002d, BadServer = 0x0000002e, - NoCookie = 0x0000002f, - ExpiredCookie = 0x00000030, TokenNotFound = 0x00000031, GameAccountNoTime = 0x00000032, GameAccountNoPlan = 0x00000033, @@ -60,13 +44,17 @@ namespace Framework.Constants GameAccountCancelled = 0x00000037, GameAccountCreationDisabled = 0x00000038, GameAccountLocked = 0x00000039, - + GameAccountPhoneLock = 0x0000003a, + GameAccountBillingLock = 0x0000003b, SessionDuplicate = 0x0000003c, SessionDisconnected = 0x0000003d, SessionDataChanged = 0x0000003e, SessionUpdateFailed = 0x0000003f, SessionNotFound = 0x00000040, - + SessionFreePlayNotSupported = 0x00000041, + SessionSubscriptionAdded = 0x00000042, + SessionConsumptionTimeAdded = 0x00000043, + SessionTokenNotFound = 0x00000044, AdminKick = 0x00000046, UnplannedMaintenance = 0x00000047, PlannedMaintenance = 0x00000048, @@ -82,42 +70,29 @@ namespace Framework.Constants LocaleRestrictedKo = 0x00000053, LocaleRestrictedTw = 0x00000054, LocaleRestricted = 0x00000055, - AccountNeedsMaintenance = 0x00000056, - ModuleApiError = 0x00000057, - ModuleBadCacheHandle = 0x00000058, - ModuleAlreadyLoaded = 0x00000059, - NetworkBlacklisted = 0x0000005a, + NetworkBlocklisted = 0x0000005a, EventProcessorSlow = 0x0000005b, ServerShuttingDown = 0x0000005c, NetworkNotPrivileged = 0x0000005d, TooManyOutstandingRequests = 0x0000005e, - NoAccountRegistered = 0x0000005f, BattlenetAccountBanned = 0x00000060, - - OkDeprecated = 0x00000064, ServerInModeZombie = 0x00000065, + AgentIsBlockingTarget = 0x00000066, + TargetIsBlockingAgent = 0x00000067, + FeatureUnavailable = 0x00000068, + BrokenPromise = 0x00000069, + UninitializedExpected = 0x0000006a, + NoSslConnection = 0x0000006b, + ServiceNotReady = 0x0000006e, - LogonModuleRequired = 0x000001f4, - LogonModuleNotConfigured = 0x000001f5, - LogonModuleTimeout = 0x000001f6, - LogonAgreementRequired = 0x000001fe, - LogonAgreementNotConfigured = 0x000001ff, - - LogonInvalidServerProof = 0x00000208, LogonWebVerifyTimeout = 0x00000209, LogonInvalidAuthToken = 0x0000020a, - - ChallengeSmsTooSoon = 0x00000258, - ChallengeSmsThrottled = 0x00000259, - ChallengeSmsTempOutage = 0x0000025a, - ChallengeNoChallenge = 0x0000025b, - ChallengeNotPicked = 0x0000025c, - ChallengeAlreadyPicked = 0x0000025d, - ChallengeInProgress = 0x0000025e, + LogonTassadarRequestFailed = 0x0000020b, ConfigFormatInvalid = 0x000002bc, ConfigNotFound = 0x000002bd, ConfigRetrieveFailed = 0x000002be, + ConfigDumpFailed = 0x000002bf, NetworkModuleBusy = 0x000003e8, NetworkModuleCantResolveAddress = 0x000003e9, @@ -136,12 +111,10 @@ namespace Framework.Constants NetworkModuleNoSslCommonNameForCertificate = 0x000003f6, NetworkModuleSslCommonNameDoesNotMatchRemoteEndpoint = 0x000003f7, NetworkModuleSocketClosed = 0x000003f8, - NetworkModuleSslPeerIsNotRegisteredInCertbundle = 0x000003f9, - NetworkModuleSslInitializeLowFirst = 0x000003fa, - NetworkModuleSslCertBundleReadError = 0x000003fb, - NetworkModuleNoCertBundle = 0x000003fc, - NetworkModuleFailedToDownloadCertBundle = 0x000003fd, NetworkModuleNotReadyToRead = 0x000003fe, + NetworkModuleSslCertChainValidationFailed = 0x000003ff, + NetworkModuleNetworkDown = 0x00000401, + NetworkModuleSslInitializationFailed = 0x00000402, NetworkModuleOpensslX509Ok = 0x000004b0, NetworkModuleOpensslX509UnableToGetIssuerCert = 0x000004b1, @@ -183,6 +156,7 @@ namespace Framework.Constants NetworkModuleSchannelCannotFindInterface = 0x00000517, NetworkModuleSchannelInitFail = 0x00000518, NetworkModuleSchannelFunctionCallFail = 0x00000519, + NetworkModuleSchannelHandshakeFailure = 0x0000051a, NetworkModuleSchannelX509UnableToGetIssuerCert = 0x00000546, NetworkModuleSchannelX509TimeInvalid = 0x00000547, NetworkModuleSchannelX509SignatureInvalid = 0x00000548, @@ -190,24 +164,31 @@ namespace Framework.Constants NetworkModuleSchannelX509SelfSignedLeafCertificate = 0x0000054a, NetworkModuleSchannelX509UnhandledError = 0x0000054b, NetworkModuleSchannelX509SelfSignedCertInChain = 0x0000054c, - WebsocketHandshake = 0x00000578, - NetworkModuleDurangoUnknown = 0x000005dc, NetworkModuleDurangoMalformedHostName = 0x000005dd, NetworkModuleDurangoInvalidConnectionResponse = 0x000005de, NetworkModuleDurangoInvalidCaCert = 0x000005df, + NetworkModuleDarwinsslFunctionCallFail = 0x00000640, + NetworkModuleDarwinsslX509NeverTrust = 0x00000672, + NetworkModuleDarwinsslX509UnknownError = 0x00000676, + NetworkModuleSceSslContextAllocateFailed = 0x000006a4, + NetworkModuleSceSslConnectionAllocateFailed = 0x000006a5, + NetworkModuleSceSslSetVerifyOptionFailed = 0x000006a6, + NetworkModuleSceSslHandshakeFailed = 0x000006a7, + + SdkMessageHandlerNotFound = 0x0000076c, + SdkTassadarClientInvalidInput = 0x00000776, + SdkTassadarServerError = 0x00000777, + SdkTassadarServerMaintenance = 0x00000778, RpcWriteFailed = 0x00000bb8, - RpcServiceNotBound = 0x00000bb9, RpcTooManyRequests = 0x00000bba, RpcPeerUnknown = 0x00000bbb, RpcPeerUnavailable = 0x00000bbc, RpcPeerDisconnected = 0x00000bbd, RpcRequestTimedOut = 0x00000bbe, - RpcConnectionTimedOut = 0x00000bbf, RpcMalformedResponse = 0x00000bc0, - RpcAccessDenied = 0x00000bc1, RpcInvalidService = 0x00000bc2, RpcInvalidMethod = 0x00000bc3, RpcInvalidObject = 0x00000bc4, @@ -217,30 +198,25 @@ namespace Framework.Constants RpcServerError = 0x00000bc8, RpcShutdown = 0x00000bc9, RpcDisconnect = 0x00000bca, - RpcDisconnectIdle = 0x00000bcb, RpcProtocolError = 0x00000bcc, RpcNotReady = 0x00000bcd, RpcForwardFailed = 0x00000bce, - RpcEncryptionFailed = 0x00000bcf, RpcInvalidAddress = 0x00000bd0, RpcMethodDisabled = 0x00000bd1, RpcShardNotFound = 0x00000bd2, RpcInvalidConnectionId = 0x00000bd3, RpcNotConnected = 0x00000bd4, RpcInvalidConnectionState = 0x00000bd5, - RpcServiceAlreadyRegistered = 0x00000bd6, + RpcConnectionUnreachable = 0x00000bd7, + RpcNoBufferSpace = 0x00000bd8, + RpcHttpProbe = 0x00000bd9, + RpcClientIdRequired = 0x00000bda, + RpcConnectionReplaced = 0x00000bdb, + RpcInvalidRoute = 0x00000bdc, - PresenceInvalidFieldId = 0x00000fa0, - PresenceNoValidSubscribers = 0x00000fa1, - PresenceAlreadySubscribed = 0x00000fa2, - PresenceConsumerNotFound = 0x00000fa3, - PresenceConsumerIsNull = 0x00000fa4, - PresenceTemporaryOutage = 0x00000fa5, PresenceTooManySubscriptions = 0x00000fa6, - PresenceSubscriptionCancelled = 0x00000fa7, - PresenceRichPresenceParseError = 0x00000fa8, - PresenceRichPresenceXmlError = 0x00000fa9, - PresenceRichPresenceLoadError = 0x00000faa, + PresenceNoRecord = 0x00000fab, + PresenceNoChange = 0x00000fac, FriendsTooManySentInvitations = 0x00001389, FriendsTooManyReceivedInvitations = 0x0000138a, @@ -248,7 +224,6 @@ namespace Framework.Constants FriendsFriendshipDoesNotExist = 0x0000138c, FriendsInvitationAlreadyExists = 0x0000138d, FriendsInvalidInvitation = 0x0000138e, - FriendsAlreadySubscribed = 0x0000138f, FriendsAccountBlocked = 0x00001391, FriendsNotSubscribed = 0x00001392, FriendsInvalidRoleId = 0x00001393, @@ -257,11 +232,20 @@ namespace Framework.Constants FriendsUpdateFriendStateFailed = 0x00001396, FriendsInviteeAtMaxFriends = 0x00001397, FriendsInviterAtMaxFriends = 0x00001398, + FriendsInviterIsBlockedByInvitee = 0x00001399, + FriendsReceivedInvitationUndeliverable = 0x0000139a, + FriendsMuted = 0x0000139b, + FriendsReceivedInvitationIgnored = 0x0000139c, + FriendsTransactionAlreadyExists = 0x0000139d, + FriendsMergedFriendsAboveLimit = 0x0000139e, PlatformStorageFileWriteDenied = 0x00001770, WhisperUndeliverable = 0x00001b58, WhisperMaxSizeExceeded = 0x00001b59, + WhisperAlreadyRegistered = 0x00001b5a, + WhisperDropped = 0x00001b5b, + WhisperQuotaExceeded = 0x00001b5c, UserManagerAlreadyBlocked = 0x00001f40, UserManagerNotBlocked = 0x00001f41, @@ -275,73 +259,88 @@ namespace Framework.Constants UserManagerUnblockEntityFailed = 0x00001f51, UserManagerCannotBlockFriend = 0x00001f53, - SocialNetworkDbException = 0x00002328, - SocialNetworkDenialFromProvider = 0x00002329, - SocialNetworkInvalidSnsId = 0x0000232a, - SocialNetworkCantSendToProvider = 0x0000232b, - SocialNetworkExCommFailed = 0x0000232c, - SocialNetworkDisabled = 0x0000232d, - SocialNetworkMissingRequestParam = 0x0000232e, - SocialNetworkUnsupportedOauthVersion = 0x0000232f, + SocialNetworkOauthException = 0x00002328, + SocialNetworkInvalidSnsId = 0x00002329, + SocialNetworkCantSendToProvider = 0x0000232a, + SocialNetworkDisabled = 0x0000232b, + SocialNetworkMissingRequestParam = 0x0000232c, + SocialNetworkNoAccountData = 0x0000232d, + SocialNetworkNoToken = 0x0000232e, + SocialNetworkMissingDataFromProvider = 0x0000232f, + SocialNetworkResponseNotParsable = 0x00002330, + SocialNetworkTokenPermissionDenied = 0x00002331, + SocialNetworkDenialFromProvider = 0x00002332, ChannelFull = 0x00002710, ChannelNoChannel = 0x00002711, ChannelNotMember = 0x00002712, ChannelAlreadyMember = 0x00002713, ChannelNoSuchMember = 0x00002714, - ChannelInvalidChannelId = 0x00002716, ChannelNoSuchInvitation = 0x00002718, ChannelTooManyInvitations = 0x00002719, ChannelInvitationAlreadyExists = 0x0000271a, - ChannelInvalidChannelSize = 0x0000271b, ChannelInvalidRoleId = 0x0000271c, ChannelRoleNotAssignable = 0x0000271d, ChannelInsufficientPrivileges = 0x0000271e, ChannelInsufficientPrivacyLevel = 0x0000271f, ChannelInvalidPrivacyLevel = 0x00002720, ChannelTooManyChannelsJoined = 0x00002721, - ChannelInvitationAlreadySubscribed = 0x00002722, ChannelInvalidChannelDelegate = 0x00002723, ChannelSlotAlreadyReserved = 0x00002724, - ChannelSlotNotReserved = 0x00002725, ChannelNoReservedSlotsAvailable = 0x00002726, ChannelInvalidRoleSet = 0x00002727, - ChannelRequireFriendValidation = 0x00002728, - ChannelMemberOffline = 0x00002729, ChannelReceivedTooManyInvitations = 0x0000272a, ChannelInvitationInvalidGameAccountSelected = 0x0000272b, - ChannelUnreachable = 0x0000272c, ChannelInvitationNotSubscribed = 0x0000272d, - ChannelInvalidMessageSize = 0x0000272e, - ChannelMaxMessageSizeExceeded = 0x0000272f, - ChannelConfigNotFound = 0x00002730, ChannelInvalidChannelType = 0x00002731, + ChannelInvalidIndex = 0x00002732, + ChannelMembershipNotSubscribed = 0x00002733, + ChannelAlreadySubscribed = 0x00002734, - LocalStorageFileOpenError = 0x00002af8, - LocalStorageFileCreateError = 0x00002af9, - LocalStorageFileReadError = 0x00002afa, - LocalStorageFileWriteError = 0x00002afb, - LocalStorageFileDeleteError = 0x00002afc, - LocalStorageFileCopyError = 0x00002afd, - LocalStorageFileDecompressError = 0x00002afe, - LocalStorageFileHashMismatch = 0x00002aff, - LocalStorageFileUsageMismatch = 0x00002b00, - LocalStorageDatabaseInitError = 0x00002b01, - LocalStorageDatabaseNeedsRebuild = 0x00002b02, - LocalStorageDatabaseInsertError = 0x00002b03, - LocalStorageDatabaseLookupError = 0x00002b04, - LocalStorageDatabaseUpdateError = 0x00002b05, - LocalStorageDatabaseDeleteError = 0x00002b06, - LocalStorageDatabaseShrinkError = 0x00002b07, - LocalStorageCacheCrawlError = 0x00002b08, - LocalStorageDatabaseIndexTriggerError = 0x00002b09, - LocalStorageDatabaseRebuildInProgress = 0x00002b0a, - LocalStorageOkButNotInCache = 0x00002b0b, - LocalStorageDatabaseRebuildInterrupted = 0x00002b0d, - LocalStorageDatabaseNotInitialized = 0x00002b0e, - LocalStorageDirectoryCreateError = 0x00002b0f, - LocalStorageFilekeyNotFound = 0x00002b10, - LocalStorageNotAvailableOnServer = 0x00002b11, + ClubFull = 0x00002af8, + ClubNoClub = 0x00002af9, + ClubNotMember = 0x00002afa, + ClubAlreadyMember = 0x00002afb, + ClubNoSuchMember = 0x00002afc, + ClubNoSuchInvitation = 0x00002b00, + ClubInvitationAlreadyExists = 0x00002b02, + ClubInvalidRoleId = 0x00002b04, + ClubInsufficientPrivileges = 0x00002b06, + ClubInsufficientPrivacyLevel = 0x00002b07, + ClubInvalidPrivacyLevel = 0x00002b08, + ClubTooManyClubsJoined = 0x00002b09, + ClubInvalidRoleSet = 0x00002b0f, + ClubNotSubscribed = 0x00002b15, + ClubInvalidClubType = 0x00002b19, + ClubVoiceFull = 0x00002b1a, + ClubMemberSubscriptionsAtMax = 0x00002b1b, + ClubSuggestionAlreadyExists = 0x00002b20, + ClubSuggestionCountAtMax = 0x00002b21, + ClubNoSuchSuggestion = 0x00002b22, + ClubStreamNoStream = 0x00002b5c, + ClubStreamInvalidName = 0x00002b5d, + ClubStreamCountAtMin = 0x00002b5e, + ClubStreamCountAtMax = 0x00002b5f, + ClubStreamInvalidVoiceLevel = 0x00002b60, + ClubStreamNoSuchMessage = 0x00002b61, + ClubInvalidAvatar = 0x00002b75, + ClubMemberHasRequiredRole = 0x00002b76, + ClubInvalidRoleChangeRequest = 0x00002b77, + ClubSentInvitationCountAtMax = 0x00002b8e, + ClubReceivedInvitationCountAtMax = 0x00002b8f, + ClubTargetIsBanned = 0x00002b90, + ClubNoSuchBannedTarget = 0x00002b91, + ClubBanAlreadyExists = 0x00002b92, + ClubBanCountAtMax = 0x00002b93, + ClubTicketCountAtMax = 0x00002ba2, + ClubTicketNoSuchTicket = 0x00002ba3, + ClubTicketHasConsumedAllowedRedeemCount = 0x00002ba4, + + ClubMembershipSubscriptionsAtMax = 0x00002e19, + ClubMembershipPushNotificationRegistrationsAtMax = 0x00002e1a, + ClubTagAlreadyExists = 0x00002e1b, + ClubTagNoSuchTag = 0x00002e1c, + ClubTagTooManyTags = 0x00002e1d, RegistryCreateKeyError = 0x00002ee0, RegistryOpenKeyError = 0x00002ee1, @@ -351,18 +350,10 @@ namespace Framework.Constants RegistryDeleteError = 0x00002ee5, RegistryEncryptError = 0x00002ee6, RegistryDecryptError = 0x00002ee7, - RegistryKeySizeError = 0x00002ee8, RegistryValueSizeError = 0x00002ee9, RegistryNotFound = 0x00002eeb, RegistryMalformedString = 0x00002eec, - InterfaceAlreadyConnected = 0x000032c8, - InterfaceNotReady = 0x000032c9, - InterfaceOptionKeyTooLarge = 0x000032ca, - InterfaceOptionValueTooLarge = 0x000032cb, - InterfaceOptionKeyInvalidUtf8String = 0x000032cc, - InterfaceOptionValueInvalidUtf8String = 0x000032cd, - HttpCouldntResolve = 0x000036b0, HttpCouldntConnect = 0x000036b1, HttpTimeout = 0x000036b2, @@ -373,21 +364,55 @@ namespace Framework.Constants HttpTooManyRedirects = 0x000036b7, HttpCouldntOpenFile = 0x000036b8, HttpCouldntCreateFile = 0x000036b9, - HttpCouldntReadFile = 0x000036ba, HttpCouldntRenameFile = 0x000036bb, HttpCouldntCreateDirectory = 0x000036bc, HttpCurlIsNotReady = 0x000036bd, - HttpCancelled = 0x000036be, + HttpCanceled = 0x000036be, + HttpSendFailed = 0x000036bf, + HttpRecvFailed = 0x000036c0, + HttpMalformedReply = 0x000036c1, + HttpAccessDenied = 0x000036c2, + HttpMalformedPost = 0x000036c3, + HttpInvalidCert = 0x000036c4, + HttpInvalidCaCert = 0x000036c5, + HttpSslConnectFailed = 0x000036c6, + HttpProtocolFailed = 0x000036c7, HttpFileNotFound = 0x00003844, + HttpOauth2DiscoveryFailed = 0x000038a5, + HttpOauth2TokenRefreshFailed = 0x000038a6, + HttpOauth2TokenStorageFailed = 0x000038a7, + HttpOauth2TokenExchangeFailed = 0x000038a8, + HttpOauth2InvalidContext = 0x000038a9, + + AsterionGeneralRuntime = 0x00003a98, + AsterionThrottled = 0x00003a99, + AsterionShardNotFound = 0x00003a9a, + AsterionInvalidParameter = 0x00003a9b, + AsterionRemoteRegionUnavailable = 0x00003a9d, + AsterionDeductRecordDuplicated = 0x00003a9f, + AsterionDeductRecordMinimumGametime = 0x00003aa0, + AsterionDeductRecordInvalidStopTime = 0x00003aa1, + AsterionTimedOut = 0x00003aa2, + AsterionTooManyOutstandingRequests = 0x00003aa3, + AsterionDeductRecordAnotherInProgress = 0x00003aa4, + + AsterionUnavailable = 0x00003e7f, + + EventViewIsFull = 0x00003e80, + + VoiceAccountNotFound = 0x00004268, + VoiceTokenAlreadyUsed = 0x00004269, + VoiceVersionNotSupported = 0x0000426a, + VoiceInvalidVersion = 0x0000426b, + VoiceSecretKeyStorageFailure = 0x0000426c, + AccountMissingConfig = 0x00004650, AccountDataNotFound = 0x00004651, AccountAlreadySubscribed = 0x00004652, AccountNotSubscribed = 0x00004653, AccountFailedToParseTimezoneData = 0x00004654, - AccountLoadFailed = 0x00004655, - AccountLoadCancelled = 0x00004656, AccountDatabaseInvalidateFailed = 0x00004657, AccountCacheInvalidateFailed = 0x00004658, AccountSubscriptionPending = 0x00004659, @@ -396,40 +421,20 @@ namespace Framework.Constants AccountUnderage = 0x0000465c, AccountIdentityCheckPending = 0x0000465d, AccountIdentityUnverified = 0x0000465e, - - DatabaseBindingCountMismatch = 0x00004a38, - DatabaseBindingParseFail = 0x00004a39, - DatabaseResultsetColumnsMismatch = 0x00004a3a, - DatabaseDeadlock = 0x00004a3b, - DatabaseDuplicateKey = 0x00004a3c, - DatabaseCannotConnect = 0x00004a3d, - DatabaseStatementFailed = 0x00004a3e, - DatabaseTransactionNotStarted = 0x00004a3f, - DatabaseTransactionNotEnded = 0x00004a40, - DatabaseTransactionLeak = 0x00004a41, - DatabaseTransactionStateBad = 0x00004a42, - DatabaseServerGone = 0x00004a43, - DatabaseQueryTimeout = 0x00004a44, - DatabaseBindingNotNullable = 0x00004a9c, - DatabaseBindingInvalidInteger = 0x00004a9d, - DatabaseBindingInvalidFloat = 0x00004a9e, - DatabaseBindingInvalidTemporal = 0x00004a9f, - DatabaseBindingInvalidProtobuf = 0x00004aa0, - - PartyInvalidPartyId = 0x00004e20, - PartyAlreadyInParty = 0x00004e21, - PartyNotInParty = 0x00004e22, - PartyInvitationUndeliverable = 0x00004e23, - PartyInvitationAlreadyExists = 0x00004e24, - PartyTooManyPartyInvitations = 0x00004e25, - PartyTooManyReceivedInvitations = 0x00004e26, - PartyNoSuchType = 0x00004e27, + AccountIgr = 0x0000465f, + GameAccountCreateNeedNationalId = 0x00004660, + GameAccountCreateBlocked = 0x00004661, + GameAccountDetached = 0x00004662, + GameAccountCreateTooManyGameAccount = 0x00004663, + SubscriberNoNeedToUpdate = 0x00004664, + AccountMobileNumberRequired = 0x00004665, + AccountMobileNumberAlreadyUsed = 0x00004666, + AccountDataNotExistsInCache = 0x00004667, + AccountInvalidIdentityData = 0x00004668, GamesNoSuchFactory = 0x000055f0, GamesNoSuchGame = 0x000055f1, GamesNoSuchRequest = 0x000055f2, - GamesNoSuchPartyMember = 0x000055f3, - ResourcesOffline = 0x000059d8, GameServerCreateGameRefused = 0x00005dc0, @@ -453,11 +458,8 @@ namespace Framework.Constants GameMasterRegisterFailed = 0x000061ab, GameMasterNoGameServer = 0x000061ac, GameMasterNoUtilityServer = 0x000061ad, - GameMasterNoGameVersion = 0x000061ae, GameMasterGameJoinFailed = 0x000061af, - GameMasterAlreadyRegistered = 0x000061b0, GameMasterNoFactory = 0x000061b1, - GameMasterMultipleGameVersions = 0x000061b2, GameMasterInvalidPlayer = 0x000061b3, GameMasterInvalidGameRequest = 0x000061b4, GameMasterInsufficientPrivileges = 0x000061b5, @@ -471,43 +473,50 @@ namespace Framework.Constants GameMasterInvalidTeamId = 0x000061bd, GameMasterCreationInProgress = 0x000061be, - NotificationInvalidClientId = 0x00006590, - NotificationDuplicateName = 0x00006591, - NotificationNameNotFound = 0x00006592, - NotificationInvalidServer = 0x00006593, NotificationQuotaExceeded = 0x00006594, NotificationInvalidNotificationType = 0x00006595, NotificationUndeliverable = 0x00006596, NotificationUndeliverableTemporary = 0x00006597, - AchievementsNothingToUpdate = 0x00006d60, - AchievementsInvalidParams = 0x00006d61, - AchievementsNotRegistered = 0x00006d62, - AchievementsNotReady = 0x00006d63, - AchievementsFailedToParseStaticData = 0x00006d64, - AchievementsUnknownId = 0x00006d65, - AchievementsMissingSnapshot = 0x00006d66, - AchievementsAlreadyRegistered = 0x00006d67, - AchievementsTooManyRegistrations = 0x00006d68, - AchievementsAlreadyInProgress = 0x00006d69, - AchievementsTemporaryOutage = 0x00006d6a, - AchievementsInvalidProgramid = 0x00006d6b, - AchievementsMissingRecord = 0x00006d6c, - AchievementsRegistrationPending = 0x00006d6d, - AchievementsEntityIdNotFound = 0x00006d6e, - AchievementsAchievementIdNotFound = 0x00006d6f, - AchievementsCriteriaIdNotFound = 0x00006d70, - AchievementsStaticDataMismatch = 0x00006d71, - AchievementsWrongThread = 0x00006d72, - AchievementsCallbackIsNull = 0x00006d73, - AchievementsAutoRegisterPending = 0x00006d74, - AchievementsNotInitialized = 0x00006d75, - AchievementsAchievementIdAlreadyExists = 0x00006d76, - AchievementsFailedToDownloadStaticData = 0x00006d77, - AchievementsStaticDataNotFound = 0x00006d78, + LeaderboardRuleNotFound = 0x00006d61, + LeaderboardNotFound = 0x00006d62, + LeaderboardInvalidEntityId = 0x00006d64, + LeaderboardInvalidGameAccount = 0x00006d65, + LeaderboardInvalidTimestamp = 0x00006d66, + LeaderboardInvalidTags = 0x00006d67, + LeaderboardInvalidPayload = 0x00006d69, + LeaderboardInvalidTitleId = 0x00006d6a, + LeaderboardInvalidRuleName = 0x00006d6b, + LeaderboardInvalidRequest = 0x00006d6c, + LeaderboardInvalidScores = 0x00006d6d, + LeaderboardInvalidFieldFormat = 0x00006d6e, + LeaderboardAccountNotFound = 0x00006d6f, + LeaderboardRanksNotFound = 0x00006d70, + LeaderboardInvalidBatchSubmitRanksRequest = 0x00006d71, + + MatchmakingMatchmakerNotFound = 0x00007530, + MatchmakingMatchmakerDecommissioned = 0x00007531, + MatchmakingGameserverNotFound = 0x00007532, + Matchmaking30003 = 0x00007533, + MatchmakingMatchmakerAlreadyRegistered = 0x00007534, + MatchmakingGameserverAlreadyRegistered = 0x00007535, + MatchmakingRequestIdNotFound = 0x00007536, + MatchmakingInsufficientPartyPrivileges = 0x00007537, + MatchmakingEventQueueFull = 0x00007538, + MatchmakingCancelNotAllowed = 0x00007539, + MatchmakingPlayerNotConnected = 0x0000753a, + MatchmakingEventCanceled = 0x0000753b, + MatchmakingGameserverFull = 0x0000753c, + MatchmakingInvalidResponse = 0x0000753d, + MatchmakingMatchmakerInvalidConnection = 0x0000753e, + + MatchmakingServerAlreadyInGame = 0x00007918, + MatchmakingServerInvalidGame = 0x00007919, + MatchmakingServerInvalidPlayer = 0x0000791a, + MatchmakingServerGameFull = 0x0000791b, + MatchmakingServerUnknownRequestId = 0x0000791c, GameUtilityServerVariableRequestRefused = 0x000084d1, - GameUtilityServerWrongNumberOfVariablesReturned = 0x000084d2, GameUtilityServerClientRequestRefused = 0x000084d3, GameUtilityServerPresenceChannelCreatedRefused = 0x000084d4, GameUtilityServerVariableRequestRefusedTransient = 0x00008502, @@ -518,31 +527,34 @@ namespace Framework.Constants GameUtilityServerClientRequestRefusedBusy = 0x00008535, GameUtilityServerPresenceChannelCreatedRefusedBusy = 0x00008536, GameUtilityServerServerRequestRefusedBusy = 0x00008537, + + GameUtilityServerRequestRefused = 0x00008567, + GameUtilityServerRequestRefusedBusy = 0x00008568, + GameUtilityServerRequestRefusedTransient = 0x00008569, GameUtilityServerNoServer = 0x00008598, + GameUtilityServerVersionMismatch = 0x0000859a, + GameUtilityServerTimedOut = 0x0000859b, - IdentityInsufficientData = 0x0000a028, - IdentityTooManyResults = 0x0000a029, - IdentityBadId = 0x0000a02a, - IdentityNoAccountBlob = 0x0000a02b, + SessionAdminKick = 0x00009c44, + SessionAbandoned = 0x00009c48, + SessionCaisPlaytimeExceeded = 0x00009c4b, + SessionCaisCurfew = 0x00009c4c, + SessionInvalidNid = 0x00009c4e, + SessionQueueDuplicated = 0x00009c4f, + SessionQueueAdminKick = 0x00009c51, + SessionKeyExpired = 0x00009c52, + SessionTokenExpired = 0x00009c53, - RiskChallengeAction = 0x0000a410, - RiskDelayAction = 0x0000a411, RiskThrottleAction = 0x0000a412, RiskAccountLocked = 0x0000a413, - RiskCsDenied = 0x0000a414, RiskDisconnectAccount = 0x0000a415, RiskCheckSkipped = 0x0000a416, ReportUnavailable = 0x0000afc8, - ReportTooLarge = 0x0000afc9, + ReportUnknownProgram = 0x0000afc9, ReportUnknownType = 0x0000afca, - ReportAttributeInvalid = 0x0000afcb, ReportAttributeQuotaExceeded = 0x0000afcc, ReportUnconfirmed = 0x0000afcd, - ReportNotConnected = 0x0000afce, - ReportRejected = 0x0000afcf, - ReportTooManyRequests = 0x0000afd0, - AccountAlreadyRegisterd = 0x0000bb80, AccountNotRegistered = 0x0000bb81, AccountRegistrationPending = 0x0000bb82, diff --git a/Source/Framework/Constants/ConditionConst.cs b/Source/Framework/Constants/ConditionConst.cs index 98d2e3727..87c7003e9 100644 --- a/Source/Framework/Constants/ConditionConst.cs +++ b/Source/Framework/Constants/ConditionConst.cs @@ -103,6 +103,7 @@ namespace Framework.Constants TrainerSpell = 31, ObjectIdVisibility = 32, SpawnGroup = 33, + PlayerCondition = 34, MaxDbAllowed, ReferenceCondition = MaxDbAllowed, diff --git a/Source/Framework/Constants/Network/Opcodes.cs b/Source/Framework/Constants/Network/Opcodes.cs index 8ed18fe65..5d4f7c4e2 100644 --- a/Source/Framework/Constants/Network/Opcodes.cs +++ b/Source/Framework/Constants/Network/Opcodes.cs @@ -51,8 +51,8 @@ namespace Framework.Constants AuctionSellCommodity = 0x34e0, AuctionSellItem = 0x34d3, AuctionSetFavoriteItem = 0x3735, - AuthContinuedSession = 0x3766, - AuthSession = 0x3765, + AuthContinuedSession = 0x377a, + AuthSession = 0x3779, AutobankItem = 0x3997, AutobankReagent = 0x3999, AutostoreBankItem = 0x3996, @@ -155,43 +155,45 @@ namespace Framework.Constants CharCustomize = 0x368c, CharDelete = 0x369c, CharRaceOrFactionChange = 0x3692, - ChatAddonMessage = 0x37ee, - ChatAddonMessageTargeted = 0x37ef, - ChatCanLocalWhisperTargetRequest = 0x37f6, - ChatChannelAnnouncements = 0x37e3, - ChatChannelBan = 0x37e1, - ChatChannelDeclineInvite = 0x37e6, - ChatChannelDisplayList = 0x37d6, - ChatChannelInvite = 0x37df, - ChatChannelKick = 0x37e0, - ChatChannelList = 0x37d5, - ChatChannelModerator = 0x37db, - ChatChannelOwner = 0x37d9, - ChatChannelPassword = 0x37d7, - ChatChannelSetOwner = 0x37d8, - ChatChannelSilenceAll = 0x37e4, - ChatChannelUnban = 0x37e2, - ChatChannelUnmoderator = 0x37dc, - ChatChannelUnsilenceAll = 0x37e5, - ChatJoinChannel = 0x37c8, - ChatLeaveChannel = 0x37c9, - ChatMessageAfk = 0x37d3, - ChatMessageChannel = 0x37cf, - ChatMessageDnd = 0x37d4, - ChatMessageEmote = 0x37e8, - ChatMessageGuild = 0x37d1, - ChatMessageInstanceChat = 0x37ec, - ChatMessageOfficer = 0x37d2, - ChatMessageParty = 0x37ea, - ChatMessageRaid = 0x37eb, - ChatMessageRaidWarning = 0x37ed, - ChatMessageSay = 0x37e7, - ChatMessageWhisper = 0x37d0, - ChatMessageYell = 0x37e9, - ChatRegisterAddonPrefixes = 0x37cd, - ChatReportFiltered = 0x37cc, - ChatReportIgnored = 0x37cb, - ChatUnregisterAllAddonPrefixes = 0x37ce, + ChatAddonMessage = 0x3802, + ChatAddonMessageTargeted = 0x3803, + ChatCanLocalWhisperTargetRequest = 0x380a, + ChatChannelAnnouncements = 0x37f7, + ChatChannelBan = 0x37f5, + ChatChannelDeclineInvite = 0x37fa, + ChatChannelDisplayList = 0x37ea, + ChatChannelInvite = 0x37f3, + ChatChannelKick = 0x37f4, + ChatChannelList = 0x37e9, + ChatChannelModerator = 0x37ef, + ChatChannelOwner = 0x37ed, + ChatChannelPassword = 0x37eb, + ChatChannelSetOwner = 0x37ec, + ChatChannelSilenceAll = 0x37f8, + ChatChannelUnban = 0x37f6, + ChatChannelUnmoderator = 0x37f0, + ChatChannelUnsilenceAll = 0x37f9, + ChatJoinChannel = 0x37dc, + ChatLeaveChannel = 0x37dd, + ChatLobbyMatchmakerMessageInstanceChat = 0x3809, + ChatLobbyMatchmakerMessageParty = 0x3808, + ChatMessageAfk = 0x37e7, + ChatMessageChannel = 0x37e3, + ChatMessageDnd = 0x37e8, + ChatMessageEmote = 0x37fc, + ChatMessageGuild = 0x37e5, + ChatMessageInstanceChat = 0x3800, + ChatMessageOfficer = 0x37e6, + ChatMessageParty = 0x37fe, + ChatMessageRaid = 0x37ff, + ChatMessageRaidWarning = 0x3801, + ChatMessageSay = 0x37fb, + ChatMessageWhisper = 0x37e4, + ChatMessageYell = 0x37fd, + ChatRegisterAddonPrefixes = 0x37e1, + ChatReportFiltered = 0x37e0, + ChatReportIgnored = 0x37df, + ChatUnregisterAllAddonPrefixes = 0x37e2, CheckCharacterNameAvailability = 0x3645, CheckIsAdventureMapPoiValid = 0x3258, ChoiceResponse = 0x32c1, @@ -292,10 +294,10 @@ namespace Framework.Constants DuelResponse = 0x34f1, EjectPassenger = 0x324d, Emote = 0x3555, - EnableNagle = 0x376b, + EnableNagle = 0x377f, EnableTaxiNode = 0x34b0, EngineSurvey = 0x36e1, - EnterEncryptedModeAck = 0x3767, + EnterEncryptedModeAck = 0x377b, EnumCharacters = 0x35e8, EnumCharactersDeletedByClient = 0x36db, FarSight = 0x34f7, @@ -407,7 +409,7 @@ namespace Framework.Constants JoinRatedBattleground = 0x3178, KeepAlive = 0x367f, KeyboundOverride = 0x322f, - LatencyReport = 0x3771, + LatencyReport = 0x3785, LearnPvpTalents = 0x356d, LearnTalents = 0x356b, LeaveGroup = 0x3649, @@ -429,11 +431,20 @@ namespace Framework.Constants LiveRegionKeyBindingsCopy = 0x36b8, LoadingScreenNotify = 0x35f8, LoadSelectedTrophy = 0x3333, + LobbyMatchmakerAcceptPartyInvite = 0x373e, + LobbyMatchmakerCreateCharacter = 0x374c, + LobbyMatchmakerLeaveParty = 0x3741, + LobbyMatchmakerPartyInvite = 0x373d, + LobbyMatchmakerPartyUninvite = 0x3740, + LobbyMatchmakerRejectPartyInvite = 0x373f, + LobbyMatchmakerSetPartyPlaylistEntry = 0x3742, + LobbyMatchmakerSetPlayerReady = 0x3743, LogoutCancel = 0x34e7, LogoutInstant = 0x34e8, + LogoutLobbyMatchmaker = 0x3594, LogoutRequest = 0x34e5, - LogDisconnect = 0x3769, - LogStreamingError = 0x376d, + LogDisconnect = 0x377d, + LogStreamingError = 0x3781, LootItem = 0x3217, LootMoney = 0x3216, LootRelease = 0x321b, @@ -591,7 +602,7 @@ namespace Framework.Constants PetSetAction = 0x3490, PetSpellAutocast = 0x3495, PetStopAttack = 0x3492, - Ping = 0x3768, + Ping = 0x377c, PlayerLogin = 0x35ea, PushQuestToParty = 0x34a5, PvpLogData = 0x317b, @@ -609,9 +620,9 @@ namespace Framework.Constants QueryPageText = 0x328c, QueryPetition = 0x3290, QueryPetName = 0x328d, - QueryPlayerNames = 0x3772, - QueryPlayerNamesForCommunity = 0x3770, - QueryPlayerNameByCommunityId = 0x376f, + QueryPlayerNames = 0x3786, + QueryPlayerNamesForCommunity = 0x3784, + QueryPlayerNameByCommunityId = 0x3783, QueryQuestCompletionNpcs = 0x3174, QueryQuestInfo = 0x328b, QueryQuestItemUsability = 0x3175, @@ -637,7 +648,7 @@ namespace Framework.Constants QuestSessionBeginResponse = 0x33d0, QuestSessionRequestStart = 0x33cf, QuestSessionRequestStop = 0x372c, - QueuedMessagesEnd = 0x376c, + QueuedMessagesEnd = 0x3780, QuickJoinAutoAcceptRequests = 0x3704, QuickJoinRequestInvite = 0x3703, QuickJoinRequestInviteWithConfirmation = 0x3731, @@ -774,6 +785,7 @@ namespace Framework.Constants SortBankBags = 0x335c, SortReagentBankBags = 0x335d, SpawnTrackingUpdate = 0x32ae, + SpectateChange = 0x342a, SpellClick = 0x349b, SpellEmpowerRelease = 0x3280, SpellEmpowerRestart = 0x3281, @@ -792,8 +804,8 @@ namespace Framework.Constants SummonResponse = 0x366a, SupportTicketSubmitComplaint = 0x3646, SurrenderArena = 0x3173, - SuspendCommsAck = 0x3764, - SuspendTokenResponse = 0x376a, + SuspendCommsAck = 0x3778, + SuspendTokenResponse = 0x377e, SwapGuildBankItemWithGuildBankItem = 0x34c1, SwapInvItem = 0x399d, SwapItem = 0x399c, @@ -854,6 +866,7 @@ namespace Framework.Constants Warden3Data = 0x35ec, Who = 0x3681, WhoIs = 0x3680, + WorldLootObjectClick = 0x342d, WorldPortResponse = 0x35f9, WrapItem = 0x3994, @@ -864,45 +877,45 @@ namespace Framework.Constants public enum ServerOpcodes : uint { AbortNewWorld = 0x2597, - AccountCosmeticAdded = 0x2876, - AccountCriteriaUpdate = 0x285c, - AccountDataTimes = 0x2705, - AccountExportResponse = 0x28b2, + AccountCosmeticAdded = 0x2878, + AccountCriteriaUpdate = 0x285e, + AccountDataTimes = 0x2707, + AccountExportResponse = 0x28b5, AccountMountRemoved = 0x25ae, AccountMountUpdate = 0x25ad, - AccountNotificationsResponse = 0x2875, + AccountNotificationsResponse = 0x2877, AccountToyUpdate = 0x25af, AccountTransmogSetFavoritesUpdate = 0x25b3, AccountTransmogUpdate = 0x25b2, - AchievementDeleted = 0x26e3, + AchievementDeleted = 0x26e5, AchievementEarned = 0x2640, ActivateEssenceFailed = 0x3015, ActivateSoulbindFailed = 0x3017, - ActivateTaxiReply = 0x267a, + ActivateTaxiReply = 0x267c, ActiveGlyphs = 0x2c56, - ActiveScheduledWorldStateInfo = 0x2741, + ActiveScheduledWorldStateInfo = 0x2743, AddonListRequest = 0x263f, AddBattlenetFriendResponse = 0x263a, AddItemPassive = 0x25a9, - AddLossOfControl = 0x266e, - AddRunePower = 0x26b4, + AddLossOfControl = 0x2670, + AddRunePower = 0x26b6, AdjustSplineDuration = 0x25cf, - AdvancedCombatLog = 0x2872, - AdventureJournalDataResponse = 0x286c, + AdvancedCombatLog = 0x2874, + AdventureJournalDataResponse = 0x286e, AeLootTargets = 0x2615, AeLootTargetAck = 0x2616, - AiReaction = 0x26b1, - AlliedRaceDetails = 0x27f0, + AiReaction = 0x26b3, + AlliedRaceDetails = 0x27f2, AllAccountCriteria = 0x2571, AllAchievementData = 0x2570, AllGuildAchievements = 0x29b8, - ApplyMountEquipmentResult = 0x2849, + ApplyMountEquipmentResult = 0x284b, ArchaeologySurveryCast = 0x2586, AreaPoiUpdateResponse = 0x3010, - AreaSpiritHealerTime = 0x273a, + AreaSpiritHealerTime = 0x273c, AreaTriggerDenied = 0x2903, AreaTriggerForceSetPositionAndFacing = 0x2900, - AreaTriggerNoCorpse = 0x2711, + AreaTriggerNoCorpse = 0x2713, AreaTriggerPlaySpellVisual = 0x28fe, AreaTriggerRePath = 0x28fd, AreaTriggerReShape = 0x2902, @@ -911,42 +924,42 @@ namespace Framework.Constants ArenaClearOpponents = 0x2646, ArenaCrowdControlSpellResult = 0x262f, ArenaPrepOpponentSpecializations = 0x2645, - ArtifactEndgamePowersRefunded = 0x279c, - ArtifactForgeError = 0x279a, - ArtifactRespecPrompt = 0x279b, - ArtifactXpGain = 0x27e3, + ArtifactEndgamePowersRefunded = 0x279e, + ArtifactForgeError = 0x279c, + ArtifactRespecPrompt = 0x279d, + ArtifactXpGain = 0x27e5, AttackerStateUpdate = 0x294e, AttackStart = 0x2939, AttackStop = 0x293a, AttackSwingError = 0x2948, AttackSwingLandedLog = 0x2949, - AuctionableTokenAuctionSold = 0x27cc, - AuctionableTokenSellAtMarketPriceResponse = 0x27cb, - AuctionableTokenSellConfirmRequired = 0x27ca, - AuctionClosedNotification = 0x26ee, - AuctionCommandResult = 0x26eb, - AuctionDisableNewPostings = 0x2892, - AuctionFavoriteList = 0x2863, - AuctionGetCommodityQuoteResult = 0x285a, - AuctionHelloResponse = 0x26e9, - AuctionListBiddedItemsResult = 0x2859, - AuctionListBucketsResult = 0x2856, - AuctionListItemsResult = 0x2857, - AuctionListOwnedItemsResult = 0x2858, - AuctionOutbidNotification = 0x26ed, - AuctionOwnerBidNotification = 0x26ef, - AuctionReplicateResponse = 0x26ea, - AuctionWonNotification = 0x26ec, + AuctionableTokenAuctionSold = 0x27ce, + AuctionableTokenSellAtMarketPriceResponse = 0x27cd, + AuctionableTokenSellConfirmRequired = 0x27cc, + AuctionClosedNotification = 0x26f0, + AuctionCommandResult = 0x26ed, + AuctionDisableNewPostings = 0x2895, + AuctionFavoriteList = 0x2865, + AuctionGetCommodityQuoteResult = 0x285c, + AuctionHelloResponse = 0x26eb, + AuctionListBiddedItemsResult = 0x285b, + AuctionListBucketsResult = 0x2858, + AuctionListItemsResult = 0x2859, + AuctionListOwnedItemsResult = 0x285a, + AuctionOutbidNotification = 0x26ef, + AuctionOwnerBidNotification = 0x26f1, + AuctionReplicateResponse = 0x26ec, + AuctionWonNotification = 0x26ee, AuraPointsDepleted = 0x2c22, AuraUpdate = 0x2c21, AuthChallenge = 0x3048, AuthFailed = 0x256c, AuthResponse = 0x256d, AvailableHotfixes = 0x290f, - BackpackDefaultSizeChanged = 0x2897, + BackpackDefaultSizeChanged = 0x289a, BagCleanupFinished = 0x2da7, - BarberShopResult = 0x26b9, - BatchPresenceSubscription = 0x283a, + BarberShopResult = 0x26bb, + BatchPresenceSubscription = 0x283c, BattlefieldList = 0x2927, BattlefieldPortDenied = 0x292d, BattlefieldStatusActive = 0x2923, @@ -962,31 +975,31 @@ namespace Framework.Constants BattlegroundPlayerLeft = 0x292c, BattlegroundPlayerPositions = 0x2928, BattlegroundPoints = 0x294a, - BattlenetChallengeAbort = 0x2784, - BattlenetChallengeStart = 0x2783, - BattlenetNotification = 0x27fc, - BattlenetResponse = 0x27fb, - BattleNetConnectionStatus = 0x27fd, - BattlePayAckFailed = 0x277e, - BattlePayBattlePetDelivered = 0x2773, - BattlePayCollectionItemDelivered = 0x2774, - BattlePayConfirmPurchase = 0x277d, - BattlePayDeliveryEnded = 0x2771, - BattlePayDeliveryStarted = 0x2770, - BattlePayDistributionAssignVasResponse = 0x287b, - BattlePayDistributionUnrevoked = 0x276e, - BattlePayDistributionUpdate = 0x276f, - BattlePayGetDistributionListResponse = 0x276d, - BattlePayGetProductListResponse = 0x276b, - BattlePayGetPurchaseListResponse = 0x276c, - BattlePayMountDelivered = 0x2772, - BattlePayPurchaseUpdate = 0x277c, - BattlePayStartCheckout = 0x2818, - BattlePayStartDistributionAssignToTargetResponse = 0x277a, - BattlePayStartPurchaseResponse = 0x2779, - BattlePayValidatePurchaseResponse = 0x280c, + BattlenetChallengeAbort = 0x2786, + BattlenetChallengeStart = 0x2785, + BattlenetNotification = 0x27fe, + BattlenetResponse = 0x27fd, + BattleNetConnectionStatus = 0x27ff, + BattlePayAckFailed = 0x2780, + BattlePayBattlePetDelivered = 0x2775, + BattlePayCollectionItemDelivered = 0x2776, + BattlePayConfirmPurchase = 0x277f, + BattlePayDeliveryEnded = 0x2773, + BattlePayDeliveryStarted = 0x2772, + BattlePayDistributionAssignVasResponse = 0x287d, + BattlePayDistributionUnrevoked = 0x2770, + BattlePayDistributionUpdate = 0x2771, + BattlePayGetDistributionListResponse = 0x276f, + BattlePayGetProductListResponse = 0x276d, + BattlePayGetPurchaseListResponse = 0x276e, + BattlePayMountDelivered = 0x2774, + BattlePayPurchaseUpdate = 0x277e, + BattlePayStartCheckout = 0x281a, + BattlePayStartDistributionAssignToTargetResponse = 0x277c, + BattlePayStartPurchaseResponse = 0x277b, + BattlePayValidatePurchaseResponse = 0x280e, BattlePetsHealed = 0x25f1, - BattlePetCageDateError = 0x2675, + BattlePetCageDateError = 0x2677, BattlePetDeleted = 0x25ee, BattlePetError = 0x2635, BattlePetJournal = 0x25ed, @@ -1005,34 +1018,34 @@ namespace Framework.Constants BossKill = 0x294d, BreakTarget = 0x2938, BroadcastAchievement = 0x2bbc, - BroadcastSummonCast = 0x283c, - BroadcastSummonResponse = 0x283d, - BuyFailed = 0x26c2, - BuySucceeded = 0x26c1, + BroadcastSummonCast = 0x283e, + BroadcastSummonResponse = 0x283f, + BuyFailed = 0x26c4, + BuySucceeded = 0x26c3, CacheInfo = 0x291d, CacheVersion = 0x291c, - CalendarClearPendingAction = 0x269a, - CalendarCommandResult = 0x269b, - CalendarCommunityInvite = 0x268a, - CalendarEventRemovedAlert = 0x2692, - CalendarEventUpdatedAlert = 0x2693, - CalendarInviteAdded = 0x268b, - CalendarInviteAlert = 0x268f, - CalendarInviteNotes = 0x2694, - CalendarInviteNotesAlert = 0x2695, - CalendarInviteRemoved = 0x268c, - CalendarInviteRemovedAlert = 0x2691, - CalendarInviteStatus = 0x268d, - CalendarInviteStatusAlert = 0x2690, - CalendarModeratorStatus = 0x268e, - CalendarRaidLockoutAdded = 0x2696, - CalendarRaidLockoutRemoved = 0x2697, - CalendarRaidLockoutUpdated = 0x2698, - CalendarSendCalendar = 0x2688, - CalendarSendEvent = 0x2689, - CalendarSendNumPending = 0x2699, - CameraEffect = 0x2720, - CancelAutoRepeat = 0x26d9, + CalendarClearPendingAction = 0x269c, + CalendarCommandResult = 0x269d, + CalendarCommunityInvite = 0x268c, + CalendarEventRemovedAlert = 0x2694, + CalendarEventUpdatedAlert = 0x2695, + CalendarInviteAdded = 0x268d, + CalendarInviteAlert = 0x2691, + CalendarInviteNotes = 0x2696, + CalendarInviteNotesAlert = 0x2697, + CalendarInviteRemoved = 0x268e, + CalendarInviteRemovedAlert = 0x2693, + CalendarInviteStatus = 0x268f, + CalendarInviteStatusAlert = 0x2692, + CalendarModeratorStatus = 0x2690, + CalendarRaidLockoutAdded = 0x2698, + CalendarRaidLockoutRemoved = 0x2699, + CalendarRaidLockoutUpdated = 0x269a, + CalendarSendCalendar = 0x268a, + CalendarSendEvent = 0x268b, + CalendarSendNumPending = 0x269b, + CameraEffect = 0x2722, + CancelAutoRepeat = 0x26db, CancelCombat = 0x2947, CancelOrphanSpellVisual = 0x2c48, CancelPingPin = 0x25a2, @@ -1041,7 +1054,7 @@ namespace Framework.Constants CancelSpellVisual = 0x2c46, CancelSpellVisualKit = 0x2c4a, CanDuelResult = 0x2943, - CanRedeemTokenForBalanceResponse = 0x280b, + CanRedeemTokenForBalanceResponse = 0x280d, CapturePointRemoved = 0x292a, CastFailed = 0x2c59, ChainMissileBounce = 0x25c7, @@ -1051,22 +1064,22 @@ namespace Framework.Constants ChallengeModeStart = 0x2605, ChallengeModeUpdateDeathCount = 0x2606, ChangePlayerDifficultyResult = 0x3004, - ChangeRealmTicketResponse = 0x27fe, + ChangeRealmTicketResponse = 0x2800, ChannelList = 0x2bc4, ChannelNotify = 0x2bc1, ChannelNotifyJoined = 0x2bc2, ChannelNotifyLeft = 0x2bc3, - CharacterCheckUpgradeResult = 0x27b7, - CharacterLoginFailed = 0x2700, - CharacterObjectTestResponse = 0x2782, - CharacterRenameResult = 0x275d, - CharacterUpgradeAborted = 0x27b6, - CharacterUpgradeComplete = 0x27b5, - CharacterUpgradeManualUnrevokeResult = 0x27b8, - CharacterUpgradeStarted = 0x27b4, - CharCustomizeFailure = 0x26dd, - CharCustomizeSuccess = 0x26de, - CharFactionChangeResult = 0x27a1, + CharacterCheckUpgradeResult = 0x27b9, + CharacterLoginFailed = 0x2702, + CharacterObjectTestResponse = 0x2784, + CharacterRenameResult = 0x275f, + CharacterUpgradeAborted = 0x27b8, + CharacterUpgradeComplete = 0x27b7, + CharacterUpgradeManualUnrevokeResult = 0x27ba, + CharacterUpgradeStarted = 0x27b6, + CharCustomizeFailure = 0x26df, + CharCustomizeSuccess = 0x26e0, + CharFactionChangeResult = 0x27a3, Chat = 0x2bad, ChatAutoResponded = 0x2bb8, ChatCanLocalWhisperTargetResponse = 0x2bcb, @@ -1084,84 +1097,84 @@ namespace Framework.Constants CheckAbandonNpe = 0x3018, CheckCharacterNameAvailabilityResult = 0x2584, CheckWargameEntry = 0x258f, - ChromieTimeSelectExpansionSuccess = 0x2866, - ClaimRafRewardResponse = 0x284d, + ChromieTimeSelectExpansionSuccess = 0x2868, + ClaimRafRewardResponse = 0x284f, ClearAllSpellCharges = 0x2c26, ClearBossEmotes = 0x25ba, - ClearCooldown = 0x26b6, + ClearCooldown = 0x26b8, ClearCooldowns = 0x2c25, ClearResurrect = 0x257f, ClearSpellCharges = 0x2c27, ClearTarget = 0x2944, ClearTreasurePickerCache = 0x2aa1, - CloseArtifactForge = 0x2799, - ClubFinderErrorMessage = 0x2845, - ClubFinderGetClubPostingIdsResponse = 0x2848, - ClubFinderLookupClubPostingsList = 0x2846, - ClubFinderResponseCharacterApplicationList = 0x2843, - ClubFinderResponsePostRecruitmentMessage = 0x2847, - ClubFinderUpdateApplications = 0x2844, - ClubFinderWhisperApplicantResponse = 0x2889, + CloseArtifactForge = 0x279b, + ClubFinderErrorMessage = 0x2847, + ClubFinderGetClubPostingIdsResponse = 0x284a, + ClubFinderLookupClubPostingsList = 0x2848, + ClubFinderResponseCharacterApplicationList = 0x2845, + ClubFinderResponsePostRecruitmentMessage = 0x2849, + ClubFinderUpdateApplications = 0x2846, + ClubFinderWhisperApplicantResponse = 0x288b, CoinRemoved = 0x2614, CombatEventFailed = 0x293b, - CommentatorMapInfo = 0x2702, - CommentatorPlayerInfo = 0x2703, - CommentatorStateChanged = 0x2701, - CommerceTokenGetCountResponse = 0x27c7, - CommerceTokenGetLogResponse = 0x27d3, - CommerceTokenGetMarketPriceResponse = 0x27c9, - CommerceTokenUpdate = 0x27c8, - ComplaintResult = 0x26a8, - CompleteShipmentResponse = 0x2792, - ConfirmPartyInvite = 0x280a, + CommentatorMapInfo = 0x2704, + CommentatorPlayerInfo = 0x2705, + CommentatorStateChanged = 0x2703, + CommerceTokenGetCountResponse = 0x27c9, + CommerceTokenGetLogResponse = 0x27d5, + CommerceTokenGetMarketPriceResponse = 0x27cb, + CommerceTokenUpdate = 0x27ca, + ComplaintResult = 0x26aa, + CompleteShipmentResponse = 0x2794, + ConfirmPartyInvite = 0x280c, ConnectTo = 0x304d, - ConquestFormulaConstants = 0x277f, + ConquestFormulaConstants = 0x2781, ConsoleWrite = 0x2632, - ConsumableTokenBuyAtMarketPriceResponse = 0x27cf, - ConsumableTokenBuyChoiceRequired = 0x27ce, - ConsumableTokenCanVeteranBuyResponse = 0x27cd, - ConsumableTokenRedeemConfirmRequired = 0x27d1, - ConsumableTokenRedeemResponse = 0x27d2, - ContactList = 0x2780, - ContributionLastUpdateResponse = 0x2811, + ConsumableTokenBuyAtMarketPriceResponse = 0x27d1, + ConsumableTokenBuyChoiceRequired = 0x27d0, + ConsumableTokenCanVeteranBuyResponse = 0x27cf, + ConsumableTokenRedeemConfirmRequired = 0x27d3, + ConsumableTokenRedeemResponse = 0x27d4, + ContactList = 0x2782, + ContributionLastUpdateResponse = 0x2813, ControlUpdate = 0x2644, - ConvertItemsToCurrencyValue = 0x286f, - CooldownCheat = 0x2733, - CooldownEvent = 0x26b5, + ConvertItemsToCurrencyValue = 0x2871, + CooldownCheat = 0x2735, + CooldownEvent = 0x26b7, CorpseLocation = 0x264c, - CorpseReclaimDelay = 0x2744, - CorpseTransportQuery = 0x270d, + CorpseReclaimDelay = 0x2746, + CorpseTransportQuery = 0x270f, CovenantCallingsAvailabilityResponse = 0x2aa3, - CovenantPreviewOpenNpc = 0x27f3, - CovenantRenownSendCatchupState = 0x2870, - CraftingHouseHelloResponse = 0x28a5, - CraftingOrderCancelResult = 0x28a1, - CraftingOrderClaimResult = 0x289d, - CraftingOrderCraftResult = 0x289f, - CraftingOrderCreateResult = 0x289b, - CraftingOrderFulfillResult = 0x28a0, - CraftingOrderListOrdersResponse = 0x289c, - CraftingOrderRejectResult = 0x28a3, - CraftingOrderReleaseResult = 0x289e, - CraftingOrderUpdateState = 0x28a6, - CraftEnchantResult = 0x28a4, - CreateChar = 0x26fc, - CreateShipmentResponse = 0x2791, - CreatorVisualsOverride = 0x28a9, - CriteriaDeleted = 0x26e2, - CriteriaUpdate = 0x26dc, - CrossedInebriationThreshold = 0x26bd, + CovenantPreviewOpenNpc = 0x27f5, + CovenantRenownSendCatchupState = 0x2872, + CraftingHouseHelloResponse = 0x28a8, + CraftingOrderCancelResult = 0x28a4, + CraftingOrderClaimResult = 0x28a0, + CraftingOrderCraftResult = 0x28a2, + CraftingOrderCreateResult = 0x289e, + CraftingOrderFulfillResult = 0x28a3, + CraftingOrderListOrdersResponse = 0x289f, + CraftingOrderRejectResult = 0x28a6, + CraftingOrderReleaseResult = 0x28a1, + CraftingOrderUpdateState = 0x28a9, + CraftEnchantResult = 0x28a7, + CreateChar = 0x26fe, + CreateShipmentResponse = 0x2793, + CreatorVisualsOverride = 0x28ac, + CriteriaDeleted = 0x26e4, + CriteriaUpdate = 0x26de, + CrossedInebriationThreshold = 0x26bf, CustomLoadScreen = 0x25ca, DailyQuestsReset = 0x2a80, DamageCalcLog = 0x2c65, DbReply = 0x290e, - DeathReleaseLoc = 0x26cf, - DebugMenuManagerFullUpdate = 0x2652, + DeathReleaseLoc = 0x26d1, + DebugMenuManagerFullUpdate = 0x2654, DefenseMessage = 0x2bb6, - DeleteChar = 0x26fd, + DeleteChar = 0x26ff, DeleteExpiredMissionsResult = 0x2980, - DestroyArenaUnit = 0x273c, - DestructibleBuildingDamage = 0x26f4, + DestroyArenaUnit = 0x273e, + DestructibleBuildingDamage = 0x26f6, DifferentInstanceFromParty = 0x2589, DisenchantCredit = 0x25a6, DismountResult = 0x257c, @@ -1170,9 +1183,9 @@ namespace Framework.Constants DisplayPlayerChoice = 0x2ffc, DisplayPromotion = 0x2649, DisplayQuestPopup = 0x2a9e, - DisplaySoulbindUpdateMessage = 0x2874, + DisplaySoulbindUpdateMessage = 0x2876, DisplayToast = 0x2621, - DisplayWorldText = 0x27e4, + DisplayWorldText = 0x27e6, DisplayWorldTextOnTarget = 0x2c64, DontAutoPushSpellsToActionBar = 0x25df, DropNewConnection = 0x304c, @@ -1183,52 +1196,52 @@ namespace Framework.Constants DuelOutOfBounds = 0x293e, DuelRequested = 0x293c, DuelWinner = 0x2942, - DurabilityDamageDeath = 0x273f, - Emote = 0x27be, - EnableBarberShop = 0x26b8, - EnchantmentLog = 0x270e, - EncounterEnd = 0x2778, - EncounterStart = 0x2777, - EndLightningStorm = 0x26a5, - EnsureWorldLoaded = 0x2883, + DurabilityDamageDeath = 0x2741, + Emote = 0x27c0, + EnableBarberShop = 0x26ba, + EnchantmentLog = 0x2710, + EncounterEnd = 0x277a, + EncounterStart = 0x2779, + EndLightningStorm = 0x26a7, + EnsureWorldLoaded = 0x2885, EnterEncryptedMode = 0x3049, EnumCharactersResult = 0x2583, - EnumVasPurchaseStatesResponse = 0x27e9, + EnumVasPurchaseStatesResponse = 0x27eb, EnvironmentalDamageLog = 0x2c1e, - EquipmentSetId = 0x26ae, + EquipmentSetId = 0x26b0, ExpectedSpamRecords = 0x2bb1, - ExplorationExperience = 0x2759, - ExternalTransactionIdGenerated = 0x286d, - FactionBonusInfo = 0x271f, + ExplorationExperience = 0x275b, + ExternalTransactionIdGenerated = 0x286f, + FactionBonusInfo = 0x2721, FailedPlayerCondition = 0x2ffa, - FailedQuestTurnIn = 0x2807, + FailedQuestTurnIn = 0x2809, FeatureSystemStatus = 0x25be, FeatureSystemStatusGlueScreen = 0x25bf, - FeignDeathResisted = 0x273e, - FishEscaped = 0x26cc, - FishNotHooked = 0x26cb, + FeignDeathResisted = 0x2740, + FishEscaped = 0x26ce, + FishNotHooked = 0x26cd, FlightSplineSync = 0x2e2b, FlushCombatLogFile = 0x2c20, - ForcedDeathUpdate = 0x26d0, - ForceAnim = 0x274b, - ForceAnimations = 0x274c, + ForcedDeathUpdate = 0x26d2, + ForceAnim = 0x274d, + ForceAnimations = 0x274e, ForceObjectRelink = 0x2648, ForceRandomTransmogToast = 0x25b1, - FriendStatus = 0x2781, - GainMawPower = 0x27d8, + FriendStatus = 0x2783, + GainMawPower = 0x27da, GameObjectActivateAnimKit = 0x25c2, - GameObjectBase = 0x281e, - GameObjectCloseInteraction = 0x2887, + GameObjectBase = 0x2820, + GameObjectCloseInteraction = 0x2889, GameObjectCustomAnim = 0x25c3, GameObjectDespawn = 0x25c4, - GameObjectInteraction = 0x2886, + GameObjectInteraction = 0x2888, GameObjectPlaySpellVisual = 0x2c4d, GameObjectPlaySpellVisualKit = 0x2c4c, - GameObjectResetState = 0x2719, - GameObjectSetStateLocal = 0x27fa, - GameSpeedSet = 0x267e, - GameTimeSet = 0x2707, - GameTimeUpdate = 0x2706, + GameObjectResetState = 0x271b, + GameObjectSetStateLocal = 0x27fc, + GameSpeedSet = 0x2680, + GameTimeSet = 0x2709, + GameTimeUpdate = 0x2708, GarrisonActivateMissionBonusAbility = 0x2982, GarrisonAddEvent = 0x29a6, GarrisonAddFollowerResult = 0x2974, @@ -1300,36 +1313,36 @@ namespace Framework.Constants GarrisonUpgradeResult = 0x296b, GarrisonUseRecallPortalResult = 0x297d, GenerateRandomCharacterNameResult = 0x2585, - GenerateSsoTokenResponse = 0x2812, - GetAccountCharacterListResult = 0x275b, + GenerateSsoTokenResponse = 0x2814, + GetAccountCharacterListResult = 0x275d, GetGarrisonInfoResult = 0x295e, - GetLandingPageShipmentsResponse = 0x2794, - GetRealmHiddenResult = 0x28b7, - GetRemainingGameTimeResponse = 0x27d0, - GetSelectedTrophyIdResponse = 0x27bc, - GetShipmentsOfTypeResponse = 0x2793, - GetShipmentInfoResponse = 0x278f, - GetTrophyListResponse = 0x27bb, - GetVasAccountCharacterListResult = 0x27e5, - GetVasTransferTargetRealmListResult = 0x27e6, + GetLandingPageShipmentsResponse = 0x2796, + GetRealmHiddenResult = 0x28ba, + GetRemainingGameTimeResponse = 0x27d2, + GetSelectedTrophyIdResponse = 0x27be, + GetShipmentsOfTypeResponse = 0x2795, + GetShipmentInfoResponse = 0x2791, + GetTrophyListResponse = 0x27bd, + GetVasAccountCharacterListResult = 0x27e7, + GetVasTransferTargetRealmListResult = 0x27e8, GmPlayerInfo = 0x3005, GmRequestPlayerInfo = 0x2ffb, - GmTicketCaseStatus = 0x26a0, - GmTicketSystemStatus = 0x269f, - GodMode = 0x26f7, + GmTicketCaseStatus = 0x26a2, + GmTicketSystemStatus = 0x26a1, + GodMode = 0x26f9, GossipComplete = 0x2a97, GossipMessage = 0x2a98, GossipOptionNpcInteraction = 0x2aa7, - GossipPoi = 0x278c, + GossipPoi = 0x278e, GossipQuestUpdate = 0x2a99, GossipRefreshOptions = 0x2aa6, GroupActionThrottled = 0x258d, - GroupAutoKick = 0x2789, - GroupDecline = 0x2785, - GroupDestroyed = 0x2788, + GroupAutoKick = 0x278b, + GroupDecline = 0x2787, + GroupDestroyed = 0x278a, GroupNewLeader = 0x262a, - GroupRequestDecline = 0x2786, - GroupUninvite = 0x2787, + GroupRequestDecline = 0x2788, + GroupUninvite = 0x2789, GuildAchievementDeleted = 0x29c5, GuildAchievementEarned = 0x29c4, GuildAchievementMembers = 0x29c7, @@ -1383,59 +1396,59 @@ namespace Framework.Constants GuildRoster = 0x29bb, GuildRosterUpdate = 0x29bc, GuildSendRankChange = 0x29b9, - HealthUpdate = 0x26cd, - HighestThreatUpdate = 0x26d5, + HealthUpdate = 0x26cf, + HighestThreatUpdate = 0x26d7, HotfixConnect = 0x2911, HotfixMessage = 0x2910, - InitializeFactions = 0x271e, + InitializeFactions = 0x2720, InitialSetup = 0x2580, - InitWorldStates = 0x2740, + InitWorldStates = 0x2742, InspectResult = 0x262e, - InstanceEncounterChangePriority = 0x27a7, - InstanceEncounterDisengageUnit = 0x27a6, - InstanceEncounterEnd = 0x27af, - InstanceEncounterEngageUnit = 0x27a5, - InstanceEncounterGainCombatResurrectionCharge = 0x27b1, - InstanceEncounterInCombatResurrection = 0x27b0, - InstanceEncounterObjectiveComplete = 0x27aa, - InstanceEncounterObjectiveStart = 0x27a9, - InstanceEncounterObjectiveUpdate = 0x27ae, - InstanceEncounterPhaseShiftChanged = 0x27b2, - InstanceEncounterStart = 0x27ab, - InstanceEncounterTimerStart = 0x27a8, - InstanceEncounterUpdateAllowReleaseInProgress = 0x27ad, - InstanceEncounterUpdateSuppressRelease = 0x27ac, - InstanceGroupSizeChanged = 0x26f5, + InstanceEncounterChangePriority = 0x27a9, + InstanceEncounterDisengageUnit = 0x27a8, + InstanceEncounterEnd = 0x27b1, + InstanceEncounterEngageUnit = 0x27a7, + InstanceEncounterGainCombatResurrectionCharge = 0x27b3, + InstanceEncounterInCombatResurrection = 0x27b2, + InstanceEncounterObjectiveComplete = 0x27ac, + InstanceEncounterObjectiveStart = 0x27ab, + InstanceEncounterObjectiveUpdate = 0x27b0, + InstanceEncounterPhaseShiftChanged = 0x27b4, + InstanceEncounterStart = 0x27ad, + InstanceEncounterTimerStart = 0x27aa, + InstanceEncounterUpdateAllowReleaseInProgress = 0x27af, + InstanceEncounterUpdateSuppressRelease = 0x27ae, + InstanceGroupSizeChanged = 0x26f7, InstanceInfo = 0x2631, - InstanceReset = 0x2683, - InstanceResetFailed = 0x2684, - InstanceSaveCreated = 0x2776, + InstanceReset = 0x2685, + InstanceResetFailed = 0x2686, + InstanceSaveCreated = 0x2778, InterruptPowerRegen = 0x2c5b, InvalidatePageText = 0x2918, InvalidatePlayer = 0x2fff, - InvalidPromotionCode = 0x274d, + InvalidPromotionCode = 0x274f, InventoryChangeFailure = 0x2da5, - InventoryFixupComplete = 0x2809, - InventoryFullOverflow = 0x281a, - IslandAzeriteGain = 0x2756, - IslandComplete = 0x2757, + InventoryFixupComplete = 0x280b, + InventoryFullOverflow = 0x281c, + IslandAzeriteGain = 0x2758, + IslandComplete = 0x2759, IsQuestCompleteResponse = 0x2a84, - ItemChanged = 0x26e6, - ItemCooldown = 0x27bd, - ItemEnchantTimeUpdate = 0x274f, + ItemChanged = 0x26e8, + ItemCooldown = 0x27bf, + ItemEnchantTimeUpdate = 0x2751, ItemExpirePurchaseRefund = 0x259b, - ItemInteractionComplete = 0x2865, + ItemInteractionComplete = 0x2867, ItemPurchaseRefundResult = 0x2599, ItemPushResult = 0x2620, - ItemTimeUpdate = 0x274e, - KickReason = 0x2686, - LatencyReportPing = 0x2877, + ItemTimeUpdate = 0x2750, + KickReason = 0x2688, + LatencyReportPing = 0x2879, LearnedSpells = 0x2c4f, LearnPvpTalentFailed = 0x25d3, LearnTalentFailed = 0x25d2, - LegacyLootRules = 0x281f, - LevelLinkingResult = 0x284b, - LevelUpInfo = 0x26e4, + LegacyLootRules = 0x2821, + LevelLinkingResult = 0x284d, + LevelUpInfo = 0x26e6, LfgBootPlayer = 0x2a35, LfgDisabled = 0x2a33, LfgExpandSearchPrompt = 0x2a3b, @@ -1463,23 +1476,24 @@ namespace Framework.Constants LfgSlotInvalid = 0x2a30, LfgTeleportDenied = 0x2a32, LfgUpdateStatus = 0x2a24, - LiveRegionAccountRestoreResult = 0x2768, - LiveRegionCharacterCopyResult = 0x2767, - LiveRegionGetAccountCharacterListResult = 0x275c, - LiveRegionKeyBindingsCopyResult = 0x2769, + LiveRegionAccountRestoreResult = 0x276a, + LiveRegionCharacterCopyResult = 0x2769, + LiveRegionGetAccountCharacterListResult = 0x275e, + LiveRegionKeyBindingsCopyResult = 0x276b, LoadCufProfiles = 0x25bb, - LoadEquipmentSet = 0x2709, - LobbyMatchmakerPartyInfo = 0x288b, - LobbyMatchmakerPartyInviteRejected = 0x288c, - LobbyMatchmakerReceiveInvite = 0x288d, - LoginSetTimeSpeed = 0x2708, + LoadEquipmentSet = 0x270b, + LobbyMatchmakerLobbyAcquiredServer = 0x288c, + LobbyMatchmakerPartyInfo = 0x288d, + LobbyMatchmakerPartyInviteRejected = 0x288e, + LobbyMatchmakerReceiveInvite = 0x288f, + LoginSetTimeSpeed = 0x270a, LoginVerifyWorld = 0x2596, - LogoutCancelAck = 0x2682, - LogoutComplete = 0x2681, - LogoutResponse = 0x2680, - LogXpGain = 0x26e0, + LogoutCancelAck = 0x2684, + LogoutComplete = 0x2683, + LogoutResponse = 0x2682, + LogXpGain = 0x26e2, LootAllPassed = 0x261e, - LootList = 0x273b, + LootList = 0x273d, LootMoneyNotify = 0x2619, LootRelease = 0x2618, LootReleaseAll = 0x2617, @@ -1488,22 +1502,22 @@ namespace Framework.Constants LootRoll = 0x261b, LootRollsComplete = 0x261d, LootRollWon = 0x261f, - LossOfControlAuraUpdate = 0x266d, + LossOfControlAuraUpdate = 0x266f, MailCommandResult = 0x2638, - MailListResult = 0x2750, - MailQueryNextTimeResult = 0x2751, + MailListResult = 0x2752, + MailQueryNextTimeResult = 0x2753, MapObjectivesInit = 0x294c, MapObjEvents = 0x25c5, MasterLootCandidateList = 0x261c, - MeetingStoneFailed = 0x288e, + MeetingStoneFailed = 0x2890, MessageBox = 0x2576, - MinimapPing = 0x26ca, + MinimapPing = 0x26cc, MirrorImageComponentedData = 0x2c14, MirrorImageCreatureData = 0x2c13, MissileCancel = 0x25c6, - ModifyCooldown = 0x275e, + ModifyCooldown = 0x2760, MountResult = 0x257b, - MovementEnforcementAlert = 0x283b, + MovementEnforcementAlert = 0x283d, MoveAddImpulse = 0x2e32, MoveApplyInertia = 0x2e2e, MoveApplyMovementForce = 0x2e15, @@ -1611,54 +1625,54 @@ namespace Framework.Constants MoveUpdateTeleport = 0x2de1, MoveUpdateTurnRate = 0x2ddd, MoveUpdateWalkSpeed = 0x2dd8, - MultiFloorLeaveFloor = 0x27d5, - MultiFloorNewFloor = 0x27d4, + MultiFloorLeaveFloor = 0x27d7, + MultiFloorNewFloor = 0x27d6, MythicPlusAllMapStats = 0x2609, MythicPlusCurrentAffixes = 0x260b, MythicPlusNewWeekRecord = 0x260f, MythicPlusSeasonData = 0x260a, NeutralPlayerFactionSelectResult = 0x25da, - NewDataBuild = 0x28b6, - NewTaxiPath = 0x267b, + NewDataBuild = 0x28b9, + NewTaxiPath = 0x267d, NewWorld = 0x2593, NotifyDestLocSpellCast = 0x2c45, - NotifyMissileTrajectoryCollision = 0x26a7, + NotifyMissileTrajectoryCollision = 0x26a9, NotifyMoney = 0x2598, NotifyReceivedMail = 0x2639, - NpcInteractionOpenResult = 0x2885, - OfferPetitionError = 0x26b2, - OnCancelExpectedRideVehicleAura = 0x26e1, + NpcInteractionOpenResult = 0x2887, + OfferPetitionError = 0x26b4, + OnCancelExpectedRideVehicleAura = 0x26e3, OnMonsterMove = 0x2dd4, - OpenArtifactForge = 0x2798, + OpenArtifactForge = 0x279a, OpenContainer = 0x2da6, OpenLfgDungeonFinder = 0x2a31, - OpenShipmentNpcResult = 0x2790, - OverrideLight = 0x26b7, - PageText = 0x2714, - PartyCommandResult = 0x278a, + OpenShipmentNpcResult = 0x2792, + OverrideLight = 0x26b9, + PageText = 0x2716, + PartyCommandResult = 0x278c, PartyInvite = 0x25bc, - PartyKillLog = 0x2754, - PartyMemberFullState = 0x2753, - PartyMemberPartialState = 0x2752, - PartyNotifyLfgLeaderChange = 0x286b, + PartyKillLog = 0x2756, + PartyMemberFullState = 0x2755, + PartyMemberPartialState = 0x2754, + PartyNotifyLfgLeaderChange = 0x286d, PartyUpdate = 0x25f2, PastTimeEvents = 0x25c1, - PauseMirrorTimer = 0x270b, - PendingRaidLock = 0x26f3, - PerksProgramActivityComplete = 0x2881, - PerksProgramActivityUpdate = 0x287d, - PerksProgramDisabled = 0x2882, - PerksProgramResult = 0x287e, - PerksProgramVendorUpdate = 0x287c, + PauseMirrorTimer = 0x270d, + PendingRaidLock = 0x26f5, + PerksProgramActivityComplete = 0x2883, + PerksProgramActivityUpdate = 0x287f, + PerksProgramDisabled = 0x2884, + PerksProgramResult = 0x2880, + PerksProgramVendorUpdate = 0x287e, PetitionAlreadySigned = 0x259e, PetitionRenameGuildResponse = 0x29fa, - PetitionShowList = 0x26ba, - PetitionShowSignatures = 0x26bb, - PetitionSignResults = 0x2746, - PetActionFeedback = 0x2743, - PetActionSound = 0x269d, + PetitionShowList = 0x26bc, + PetitionShowSignatures = 0x26bd, + PetitionSignResults = 0x2748, + PetActionFeedback = 0x2745, + PetActionSound = 0x269f, PetBattleChatRestricted = 0x2600, - PetBattleDebugQueueDumpResponse = 0x2672, + PetBattleDebugQueueDumpResponse = 0x2674, PetBattleFinalizeLocation = 0x25f9, PetBattleFinalRound = 0x25fe, PetBattleFinished = 0x25ff, @@ -1674,19 +1688,19 @@ namespace Framework.Constants PetBattleSlotUpdates = 0x25ea, PetCastFailed = 0x2c5a, PetClearSpells = 0x2c23, - PetDismissSound = 0x269e, - PetGodMode = 0x2678, - PetGuids = 0x26ff, + PetDismissSound = 0x26a0, + PetGodMode = 0x267a, + PetGuids = 0x2701, PetLearnedSpells = 0x2c51, PetMode = 0x2588, - PetNameInvalid = 0x26bf, + PetNameInvalid = 0x26c1, PetNewlyTamed = 0x2587, PetSpellsMessage = 0x2c24, PetStableResult = 0x2592, - PetTameFailure = 0x26af, + PetTameFailure = 0x26b1, PetUnlearnedSpells = 0x2c52, PhaseShiftChange = 0x2578, - PlayedTime = 0x26d1, + PlayedTime = 0x26d3, PlayerAckowledgeArrowCallout = 0x3022, PlayerAzeriteItemEquippedStatusChanged = 0x3014, PlayerAzeriteItemGains = 0x3013, @@ -1707,25 +1721,25 @@ namespace Framework.Constants PlayerSkinned = 0x3006, PlayerTutorialHighlightSpell = 0x300d, PlayerTutorialUnhighlightSpell = 0x300c, - PlayMusic = 0x2763, - PlayObjectSound = 0x2764, - PlayOneShotAnimKit = 0x272b, + PlayMusic = 0x2765, + PlayObjectSound = 0x2766, + PlayOneShotAnimKit = 0x272d, PlayOrphanSpellVisual = 0x2c49, PlayScene = 0x2633, - PlaySound = 0x2762, - PlaySpeakerbotSound = 0x2765, + PlaySound = 0x2764, + PlaySpeakerbotSound = 0x2767, PlaySpellVisual = 0x2c47, PlaySpellVisualKit = 0x2c4b, - PlayTimeWarning = 0x26f9, + PlayTimeWarning = 0x26fb, Pong = 0x304e, - PowerUpdate = 0x26ce, + PowerUpdate = 0x26d0, PreloadChildMap = 0x2579, PreloadWorld = 0x2594, - PrepopulateNameCache = 0x283e, - PreRessurect = 0x2761, + PrepopulateNameCache = 0x2840, + PreRessurect = 0x2763, PrintNotification = 0x25c9, - ProcResist = 0x2755, - ProfessionGossip = 0x27f5, + ProcResist = 0x2757, + ProfessionGossip = 0x27f7, PushSpellToActionBar = 0x2c53, PvpCredit = 0x2946, PvpMatchComplete = 0x2951, @@ -1734,7 +1748,7 @@ namespace Framework.Constants PvpMatchStart = 0x294f, PvpMatchStatistics = 0x2932, PvpOptionsEnabled = 0x2935, - PvpTierRecord = 0x2878, + PvpTierRecord = 0x287a, QueryBattlePetNameResponse = 0x291a, QueryCreatureResponse = 0x2914, QueryGameObjectResponse = 0x2915, @@ -1750,7 +1764,7 @@ namespace Framework.Constants QueryPlayerNameByCommunityIdResponse = 0x3002, QueryQuestInfoResponse = 0x2a96, QueryRealmGuildMasterInfoResponse = 0x29e6, - QueryTimeResponse = 0x26df, + QueryTimeResponse = 0x26e1, QuestCompletionNpcResponse = 0x2a81, QuestConfirmAccept = 0x2a8f, QuestForceRemoved = 0x2a9c, @@ -1769,22 +1783,22 @@ namespace Framework.Constants QuestPoiQueryResponse = 0x2a9d, QuestPoiUpdateResponse = 0x2a9f, QuestPushResult = 0x2a90, - QuestSessionInfoResponse = 0x2861, - QuestSessionReadyCheck = 0x284f, - QuestSessionReadyCheckResponse = 0x2850, - QuestSessionResult = 0x284e, + QuestSessionInfoResponse = 0x2863, + QuestSessionReadyCheck = 0x2851, + QuestSessionReadyCheckResponse = 0x2852, + QuestSessionResult = 0x2850, QuestUpdateAddCredit = 0x2a8c, QuestUpdateAddCreditSimple = 0x2a8d, QuestUpdateAddPvpCredit = 0x2a8e, QuestUpdateComplete = 0x2a89, QuestUpdateFailed = 0x2a8a, QuestUpdateFailedTimer = 0x2a8b, - QueueSummaryUpdate = 0x2808, - RafAccountInfo = 0x284c, - RafActivityStateChanged = 0x285d, - RafDebugFriendMonths = 0x28b3, - RaidDifficultySet = 0x27a2, - RaidGroupOnly = 0x27a4, + QueueSummaryUpdate = 0x280a, + RafAccountInfo = 0x284e, + RafActivityStateChanged = 0x285f, + RafDebugFriendMonths = 0x28b6, + RaidDifficultySet = 0x27a4, + RaidGroupOnly = 0x27a6, RaidInstanceMessage = 0x2bb4, RaidMarkersChanged = 0x259f, RandomRoll = 0x262d, @@ -1792,33 +1806,33 @@ namespace Framework.Constants ReadyCheckCompleted = 0x25f6, ReadyCheckResponse = 0x25f5, ReadyCheckStarted = 0x25f4, - ReadItemResultFailed = 0x279e, - ReadItemResultOk = 0x2795, + ReadItemResultFailed = 0x27a0, + ReadItemResultOk = 0x2797, RealmQueryResponse = 0x2913, - ReattachResurrect = 0x2745, + ReattachResurrect = 0x2747, ReceivePingUnit = 0x25a0, ReceivePingWorldPoint = 0x25a1, - RecraftItemResult = 0x28a2, - RecruitAFriendFailure = 0x26bc, + RecraftItemResult = 0x28a5, + RecruitAFriendFailure = 0x26be, RefreshComponent = 0x264e, RefreshSpellHistory = 0x2c2b, RemoveItemPassive = 0x25aa, RemoveSpellFromActionBar = 0x2c54, - ReplaceTrophyResponse = 0x27ba, + ReplaceTrophyResponse = 0x27bc, ReportPvpPlayerAfkResult = 0x3001, RequestCemeteryListResponse = 0x258e, RequestPvpRewardsResponse = 0x2936, RequestScheduledPvpInfoResponse = 0x2937, ResetCompressionContext = 0x304f, - ResetFailedNotify = 0x26b3, - ResetLastLoadedConfigCvars = 0x28a8, + ResetFailedNotify = 0x26b5, + ResetLastLoadedConfigCvars = 0x28ab, ResetQuestPoi = 0x2aa0, ResetRangedCombatTimer = 0x2945, ResetWeeklyCurrency = 0x2575, RespecWipeConfirm = 0x2610, RespondInspectAchievements = 0x2572, - ResponsePerkPendingRewards = 0x287f, - ResponsePerkRecentPurchases = 0x2880, + ResponsePerkPendingRewards = 0x2881, + ResponsePerkRecentPurchases = 0x2882, RestartGlobalCooldown = 0x2c63, RestrictedAccountWarning = 0x25b8, ResumeCast = 0x2c3d, @@ -1827,21 +1841,21 @@ namespace Framework.Constants ResumeToken = 0x25a8, ResurrectRequest = 0x257e, ResyncRunes = 0x2c61, - ReturningPlayerPrompt = 0x279d, - ReturnApplicantList = 0x2842, - ReturnRecruitingClubs = 0x2841, + ReturningPlayerPrompt = 0x279f, + ReturnApplicantList = 0x2844, + ReturnRecruitingClubs = 0x2843, RoleChangedInform = 0x258a, RoleChosen = 0x2a39, RolePollInform = 0x258b, - RuneforgeLegendaryCraftingOpenNpc = 0x27f4, + RuneforgeLegendaryCraftingOpenNpc = 0x27f6, RuneRegenDebug = 0x25b5, - ScenarioCompleted = 0x27e2, + ScenarioCompleted = 0x27e4, ScenarioPois = 0x2630, ScenarioProgressUpdate = 0x2629, - ScenarioShowCriteria = 0x27f8, + ScenarioShowCriteria = 0x27fa, ScenarioState = 0x2628, - ScenarioUiUpdate = 0x27f7, - ScenarioVacate = 0x279f, + ScenarioUiUpdate = 0x27f9, + ScenarioVacate = 0x27a1, SceneObjectEvent = 0x25e0, SceneObjectPetBattleFinalRound = 0x25e5, SceneObjectPetBattleFinished = 0x25e6, @@ -1851,7 +1865,7 @@ namespace Framework.Constants SceneObjectPetBattleRoundResult = 0x25e3, ScriptCast = 0x2c58, SeasonInfo = 0x25c0, - SellResponse = 0x26c0, + SellResponse = 0x26c2, SendItemPassives = 0x25ab, SendKnownSpells = 0x2c29, SendRaidTargetUpdateAll = 0x262b, @@ -1860,48 +1874,50 @@ namespace Framework.Constants SendSpellHistory = 0x2c2a, SendUnlearnSpells = 0x2c2d, ServerFirstAchievements = 0x264b, - ServerTime = 0x267f, - ServerTimeOffset = 0x270f, + ServerTime = 0x2681, + ServerTimeOffset = 0x2711, SetupCombatLogFileFlush = 0x2c1f, SetupCurrency = 0x2573, - SetAiAnimKit = 0x272a, - SetAnimTier = 0x272e, + SetAiAnimKit = 0x272c, + SetAnimTier = 0x2730, SetChrUpgradeTier = 0x25dd, SetCurrency = 0x2574, SetDfFastLaunchResult = 0x2a2e, - SetDungeonDifficulty = 0x26a1, - SetFactionAtWar = 0x26fb, - SetFactionNotVisible = 0x2725, - SetFactionStanding = 0x2726, - SetFactionVisible = 0x2724, + SetDungeonDifficulty = 0x26a3, + SetFactionAtWar = 0x26fd, + SetFactionNotVisible = 0x2727, + SetFactionStanding = 0x2728, + SetFactionVisible = 0x2726, SetFlatSpellModifier = 0x2c38, - SetForcedReactions = 0x2718, + SetForcedReactions = 0x271a, SetItemPurchaseData = 0x259a, - SetLootMethodFailed = 0x27c6, + SetLootMethodFailed = 0x27c8, SetMaxWeeklyQuantity = 0x259d, - SetMeleeAnimKit = 0x272d, - SetMovementAnimKit = 0x272c, + SetMeleeAnimKit = 0x272f, + SetMovementAnimKit = 0x272e, SetPctSpellModifier = 0x2c39, SetPetSpecialization = 0x2622, SetPlayerDeclinedNamesResult = 0x3003, SetPlayHoverAnim = 0x25b9, - SetProficiency = 0x272f, - SetQuestReplayCooldownOverride = 0x2855, + SetProficiency = 0x2731, + SetQuestReplayCooldownOverride = 0x2857, SetShipmentReadyResponse = 0x2998, SetSpellCharges = 0x2c28, - SetTimeZoneInformation = 0x2674, - SetVehicleRecId = 0x26f2, - ShadowlandsCapacitanceUpdate = 0x2884, + SetTimeZoneInformation = 0x2676, + SetVehicleRecId = 0x26f4, + ShadowlandsCapacitanceUpdate = 0x2886, ShipmentFactionUpdateResult = 0x2999, ShowNeutralPlayerFactionSelectUi = 0x25d9, ShowQuestCompletionText = 0x2a95, - ShowTaxiNodes = 0x26c9, - ShowTradeSkillResponse = 0x276a, - SocialContractRequestResponse = 0x288f, - SocketGemsFailure = 0x2722, - SocketGemsSuccess = 0x2721, - SpecialMountAnim = 0x269c, - SpecInvoluntarilyChanged = 0x2713, + ShowTaxiNodes = 0x26cb, + ShowTradeSkillResponse = 0x276c, + SocialContractRequestResponse = 0x2891, + SocketGemsFailure = 0x2724, + SocketGemsSuccess = 0x2723, + SpecialMountAnim = 0x269e, + SpectateEnd = 0x28b8, + SpectatePlayer = 0x28b7, + SpecInvoluntarilyChanged = 0x2715, SpellAbsorbLog = 0x2c1c, SpellCategoryCooldown = 0x2c16, SpellChannelStart = 0x2c33, @@ -1930,93 +1946,93 @@ namespace Framework.Constants SpellPrepare = 0x2c3a, SpellStart = 0x2c3c, SpellVisualLoadScreen = 0x25cb, - SplashScreenShowLatest = 0x2867, - StandStateUpdate = 0x2717, + SplashScreenShowLatest = 0x2869, + StandStateUpdate = 0x2719, StarterBuildActivateFailed = 0x25d1, StartElapsedTimer = 0x2602, StartElapsedTimers = 0x2604, - StartLightningStorm = 0x26a4, + StartLightningStorm = 0x26a6, StartLootRoll = 0x261a, - StartMirrorTimer = 0x270a, + StartMirrorTimer = 0x270c, StartTimer = 0x25a4, StopElapsedTimer = 0x2603, - StopMirrorTimer = 0x270c, - StopSpeakerbotSound = 0x2766, + StopMirrorTimer = 0x270e, + StopSpeakerbotSound = 0x2768, StopTimer = 0x25a5, StreamingMovies = 0x25a3, - SuggestInviteInform = 0x278b, - SummonCancel = 0x26ad, + SuggestInviteInform = 0x278d, + SummonCancel = 0x26af, SummonRaidMemberValidateFailed = 0x258c, - SummonRequest = 0x271c, + SummonRequest = 0x271e, SupercededSpells = 0x2c4e, SuspendComms = 0x304a, SuspendToken = 0x25a7, - SyncWowEntitlements = 0x285f, - TalentsInvoluntarilyReset = 0x2712, - TaxiNodeStatus = 0x2679, - TextEmote = 0x2677, - ThreatClear = 0x26d8, - ThreatRemove = 0x26d7, - ThreatUpdate = 0x26d6, + SyncWowEntitlements = 0x2861, + TalentsInvoluntarilyReset = 0x2714, + TaxiNodeStatus = 0x267b, + TextEmote = 0x2679, + ThreatClear = 0x26da, + ThreatRemove = 0x26d9, + ThreatUpdate = 0x26d8, TimeAdjustment = 0x2dd3, TimeSyncRequest = 0x2dd2, - TitleEarned = 0x26d3, - TitleLost = 0x26d4, - TotemCreated = 0x26c3, - TotemDurationChanged = 0x26c5, - TotemMoved = 0x26c6, - TotemRemoved = 0x26c4, + TitleEarned = 0x26d5, + TitleLost = 0x26d6, + TotemCreated = 0x26c5, + TotemDurationChanged = 0x26c7, + TotemMoved = 0x26c8, + TotemRemoved = 0x26c6, TradeStatus = 0x2582, TradeUpdated = 0x2581, - TrainerBuyFailed = 0x26db, - TrainerList = 0x26da, + TrainerBuyFailed = 0x26dd, + TrainerList = 0x26dc, TraitConfigCommitFailed = 0x25d0, - TransferAborted = 0x26fe, + TransferAborted = 0x2700, TransferPending = 0x25cc, TreasurePickerResponse = 0x291f, - TriggerCinematic = 0x27bf, - TriggerMovie = 0x26c7, - TurnInPetitionResult = 0x2748, - TutorialFlags = 0x27b3, + TriggerCinematic = 0x27c1, + TriggerMovie = 0x26c9, + TurnInPetitionResult = 0x274a, + TutorialFlags = 0x27b5, UiMapQuestLinesResponse = 0x2aa2, - UndeleteCharacterResponse = 0x27c1, - UndeleteCooldownStatusResponse = 0x27c2, + UndeleteCharacterResponse = 0x27c3, + UndeleteCooldownStatusResponse = 0x27c4, UnlearnedSpells = 0x2c50, UnloadChildMap = 0x257a, - UpdateAadcStatusResponse = 0x2879, - UpdateAccountData = 0x2704, + UpdateAadcStatusResponse = 0x287b, + UpdateAccountData = 0x2706, UpdateActionButtons = 0x25de, - UpdateBnetSessionKey = 0x2819, + UpdateBnetSessionKey = 0x281b, UpdateCapturePoint = 0x2929, - UpdateCelestialBody = 0x2815, - UpdateCharacterFlags = 0x27b9, - UpdateChargeCategoryCooldown = 0x2760, - UpdateCooldown = 0x275f, + UpdateCelestialBody = 0x2817, + UpdateCharacterFlags = 0x27bb, + UpdateChargeCategoryCooldown = 0x2762, + UpdateCooldown = 0x2761, UpdateCraftingNpcRecipes = 0x2996, UpdateDailyMissionCounter = 0x297f, UpdateExpansionLevel = 0x2643, - UpdateGameTimeState = 0x281c, - UpdateInstanceOwnership = 0x26a6, - UpdateLastInstance = 0x2685, - UpdateObject = 0x27c0, + UpdateGameTimeState = 0x281e, + UpdateInstanceOwnership = 0x26a8, + UpdateLastInstance = 0x2687, + UpdateObject = 0x27c2, UpdatePrimarySpec = 0x25d6, UpdateRecentPlayerGuids = 0x25f3, UpdateTalentData = 0x25d5, - UpdateWorldState = 0x2742, + UpdateWorldState = 0x2744, UserlistAdd = 0x2bb9, UserlistRemove = 0x2bba, UserlistUpdate = 0x2bbb, - UseEquipmentSetResult = 0x2749, - VasCheckTransferOkResponse = 0x2810, - VasGetQueueMinutesResponse = 0x280e, - VasGetServiceStatusResponse = 0x280d, - VasPurchaseComplete = 0x27e8, - VasPurchaseStateUpdate = 0x27e7, + UseEquipmentSetResult = 0x274b, + VasCheckTransferOkResponse = 0x2812, + VasGetQueueMinutesResponse = 0x2810, + VasGetServiceStatusResponse = 0x280f, + VasPurchaseComplete = 0x27ea, + VasPurchaseStateUpdate = 0x27e9, VendorInventory = 0x25b7, VignetteUpdate = 0x3008, - VoiceChannelInfoResponse = 0x2814, - VoiceChannelSttTokenResponse = 0x2873, - VoiceLoginResponse = 0x2813, + VoiceChannelInfoResponse = 0x2816, + VoiceChannelSttTokenResponse = 0x2875, + VoiceLoginResponse = 0x2815, VoidItemSwapResponse = 0x2da4, VoidStorageContents = 0x2da1, VoidStorageFailed = 0x2da0, @@ -2025,24 +2041,28 @@ namespace Framework.Constants WaitQueueFinish = 0x256f, WaitQueueUpdate = 0x256e, Warden3Data = 0x2577, - Warden3Disabled = 0x2817, - Warden3Enabled = 0x2816, - WarfrontComplete = 0x2758, + Warden3Disabled = 0x2819, + Warden3Enabled = 0x2818, + WarfrontComplete = 0x275a, WargameRequestOpponentResponse = 0x2934, WargameRequestSuccessfullySentToOpponent = 0x2933, - Weather = 0x26a3, - WeeklyRewardsProgressResult = 0x286a, - WeeklyRewardsResult = 0x2868, - WeeklyRewardClaimResult = 0x2869, + Weather = 0x26a5, + WeeklyRewardsProgressResult = 0x286c, + WeeklyRewardsResult = 0x286a, + WeeklyRewardClaimResult = 0x286b, Who = 0x2bae, - WhoIs = 0x26a2, - WillBeKickedForAddedSubscriptionTime = 0x281b, + WhoIs = 0x26a4, + WillBeKickedForAddedSubscriptionTime = 0x281d, WorldQuestUpdateResponse = 0x300f, WorldServerInfo = 0x25ac, - WowEntitlementNotification = 0x2860, - XpAwardedFromCurrency = 0x28a7, + WowEntitlementNotification = 0x2862, + WowLabsNotifyPlayersMatchEnd = 0x2892, + WowLabsNotifyPlayersMatchStateChanged = 0x2893, + WowLabsPartyError = 0x289b, + WowLabsSetPredictionCircle = 0x2894, + XpAwardedFromCurrency = 0x28aa, XpGainAborted = 0x25c8, - XpGainEnabled = 0x27a3, + XpGainEnabled = 0x27a5, ZoneUnderAttack = 0x2bb5, // Opcodes That Are Not Generated Automatically diff --git a/Source/Framework/Constants/QuestConst.cs b/Source/Framework/Constants/QuestConst.cs index 7e1e3674f..f237ab578 100644 --- a/Source/Framework/Constants/QuestConst.cs +++ b/Source/Framework/Constants/QuestConst.cs @@ -369,16 +369,19 @@ namespace Framework.Constants RaceToRecipient = 29, // "%s's attempt to share quest "%s" failed. You are the wrong race for that quest." LowFaction = 30, // "%s's reputation is too low for that quest." LowFactionToRecipient = 31, // "%s's attempt to share quest "%s" failed. Your reputation is too low for that quest." - Expansion = 32, // "%s doesn't own the required expansion for that quest." - ExpansionToRecipient = 33, // "%s's attempt to share quest "%s" failed. You do not own the required expansion for that quest." - NotGarrisonOwner = 34, // "%s must own a garrison to accept that quest." - NotGarrisonOwnerToRecipient = 35, // "%s's attempt to share quest "%s" failed. You must own a garrison to accept that quest." - WrongCovenant = 36, // "%s is in the wrong covenant for that quest." - WrongCovenantToRecipient = 37, // "%s's attempt to share quest "%s" failed. You are in the wrong covenant for that quest." - NewPlayerExperience = 38, // "%s must complete Exile's Reach to accept that quest." - NewPlayerExperienceToRecipient = 39, // "%s's attempt to share quest "%s" failed. You must complete Exile's Reach to accept that quest." - WrongFaction = 40, // "%s is the wrong faction for that quest." - WrongFactionToRecipient = 41 // "%s's attempt to share quest "%s" failed. You are the wrong faction for that quest." + HighFaction = 32, // "%s's reputation is too high for that quest." + HighFactionToRecipient = 33, // "%s's attempt to share quest "%s" failed. Your reputation is too high for that quest." + Expansion = 34, // "%s doesn't own the required expansion for that quest." + ExpansionToRecipient = 35, // "%s's attempt to share quest "%s" failed. You do not own the required expansion for that quest." + NotGarrisonOwner = 36, // "%s must own a garrison to accept that quest." + NotGarrisonOwnerToRecipient = 37, // "%s's attempt to share quest "%s" failed. You must own a garrison to accept that quest." + WrongCovenant = 38, // "%s is in the wrong covenant for that quest." + WrongCovenantToRecipient = 39, // "%s's attempt to share quest "%s" failed. You are in the wrong covenant for that quest." + NewPlayerExperience = 40, // "%s must complete Exile's Reach to accept that quest." + NewPlayerExperienceToRecipient = 41, // "%s's attempt to share quest "%s" failed. You must complete Exile's Reach to accept that quest." + WrongFaction = 42, // "%s is the wrong faction for that quest." + WrongFactionToRecipient = 43, // "%s's attempt to share quest "%s" failed. You are the wrong faction for that quest." + CrossFactionRestricted = 44, // "Quests can't be shared in cross-faction groups." } public enum QuestTradeSkill diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index 4f89a7c1d..8ca1289a8 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -433,6 +433,28 @@ namespace Framework.Constants } return lootType; } + + public static int GetOtherTeam(int team) => team switch + { + BattleGroundTeamId.Alliance => BattleGroundTeamId.Horde, + BattleGroundTeamId.Horde => BattleGroundTeamId.Alliance, + _ => BattleGroundTeamId.Neutral + }; + + public static Team GetOtherTeam(Team team) => team switch + { + Team.Horde => Team.Alliance, + Team.Alliance => Team.Horde, + Team.PandariaNeutral => Team.PandariaNeutral, + _ => Team.Other + }; + + public static int GetTeamIdForTeam(Team team) => team switch + { + Team.Horde => BattleGroundTeamId.Horde, + Team.Alliance => BattleGroundTeamId.Alliance, + _ => BattleGroundTeamId.Neutral + }; } public enum Locale @@ -511,11 +533,7 @@ namespace Framework.Constants { Horde = 67, Alliance = 469, - //TEAM_STEAMWHEEDLE_CARTEL = 169, // not used in code - //TEAM_ALLIANCE_FORCES = 891, - //TEAM_HORDE_FORCES = 892, - //TEAM_SANCTUARY = 936, - //TEAM_OUTLAND = 980, + PandariaNeutral = 1249, // Starting pandas should have this team Other = 0 // if ReputationListId > 0 && Flags != FACTION_FLAG_TEAM_HEADER } @@ -2384,641 +2402,649 @@ namespace Framework.Constants QuestPushRaceToRecipientS = 491, QuestPushLowFactionS = 492, QuestPushLowFactionToRecipientS = 493, - QuestPushExpansionS = 494, - QuestPushExpansionToRecipientS = 495, - QuestPushNotGarrisonOwnerS = 496, - QuestPushNotGarrisonOwnerToRecipientS = 497, - QuestPushWrongCovenantS = 498, - QuestPushWrongCovenantToRecipientS = 499, - QuestPushNewPlayerExperienceS = 500, - QuestPushNewPlayerExperienceToRecipientS = 501, - QuestPushWrongFactionS = 502, - QuestPushWrongFactionToRecipientS = 503, - QuestPushCrossFactionRestrictedS = 504, - RaidGroupLowlevel = 505, - RaidGroupOnly = 506, - RaidGroupFull = 507, - RaidGroupRequirementsUnmatch = 508, - CorpseIsNotInInstance = 509, - PvpKillHonorable = 510, - PvpKillDishonorable = 511, - SpellFailedAlreadyAtFullHealth = 512, - SpellFailedAlreadyAtFullMana = 513, - SpellFailedAlreadyAtFullPowerS = 514, - AutolootMoneyS = 515, - GenericStunned = 516, - GenericThrottle = 517, - ClubFinderSearchingTooFast = 518, - TargetStunned = 519, - MustRepairDurability = 520, - RaidYouJoined = 521, - RaidYouLeft = 522, - InstanceGroupJoinedWithParty = 523, - InstanceGroupJoinedWithRaid = 524, - RaidMemberAddedS = 525, - RaidMemberRemovedS = 526, - InstanceGroupAddedS = 527, - InstanceGroupRemovedS = 528, - ClickOnItemToFeed = 529, - TooManyChatChannels = 530, - LootRollPending = 531, - LootPlayerNotFound = 532, - NotInRaid = 533, - LoggingOut = 534, - TargetLoggingOut = 535, - NotWhileMounted = 536, - NotWhileShapeshifted = 537, - NotInCombat = 538, - NotWhileDisarmed = 539, - PetBroken = 540, - TalentWipeError = 541, - SpecWipeError = 542, - GlyphWipeError = 543, - PetSpecWipeError = 544, - FeignDeathResisted = 545, - MeetingStoneInQueueS = 546, - MeetingStoneLeftQueueS = 547, - MeetingStoneOtherMemberLeft = 548, - MeetingStonePartyKickedFromQueue = 549, - MeetingStoneMemberStillInQueue = 550, - MeetingStoneSuccess = 551, - MeetingStoneInProgress = 552, - MeetingStoneMemberAddedS = 553, - MeetingStoneGroupFull = 554, - MeetingStoneNotLeader = 555, - MeetingStoneInvalidLevel = 556, - MeetingStoneTargetNotInParty = 557, - MeetingStoneTargetInvalidLevel = 558, - MeetingStoneMustBeLeader = 559, - MeetingStoneNoRaidGroup = 560, - MeetingStoneNeedParty = 561, - MeetingStoneNotFound = 562, - MeetingStoneTargetInVehicle = 563, - GuildemblemSame = 564, - EquipTradeItem = 565, - PvpToggleOn = 566, - PvpToggleOff = 567, - GroupJoinBattlegroundDeserters = 568, - GroupJoinBattlegroundDead = 569, - GroupJoinBattlegroundS = 570, - GroupJoinBattlegroundFail = 571, - GroupJoinBattlegroundTooMany = 572, - SoloJoinBattlegroundS = 573, - JoinSingleScenarioS = 574, - BattlegroundTooManyQueues = 575, - BattlegroundCannotQueueForRated = 576, - BattledgroundQueuedForRated = 577, - BattlegroundTeamLeftQueue = 578, - BattlegroundNotInBattleground = 579, - AlreadyInArenaTeamS = 580, - InvalidPromotionCode = 581, - BgPlayerJoinedSs = 582, - BgPlayerLeftS = 583, - RestrictedAccount = 584, - RestrictedAccountTrial = 585, - PlayTimeExceeded = 586, - ApproachingPartialPlayTime = 587, - ApproachingPartialPlayTime2 = 588, - ApproachingNoPlayTime = 589, - ApproachingNoPlayTime2 = 590, - UnhealthyTime = 591, - ChatRestrictedTrial = 592, - ChatThrottled = 593, - MailReachedCap = 594, - InvalidRaidTarget = 595, - RaidLeaderReadyCheckStartS = 596, - ReadyCheckInProgress = 597, - ReadyCheckThrottled = 598, - DungeonDifficultyFailed = 599, - DungeonDifficultyChangedS = 600, - TradeWrongRealm = 601, - TradeNotOnTaplist = 602, - ChatPlayerAmbiguousS = 603, - LootCantLootThatNow = 604, - LootMasterInvFull = 605, - LootMasterUniqueItem = 606, - LootMasterOther = 607, - FilteringYouS = 608, - UsePreventedByMechanicS = 609, - ItemUniqueEquippable = 610, - LfgLeaderIsLfmS = 611, - LfgPending = 612, - CantSpeakLangage = 613, - VendorMissingTurnins = 614, - BattlegroundNotInTeam = 615, - NotInBattleground = 616, - NotEnoughHonorPoints = 617, - NotEnoughArenaPoints = 618, - SocketingRequiresMetaGem = 619, - SocketingMetaGemOnlyInMetaslot = 620, - SocketingRequiresHydraulicGem = 621, - SocketingHydraulicGemOnlyInHydraulicslot = 622, - SocketingRequiresCogwheelGem = 623, - SocketingCogwheelGemOnlyInCogwheelslot = 624, - SocketingItemTooLowLevel = 625, - ItemMaxCountSocketed = 626, - SystemDisabled = 627, - QuestFailedTooManyDailyQuestsI = 628, - ItemMaxCountEquippedSocketed = 629, - ItemUniqueEquippableSocketed = 630, - UserSquelched = 631, - AccountSilenced = 632, - PartyMemberSilenced = 633, - PartyMemberSilencedLfgDelist = 634, - TooMuchGold = 635, - NotBarberSitting = 636, - QuestFailedCais = 637, - InviteRestrictedTrial = 638, - VoiceIgnoreFull = 639, - VoiceIgnoreSelf = 640, - VoiceIgnoreNotFound = 641, - VoiceIgnoreAlreadyS = 642, - VoiceIgnoreAddedS = 643, - VoiceIgnoreRemovedS = 644, - VoiceIgnoreAmbiguous = 645, - VoiceIgnoreDeleted = 646, - UnknownMacroOptionS = 647, - NotDuringArenaMatch = 648, - NotInRatedBattleground = 649, - PlayerSilenced = 650, - PlayerUnsilenced = 651, - ComsatDisconnect = 652, - ComsatReconnectAttempt = 653, - ComsatConnectFail = 654, - MailInvalidAttachmentSlot = 655, - MailTooManyAttachments = 656, - MailInvalidAttachment = 657, - MailAttachmentExpired = 658, - VoiceChatParentalDisableMic = 659, - ProfaneChatName = 660, - PlayerSilencedEcho = 661, - PlayerUnsilencedEcho = 662, - LootCantLootThat = 663, - ArenaExpiredCais = 664, - GroupActionThrottled = 665, - AlreadyPickpocketed = 666, - NameInvalid = 667, - NameNoName = 668, - NameTooShort = 669, - NameTooLong = 670, - NameMixedLanguages = 671, - NameProfane = 672, - NameReserved = 673, - NameThreeConsecutive = 674, - NameInvalidSpace = 675, - NameConsecutiveSpaces = 676, - NameRussianConsecutiveSilentCharacters = 677, - NameRussianSilentCharacterAtBeginningOrEnd = 678, - NameDeclensionDoesntMatchBaseName = 679, - RecruitAFriendNotLinked = 680, - RecruitAFriendNotNow = 681, - RecruitAFriendSummonLevelMax = 682, - RecruitAFriendSummonCooldown = 683, - RecruitAFriendSummonOffline = 684, - RecruitAFriendInsufExpanLvl = 685, - RecruitAFriendMapIncomingTransferNotAllowed = 686, - NotSameAccount = 687, - BadOnUseEnchant = 688, - TradeSelf = 689, - TooManySockets = 690, - ItemMaxLimitCategoryCountExceededIs = 691, - TradeTargetMaxLimitCategoryCountExceededIs = 692, - ItemMaxLimitCategorySocketedExceededIs = 693, - ItemMaxLimitCategoryEquippedExceededIs = 694, - ShapeshiftFormCannotEquip = 695, - ItemInventoryFullSatchel = 696, - ScalingStatItemLevelExceeded = 697, - ScalingStatItemLevelTooLow = 698, - PurchaseLevelTooLow = 699, - GroupSwapFailed = 700, - InviteInCombat = 701, - InvalidGlyphSlot = 702, - GenericNoValidTargets = 703, - CalendarEventAlertS = 704, - PetLearnSpellS = 705, - PetLearnAbilityS = 706, - PetSpellUnlearnedS = 707, - InviteUnknownRealm = 708, - InviteNoPartyServer = 709, - InvitePartyBusy = 710, - InvitePartyBusyPendingRequest = 711, - InvitePartyBusyPendingSuggest = 712, - PartyTargetAmbiguous = 713, - PartyLfgInviteRaidLocked = 714, - PartyLfgBootLimit = 715, - PartyLfgBootCooldownS = 716, - PartyLfgBootNotEligibleS = 717, - PartyLfgBootInpatientTimerS = 718, - PartyLfgBootInProgress = 719, - PartyLfgBootTooFewPlayers = 720, - PartyLfgBootVoteSucceeded = 721, - PartyLfgBootVoteFailed = 722, - PartyLfgBootInCombat = 723, - PartyLfgBootDungeonComplete = 724, - PartyLfgBootLootRolls = 725, - PartyLfgBootVoteRegistered = 726, - PartyPrivateGroupOnly = 727, - PartyLfgTeleportInCombat = 728, - RaidDisallowedByLevel = 729, - RaidDisallowedByCrossRealm = 730, - PartyRoleNotAvailable = 731, - JoinLfgObjectFailed = 732, - LfgRemovedLevelup = 733, - LfgRemovedXpToggle = 734, - LfgRemovedFactionChange = 735, - BattlegroundInfoThrottled = 736, - BattlegroundAlreadyIn = 737, - ArenaTeamChangeFailedQueued = 738, - ArenaTeamPermissions = 739, - NotWhileFalling = 740, - NotWhileMoving = 741, - NotWhileFatigued = 742, - MaxSockets = 743, - MultiCastActionTotemS = 744, - BattlegroundJoinLevelup = 745, - RemoveFromPvpQueueXpGain = 746, - BattlegroundJoinXpGain = 747, - BattlegroundJoinMercenary = 748, - BattlegroundJoinTooManyHealers = 749, - BattlegroundJoinRatedTooManyHealers = 750, - BattlegroundJoinTooManyTanks = 751, - BattlegroundJoinTooManyDamage = 752, - RaidDifficultyFailed = 753, - RaidDifficultyChangedS = 754, - LegacyRaidDifficultyChangedS = 755, - RaidLockoutChangedS = 756, - RaidConvertedToParty = 757, - PartyConvertedToRaid = 758, - PlayerDifficultyChangedS = 759, - GmresponseDbError = 760, - BattlegroundJoinRangeIndex = 761, - ArenaJoinRangeIndex = 762, - RemoveFromPvpQueueFactionChange = 763, - BattlegroundJoinFailed = 764, - BattlegroundJoinNoValidSpecForRole = 765, - BattlegroundJoinRespec = 766, - BattlegroundInvitationDeclined = 767, - BattlegroundInvitationDeclinedBy = 768, - BattlegroundJoinTimedOut = 769, - BattlegroundDupeQueue = 770, - BattlegroundJoinMustCompleteQuest = 771, - InBattlegroundRespec = 772, - MailLimitedDurationItem = 773, - YellRestrictedTrial = 774, - ChatRaidRestrictedTrial = 775, - LfgRoleCheckFailed = 776, - LfgRoleCheckFailedTimeout = 777, - LfgRoleCheckFailedNotViable = 778, - LfgReadyCheckFailed = 779, - LfgReadyCheckFailedTimeout = 780, - LfgGroupFull = 781, - LfgNoLfgObject = 782, - LfgNoSlotsPlayer = 783, - LfgNoSlotsParty = 784, - LfgNoSpec = 785, - LfgMismatchedSlots = 786, - LfgMismatchedSlotsLocalXrealm = 787, - LfgPartyPlayersFromDifferentRealms = 788, - LfgMembersNotPresent = 789, - LfgGetInfoTimeout = 790, - LfgInvalidSlot = 791, - LfgDeserterPlayer = 792, - LfgDeserterParty = 793, - LfgDead = 794, - LfgRandomCooldownPlayer = 795, - LfgRandomCooldownParty = 796, - LfgTooManyMembers = 797, - LfgTooFewMembers = 798, - LfgProposalFailed = 799, - LfgProposalDeclinedSelf = 800, - LfgProposalDeclinedParty = 801, - LfgNoSlotsSelected = 802, - LfgNoRolesSelected = 803, - LfgRoleCheckInitiated = 804, - LfgReadyCheckInitiated = 805, - LfgPlayerDeclinedRoleCheck = 806, - LfgPlayerDeclinedReadyCheck = 807, - LfgJoinedQueue = 808, - LfgJoinedFlexQueue = 809, - LfgJoinedRfQueue = 810, - LfgJoinedScenarioQueue = 811, - LfgJoinedWorldPvpQueue = 812, - LfgJoinedBattlefieldQueue = 813, - LfgJoinedList = 814, - LfgLeftQueue = 815, - LfgLeftList = 816, - LfgRoleCheckAborted = 817, - LfgReadyCheckAborted = 818, - LfgCantUseBattleground = 819, - LfgCantUseDungeons = 820, - LfgReasonTooManyLfg = 821, - LfgFarmLimit = 822, - LfgNoCrossFactionParties = 823, - InvalidTeleportLocation = 824, - TooFarToInteract = 825, - BattlegroundPlayersFromDifferentRealms = 826, - DifficultyChangeCooldownS = 827, - DifficultyChangeCombatCooldownS = 828, - DifficultyChangeWorldstate = 829, - DifficultyChangeEncounter = 830, - DifficultyChangeCombat = 831, - DifficultyChangePlayerBusy = 832, - DifficultyChangePlayerOnVehicle = 833, - DifficultyChangeAlreadyStarted = 834, - DifficultyChangeOtherHeroicS = 835, - DifficultyChangeHeroicInstanceAlreadyRunning = 836, - ArenaTeamPartySize = 837, - SoloShuffleWargameGroupSize = 838, - SoloShuffleWargameGroupComp = 839, - SoloMinItemLevel = 840, - PvpPlayerAbandoned = 841, - BattlegroundJoinGroupQueueWithoutHealer = 842, - QuestForceRemovedS = 843, - AttackNoActions = 844, - InRandomBg = 845, - InNonRandomBg = 846, - BnFriendSelf = 847, - BnFriendAlready = 848, - BnFriendBlocked = 849, - BnFriendListFull = 850, - BnFriendRequestSent = 851, - BnBroadcastThrottle = 852, - BgDeveloperOnly = 853, - CurrencySpellSlotMismatch = 854, - CurrencyNotTradable = 855, - RequiresExpansionS = 856, - QuestFailedSpell = 857, - TalentFailedUnspentTalentPoints = 858, - TalentFailedNotEnoughTalentsInPrimaryTree = 859, - TalentFailedNoPrimaryTreeSelected = 860, - TalentFailedCantRemoveTalent = 861, - TalentFailedUnknown = 862, - TalentFailedInCombat = 863, - TalentFailedInPvpMatch = 864, - TalentFailedInMythicPlus = 865, - WargameRequestFailure = 866, - RankRequiresAuthenticator = 867, - GuildBankVoucherFailed = 868, - WargameRequestSent = 869, - RequiresAchievementI = 870, - RefundResultExceedMaxCurrency = 871, - CantBuyQuantity = 872, - ItemIsBattlePayLocked = 873, - PartyAlreadyInBattlegroundQueue = 874, - PartyConfirmingBattlegroundQueue = 875, - BattlefieldTeamPartySize = 876, - InsuffTrackedCurrencyIs = 877, - NotOnTournamentRealm = 878, - GuildTrialAccountTrial = 879, - GuildTrialAccountVeteran = 880, - GuildUndeletableDueToLevel = 881, - CantDoThatInAGroup = 882, - GuildLeaderReplaced = 883, - TransmogrifyCantEquip = 884, - TransmogrifyInvalidItemType = 885, - TransmogrifyNotSoulbound = 886, - TransmogrifyInvalidSource = 887, - TransmogrifyInvalidDestination = 888, - TransmogrifyMismatch = 889, - TransmogrifyLegendary = 890, - TransmogrifySameItem = 891, - TransmogrifySameAppearance = 892, - TransmogrifyNotEquipped = 893, - VoidDepositFull = 894, - VoidWithdrawFull = 895, - VoidStorageWrapped = 896, - VoidStorageStackable = 897, - VoidStorageUnbound = 898, - VoidStorageRepair = 899, - VoidStorageCharges = 900, - VoidStorageQuest = 901, - VoidStorageConjured = 902, - VoidStorageMail = 903, - VoidStorageBag = 904, - VoidTransferStorageFull = 905, - VoidTransferInvFull = 906, - VoidTransferInternalError = 907, - VoidTransferItemInvalid = 908, - DifficultyDisabledInLfg = 909, - VoidStorageUnique = 910, - VoidStorageLoot = 911, - VoidStorageHoliday = 912, - VoidStorageDuration = 913, - VoidStorageLoadFailed = 914, - VoidStorageInvalidItem = 915, - ParentalControlsChatMuted = 916, - SorStartExperienceIncomplete = 917, - SorInvalidEmail = 918, - SorInvalidComment = 919, - ChallengeModeResetCooldownS = 920, - ChallengeModeResetKeystone = 921, - PetJournalAlreadyInLoadout = 922, - ReportSubmittedSuccessfully = 923, - ReportSubmissionFailed = 924, - SuggestionSubmittedSuccessfully = 925, - BugSubmittedSuccessfully = 926, - ChallengeModeEnabled = 927, - ChallengeModeDisabled = 928, - PetbattleCreateFailed = 929, - PetbattleNotHere = 930, - PetbattleNotHereOnTransport = 931, - PetbattleNotHereUnevenGround = 932, - PetbattleNotHereObstructed = 933, - PetbattleNotWhileInCombat = 934, - PetbattleNotWhileDead = 935, - PetbattleNotWhileFlying = 936, - PetbattleTargetInvalid = 937, - PetbattleTargetOutOfRange = 938, - PetbattleTargetNotCapturable = 939, - PetbattleNotATrainer = 940, - PetbattleDeclined = 941, - PetbattleInBattle = 942, - PetbattleInvalidLoadout = 943, - PetbattleAllPetsDead = 944, - PetbattleNoPetsInSlots = 945, - PetbattleNoAccountLock = 946, - PetbattleWildPetTapped = 947, - PetbattleRestrictedAccount = 948, - PetbattleOpponentNotAvailable = 949, - PetbattleNotWhileInMatchedBattle = 950, - CantHaveMorePetsOfThatType = 951, - CantHaveMorePets = 952, - PvpMapNotFound = 953, - PvpMapNotSet = 954, - PetbattleQueueQueued = 955, - PetbattleQueueAlreadyQueued = 956, - PetbattleQueueJoinFailed = 957, - PetbattleQueueJournalLock = 958, - PetbattleQueueRemoved = 959, - PetbattleQueueProposalDeclined = 960, - PetbattleQueueProposalTimeout = 961, - PetbattleQueueOpponentDeclined = 962, - PetbattleQueueRequeuedInternal = 963, - PetbattleQueueRequeuedRemoved = 964, - PetbattleQueueSlotLocked = 965, - PetbattleQueueSlotEmpty = 966, - PetbattleQueueSlotNoTracker = 967, - PetbattleQueueSlotNoSpecies = 968, - PetbattleQueueSlotCantBattle = 969, - PetbattleQueueSlotRevoked = 970, - PetbattleQueueSlotDead = 971, - PetbattleQueueSlotNoPet = 972, - PetbattleQueueNotWhileNeutral = 973, - PetbattleGameTimeLimitWarning = 974, - PetbattleGameRoundsLimitWarning = 975, - HasRestriction = 976, - ItemUpgradeItemTooLowLevel = 977, - ItemUpgradeNoPath = 978, - ItemUpgradeNoMoreUpgrades = 979, - BonusRollEmpty = 980, - ChallengeModeFull = 981, - ChallengeModeInProgress = 982, - ChallengeModeIncorrectKeystone = 983, - BattletagFriendNotFound = 984, - BattletagFriendNotValid = 985, - BattletagFriendNotAllowed = 986, - BattletagFriendThrottled = 987, - BattletagFriendSuccess = 988, - PetTooHighLevelToUncage = 989, - PetbattleInternal = 990, - CantCagePetYet = 991, - NoLootInChallengeMode = 992, - QuestPetBattleVictoriesPvpIi = 993, - RoleCheckAlreadyInProgress = 994, - RecruitAFriendAccountLimit = 995, - RecruitAFriendFailed = 996, - SetLootPersonal = 997, - SetLootMethodFailedCombat = 998, - ReagentBankFull = 999, - ReagentBankLocked = 1000, - GarrisonBuildingExists = 1001, - GarrisonInvalidPlot = 1002, - GarrisonInvalidBuildingid = 1003, - GarrisonInvalidPlotBuilding = 1004, - GarrisonRequiresBlueprint = 1005, - GarrisonNotEnoughCurrency = 1006, - GarrisonNotEnoughGold = 1007, - GarrisonCompleteMissionWrongFollowerType = 1008, - AlreadyUsingLfgList = 1009, - RestrictedAccountLfgListTrial = 1010, - ToyUseLimitReached = 1011, - ToyAlreadyKnown = 1012, - TransmogSetAlreadyKnown = 1013, - NotEnoughCurrency = 1014, - SpecIsDisabled = 1015, - FeatureRestrictedTrial = 1016, - CantBeObliterated = 1017, - CantBeScrapped = 1018, - CantBeRecrafted = 1019, - ArtifactRelicDoesNotMatchArtifact = 1020, - MustEquipArtifact = 1021, - CantDoThatRightNow = 1022, - AffectingCombat = 1023, - EquipmentManagerCombatSwapS = 1024, - EquipmentManagerBagsFull = 1025, - EquipmentManagerMissingItemS = 1026, - MovieRecordingWarningPerf = 1027, - MovieRecordingWarningDiskFull = 1028, - MovieRecordingWarningNoMovie = 1029, - MovieRecordingWarningRequirements = 1030, - MovieRecordingWarningCompressing = 1031, - NoChallengeModeReward = 1032, - ClaimedChallengeModeReward = 1033, - ChallengeModePeriodResetSs = 1034, - CantDoThatChallengeModeActive = 1035, - TalentFailedRestArea = 1036, - CannotAbandonLastPet = 1037, - TestCvarSetSss = 1038, - QuestTurnInFailReason = 1039, - ClaimedChallengeModeRewardOld = 1040, - TalentGrantedByAura = 1041, - ChallengeModeAlreadyComplete = 1042, - GlyphTargetNotAvailable = 1043, - PvpWarmodeToggleOn = 1044, - PvpWarmodeToggleOff = 1045, - SpellFailedLevelRequirement = 1046, - SpellFailedCantFlyHere = 1047, - BattlegroundJoinRequiresLevel = 1048, - BattlegroundJoinDisqualified = 1049, - BattlegroundJoinDisqualifiedNoName = 1050, - VoiceChatGenericUnableToConnect = 1051, - VoiceChatServiceLost = 1052, - VoiceChatChannelNameTooShort = 1053, - VoiceChatChannelNameTooLong = 1054, - VoiceChatChannelAlreadyExists = 1055, - VoiceChatTargetNotFound = 1056, - VoiceChatTooManyRequests = 1057, - VoiceChatPlayerSilenced = 1058, - VoiceChatParentalDisableAll = 1059, - VoiceChatDisabled = 1060, - NoPvpReward = 1061, - ClaimedPvpReward = 1062, - AzeriteEssenceSelectionFailedEssenceNotUnlocked = 1063, - AzeriteEssenceSelectionFailedCantRemoveEssence = 1064, - AzeriteEssenceSelectionFailedConditionFailed = 1065, - AzeriteEssenceSelectionFailedRestArea = 1066, - AzeriteEssenceSelectionFailedSlotLocked = 1067, - AzeriteEssenceSelectionFailedNotAtForge = 1068, - AzeriteEssenceSelectionFailedHeartLevelTooLow = 1069, - AzeriteEssenceSelectionFailedNotEquipped = 1070, - SocketingRequiresPunchcardredGem = 1071, - SocketingPunchcardredGemOnlyInPunchcardredslot = 1072, - SocketingRequiresPunchcardyellowGem = 1073, - SocketingPunchcardyellowGemOnlyInPunchcardyellowslot = 1074, - SocketingRequiresPunchcardblueGem = 1075, - SocketingPunchcardblueGemOnlyInPunchcardblueslot = 1076, - SocketingRequiresDominationShard = 1077, - SocketingDominationShardOnlyInDominationslot = 1078, - SocketingRequiresCypherGem = 1079, - SocketingCypherGemOnlyInCypherslot = 1080, - SocketingRequiresTinkerGem = 1081, - SocketingTinkerGemOnlyInTinkerslot = 1082, - SocketingRequiresPrimordialGem = 1083, - SocketingPrimordialGemOnlyInPrimordialslot = 1084, - LevelLinkingResultLinked = 1085, - LevelLinkingResultUnlinked = 1086, - ClubFinderErrorPostClub = 1087, - ClubFinderErrorApplyClub = 1088, - ClubFinderErrorRespondApplicant = 1089, - ClubFinderErrorCancelApplication = 1090, - ClubFinderErrorTypeAcceptApplication = 1091, - ClubFinderErrorTypeNoInvitePermissions = 1092, - ClubFinderErrorTypeNoPostingPermissions = 1093, - ClubFinderErrorTypeApplicantList = 1094, - ClubFinderErrorTypeApplicantListNoPerm = 1095, - ClubFinderErrorTypeFinderNotAvailable = 1096, - ClubFinderErrorTypeGetPostingIds = 1097, - ClubFinderErrorTypeJoinApplication = 1098, - ClubFinderErrorTypeRealmNotEligible = 1099, - ClubFinderErrorTypeFlaggedRename = 1100, - ClubFinderErrorTypeFlaggedDescriptionChange = 1101, - ItemInteractionNotEnoughGold = 1102, - ItemInteractionNotEnoughCurrency = 1103, - ItemInteractionNoConversionOutput = 1104, - PlayerChoiceErrorPendingChoice = 1105, - SoulbindInvalidConduit = 1106, - SoulbindInvalidConduitItem = 1107, - SoulbindInvalidTalent = 1108, - SoulbindDuplicateConduit = 1109, - ActivateSoulbindS = 1110, - ActivateSoulbindFailedRestArea = 1111, - CantUseProfanity = 1112, - NotInPetBattle = 1113, - NotInNpe = 1114, - NoSpec = 1115, - NoDominationshardOverwrite = 1116, - UseWeeklyRewardsDisabled = 1117, - CrossFactionGroupJoined = 1118, - CantTargetUnfriendlyInOverworld = 1119, - EquipablespellsSlotsFull = 1120, - ItemModAppearanceGroupAlreadyKnown = 1121, - CantBulkSellItemWithRefund = 1122, - WowLabsPartyErrorTypePartyIsFull = 1123, - WowLabsPartyErrorTypeMaxInviteSent = 1124, - WowLabsPartyErrorTypePlayerAlreadyInvited = 1125, - WowLabsPartyErrorTypePartyInviteInvalid = 1126, - WowLabsLobbyMatchmakerErrorEnterQueueFailed = 1127, - WowLabsLobbyMatchmakerErrorLeaveQueueFailed = 1128, + QuestPushHighFactionS = 494, + QuestPushHighFactionToRecipientS = 495, + QuestPushExpansionS = 496, + QuestPushExpansionToRecipientS = 497, + QuestPushNotGarrisonOwnerS = 498, + QuestPushNotGarrisonOwnerToRecipientS = 499, + QuestPushWrongCovenantS = 500, + QuestPushWrongCovenantToRecipientS = 501, + QuestPushNewPlayerExperienceS = 502, + QuestPushNewPlayerExperienceToRecipientS = 503, + QuestPushWrongFactionS = 504, + QuestPushWrongFactionToRecipientS = 505, + QuestPushCrossFactionRestrictedS = 506, + RaidGroupLowlevel = 507, + RaidGroupOnly = 508, + RaidGroupFull = 509, + RaidGroupRequirementsUnmatch = 510, + CorpseIsNotInInstance = 511, + PvpKillHonorable = 512, + PvpKillDishonorable = 513, + SpellFailedAlreadyAtFullHealth = 514, + SpellFailedAlreadyAtFullMana = 515, + SpellFailedAlreadyAtFullPowerS = 516, + AutolootMoneyS = 517, + GenericStunned = 518, + GenericThrottle = 519, + ClubFinderSearchingTooFast = 520, + TargetStunned = 521, + MustRepairDurability = 522, + RaidYouJoined = 523, + RaidYouLeft = 524, + InstanceGroupJoinedWithParty = 525, + InstanceGroupJoinedWithRaid = 526, + RaidMemberAddedS = 527, + RaidMemberRemovedS = 528, + InstanceGroupAddedS = 529, + InstanceGroupRemovedS = 530, + ClickOnItemToFeed = 531, + TooManyChatChannels = 532, + LootRollPending = 533, + LootPlayerNotFound = 534, + NotInRaid = 535, + LoggingOut = 536, + TargetLoggingOut = 537, + NotWhileMounted = 538, + NotWhileShapeshifted = 539, + NotInCombat = 540, + NotWhileDisarmed = 541, + PetBroken = 542, + TalentWipeError = 543, + SpecWipeError = 544, + GlyphWipeError = 545, + PetSpecWipeError = 546, + FeignDeathResisted = 547, + MeetingStoneInQueueS = 548, + MeetingStoneLeftQueueS = 549, + MeetingStoneOtherMemberLeft = 550, + MeetingStonePartyKickedFromQueue = 551, + MeetingStoneMemberStillInQueue = 552, + MeetingStoneSuccess = 553, + MeetingStoneInProgress = 554, + MeetingStoneMemberAddedS = 555, + MeetingStoneGroupFull = 556, + MeetingStoneNotLeader = 557, + MeetingStoneInvalidLevel = 558, + MeetingStoneTargetNotInParty = 559, + MeetingStoneTargetInvalidLevel = 560, + MeetingStoneMustBeLeader = 561, + MeetingStoneNoRaidGroup = 562, + MeetingStoneNeedParty = 563, + MeetingStoneNotFound = 564, + MeetingStoneTargetInVehicle = 565, + GuildemblemSame = 566, + EquipTradeItem = 567, + PvpToggleOn = 568, + PvpToggleOff = 569, + GroupJoinBattlegroundDeserters = 570, + GroupJoinBattlegroundDead = 571, + GroupJoinBattlegroundS = 572, + GroupJoinBattlegroundFail = 573, + GroupJoinBattlegroundTooMany = 574, + SoloJoinBattlegroundS = 575, + JoinSingleScenarioS = 576, + BattlegroundTooManyQueues = 577, + BattlegroundCannotQueueForRated = 578, + BattledgroundQueuedForRated = 579, + BattlegroundTeamLeftQueue = 580, + BattlegroundNotInBattleground = 581, + AlreadyInArenaTeamS = 582, + InvalidPromotionCode = 583, + BgPlayerJoinedSs = 584, + BgPlayerLeftS = 585, + RestrictedAccount = 586, + RestrictedAccountTrial = 587, + PlayTimeExceeded = 588, + ApproachingPartialPlayTime = 589, + ApproachingPartialPlayTime2 = 590, + ApproachingNoPlayTime = 591, + ApproachingNoPlayTime2 = 592, + UnhealthyTime = 593, + ChatRestrictedTrial = 594, + ChatThrottled = 595, + MailReachedCap = 596, + InvalidRaidTarget = 597, + RaidLeaderReadyCheckStartS = 598, + ReadyCheckInProgress = 599, + ReadyCheckThrottled = 600, + DungeonDifficultyFailed = 601, + DungeonDifficultyChangedS = 602, + TradeWrongRealm = 603, + TradeNotOnTaplist = 604, + ChatPlayerAmbiguousS = 605, + LootCantLootThatNow = 606, + LootMasterInvFull = 607, + LootMasterUniqueItem = 608, + LootMasterOther = 609, + FilteringYouS = 610, + UsePreventedByMechanicS = 611, + ItemUniqueEquippable = 612, + LfgLeaderIsLfmS = 613, + LfgPending = 614, + CantSpeakLangage = 615, + VendorMissingTurnins = 616, + BattlegroundNotInTeam = 617, + NotInBattleground = 618, + NotEnoughHonorPoints = 619, + NotEnoughArenaPoints = 620, + SocketingRequiresMetaGem = 621, + SocketingMetaGemOnlyInMetaslot = 622, + SocketingRequiresHydraulicGem = 623, + SocketingHydraulicGemOnlyInHydraulicslot = 624, + SocketingRequiresCogwheelGem = 625, + SocketingCogwheelGemOnlyInCogwheelslot = 626, + SocketingItemTooLowLevel = 627, + ItemMaxCountSocketed = 628, + SystemDisabled = 629, + QuestFailedTooManyDailyQuestsI = 630, + ItemMaxCountEquippedSocketed = 631, + ItemUniqueEquippableSocketed = 632, + UserSquelched = 633, + AccountSilenced = 634, + PartyMemberSilenced = 635, + PartyMemberSilencedLfgDelist = 636, + TooMuchGold = 637, + NotBarberSitting = 638, + QuestFailedCais = 639, + InviteRestrictedTrial = 640, + VoiceIgnoreFull = 641, + VoiceIgnoreSelf = 642, + VoiceIgnoreNotFound = 643, + VoiceIgnoreAlreadyS = 644, + VoiceIgnoreAddedS = 645, + VoiceIgnoreRemovedS = 646, + VoiceIgnoreAmbiguous = 647, + VoiceIgnoreDeleted = 648, + UnknownMacroOptionS = 649, + NotDuringArenaMatch = 650, + NotInRatedBattleground = 651, + PlayerSilenced = 652, + PlayerUnsilenced = 653, + ComsatDisconnect = 654, + ComsatReconnectAttempt = 655, + ComsatConnectFail = 656, + MailInvalidAttachmentSlot = 657, + MailTooManyAttachments = 658, + MailInvalidAttachment = 659, + MailAttachmentExpired = 660, + VoiceChatParentalDisableMic = 661, + ProfaneChatName = 662, + PlayerSilencedEcho = 663, + PlayerUnsilencedEcho = 664, + LootCantLootThat = 665, + ArenaExpiredCais = 666, + GroupActionThrottled = 667, + AlreadyPickpocketed = 668, + NameInvalid = 669, + NameNoName = 670, + NameTooShort = 671, + NameTooLong = 672, + NameMixedLanguages = 673, + NameProfane = 674, + NameReserved = 675, + NameThreeConsecutive = 676, + NameInvalidSpace = 677, + NameConsecutiveSpaces = 678, + NameRussianConsecutiveSilentCharacters = 679, + NameRussianSilentCharacterAtBeginningOrEnd = 680, + NameDeclensionDoesntMatchBaseName = 681, + RecruitAFriendNotLinked = 682, + RecruitAFriendNotNow = 683, + RecruitAFriendSummonLevelMax = 684, + RecruitAFriendSummonCooldown = 685, + RecruitAFriendSummonOffline = 686, + RecruitAFriendInsufExpanLvl = 687, + RecruitAFriendMapIncomingTransferNotAllowed = 688, + NotSameAccount = 689, + BadOnUseEnchant = 690, + TradeSelf = 691, + TooManySockets = 692, + ItemMaxLimitCategoryCountExceededIs = 693, + TradeTargetMaxLimitCategoryCountExceededIs = 694, + ItemMaxLimitCategorySocketedExceededIs = 695, + ItemMaxLimitCategoryEquippedExceededIs = 696, + ShapeshiftFormCannotEquip = 697, + ItemInventoryFullSatchel = 698, + ScalingStatItemLevelExceeded = 699, + ScalingStatItemLevelTooLow = 700, + PurchaseLevelTooLow = 701, + GroupSwapFailed = 702, + InviteInCombat = 703, + InvalidGlyphSlot = 704, + GenericNoValidTargets = 705, + CalendarEventAlertS = 706, + PetLearnSpellS = 707, + PetLearnAbilityS = 708, + PetSpellUnlearnedS = 709, + InviteUnknownRealm = 710, + InviteNoPartyServer = 711, + InvitePartyBusy = 712, + InvitePartyBusyPendingRequest = 713, + InvitePartyBusyPendingSuggest = 714, + PartyTargetAmbiguous = 715, + PartyLfgInviteRaidLocked = 716, + PartyLfgBootLimit = 717, + PartyLfgBootCooldownS = 718, + PartyLfgBootNotEligibleS = 719, + PartyLfgBootInpatientTimerS = 720, + PartyLfgBootInProgress = 721, + PartyLfgBootTooFewPlayers = 722, + PartyLfgBootVoteSucceeded = 723, + PartyLfgBootVoteFailed = 724, + PartyLfgBootInCombat = 725, + PartyLfgBootDungeonComplete = 726, + PartyLfgBootLootRolls = 727, + PartyLfgBootVoteRegistered = 728, + PartyPrivateGroupOnly = 729, + PartyLfgTeleportInCombat = 730, + RaidDisallowedByLevel = 731, + RaidDisallowedByCrossRealm = 732, + PartyRoleNotAvailable = 733, + JoinLfgObjectFailed = 734, + LfgRemovedLevelup = 735, + LfgRemovedXpToggle = 736, + LfgRemovedFactionChange = 737, + BattlegroundInfoThrottled = 738, + BattlegroundAlreadyIn = 739, + ArenaTeamChangeFailedQueued = 740, + ArenaTeamPermissions = 741, + NotWhileFalling = 742, + NotWhileMoving = 743, + NotWhileFatigued = 744, + MaxSockets = 745, + MultiCastActionTotemS = 746, + BattlegroundJoinLevelup = 747, + RemoveFromPvpQueueXpGain = 748, + BattlegroundJoinXpGain = 749, + BattlegroundJoinMercenary = 750, + BattlegroundJoinTooManyHealers = 751, + BattlegroundJoinRatedTooManyHealers = 752, + BattlegroundJoinTooManyTanks = 753, + BattlegroundJoinTooManyDamage = 754, + RaidDifficultyFailed = 755, + RaidDifficultyChangedS = 756, + LegacyRaidDifficultyChangedS = 757, + RaidLockoutChangedS = 758, + RaidConvertedToParty = 759, + PartyConvertedToRaid = 760, + PlayerDifficultyChangedS = 761, + GmresponseDbError = 762, + BattlegroundJoinRangeIndex = 763, + ArenaJoinRangeIndex = 764, + RemoveFromPvpQueueFactionChange = 765, + BattlegroundJoinFailed = 766, + BattlegroundJoinNoValidSpecForRole = 767, + BattlegroundJoinRespec = 768, + BattlegroundInvitationDeclined = 769, + BattlegroundInvitationDeclinedBy = 770, + BattlegroundJoinTimedOut = 771, + BattlegroundDupeQueue = 772, + BattlegroundJoinMustCompleteQuest = 773, + InBattlegroundRespec = 774, + MailLimitedDurationItem = 775, + YellRestrictedTrial = 776, + ChatRaidRestrictedTrial = 777, + LfgRoleCheckFailed = 778, + LfgRoleCheckFailedTimeout = 779, + LfgRoleCheckFailedNotViable = 780, + LfgReadyCheckFailed = 781, + LfgReadyCheckFailedTimeout = 782, + LfgGroupFull = 783, + LfgNoLfgObject = 784, + LfgNoSlotsPlayer = 785, + LfgNoSlotsParty = 786, + LfgNoSpec = 787, + LfgMismatchedSlots = 788, + LfgMismatchedSlotsLocalXrealm = 789, + LfgPartyPlayersFromDifferentRealms = 790, + LfgMembersNotPresent = 791, + LfgGetInfoTimeout = 792, + LfgInvalidSlot = 793, + LfgDeserterPlayer = 794, + LfgDeserterParty = 795, + LfgDead = 796, + LfgRandomCooldownPlayer = 797, + LfgRandomCooldownParty = 798, + LfgTooManyMembers = 799, + LfgTooFewMembers = 800, + LfgProposalFailed = 801, + LfgProposalDeclinedSelf = 802, + LfgProposalDeclinedParty = 803, + LfgNoSlotsSelected = 804, + LfgNoRolesSelected = 805, + LfgRoleCheckInitiated = 806, + LfgReadyCheckInitiated = 807, + LfgPlayerDeclinedRoleCheck = 808, + LfgPlayerDeclinedReadyCheck = 809, + LfgJoinedQueue = 810, + LfgJoinedFlexQueue = 811, + LfgJoinedRfQueue = 812, + LfgJoinedScenarioQueue = 813, + LfgJoinedWorldPvpQueue = 814, + LfgJoinedBattlefieldQueue = 815, + LfgJoinedList = 816, + LfgLeftQueue = 817, + LfgLeftList = 818, + LfgRoleCheckAborted = 819, + LfgReadyCheckAborted = 820, + LfgCantUseBattleground = 821, + LfgCantUseDungeons = 822, + LfgReasonTooManyLfg = 823, + LfgFarmLimit = 824, + LfgNoCrossFactionParties = 825, + InvalidTeleportLocation = 826, + TooFarToInteract = 827, + BattlegroundPlayersFromDifferentRealms = 828, + DifficultyChangeCooldownS = 829, + DifficultyChangeCombatCooldownS = 830, + DifficultyChangeWorldstate = 831, + DifficultyChangeEncounter = 832, + DifficultyChangeCombat = 833, + DifficultyChangePlayerBusy = 834, + DifficultyChangePlayerOnVehicle = 835, + DifficultyChangeAlreadyStarted = 836, + DifficultyChangeOtherHeroicS = 837, + DifficultyChangeHeroicInstanceAlreadyRunning = 838, + ArenaTeamPartySize = 839, + SoloShuffleWargameGroupSize = 840, + SoloShuffleWargameGroupComp = 841, + SoloMinItemLevel = 842, + PvpPlayerAbandoned = 843, + BattlegroundJoinGroupQueueWithoutHealer = 844, + QuestForceRemovedS = 845, + AttackNoActions = 846, + InRandomBg = 847, + InNonRandomBg = 848, + BnFriendSelf = 849, + BnFriendAlready = 850, + BnFriendBlocked = 851, + BnFriendListFull = 852, + BnFriendRequestSent = 853, + BnBroadcastThrottle = 854, + BgDeveloperOnly = 855, + CurrencySpellSlotMismatch = 856, + CurrencyNotTradable = 857, + RequiresExpansionS = 858, + QuestFailedSpell = 859, + TalentFailedUnspentTalentPoints = 860, + TalentFailedNotEnoughTalentsInPrimaryTree = 861, + TalentFailedNoPrimaryTreeSelected = 862, + TalentFailedCantRemoveTalent = 863, + TalentFailedUnknown = 864, + TalentFailedInCombat = 865, + TalentFailedInPvpMatch = 866, + TalentFailedInMythicPlus = 867, + WargameRequestFailure = 868, + RankRequiresAuthenticator = 869, + GuildBankVoucherFailed = 870, + WargameRequestSent = 871, + RequiresAchievementI = 872, + RefundResultExceedMaxCurrency = 873, + CantBuyQuantity = 874, + ItemIsBattlePayLocked = 875, + PartyAlreadyInBattlegroundQueue = 876, + PartyConfirmingBattlegroundQueue = 877, + BattlefieldTeamPartySize = 878, + InsuffTrackedCurrencyIs = 879, + NotOnTournamentRealm = 880, + GuildTrialAccountTrial = 881, + GuildTrialAccountVeteran = 882, + GuildUndeletableDueToLevel = 883, + CantDoThatInAGroup = 884, + GuildLeaderReplaced = 885, + TransmogrifyCantEquip = 886, + TransmogrifyInvalidItemType = 887, + TransmogrifyNotSoulbound = 888, + TransmogrifyInvalidSource = 889, + TransmogrifyInvalidDestination = 890, + TransmogrifyMismatch = 891, + TransmogrifyLegendary = 892, + TransmogrifySameItem = 893, + TransmogrifySameAppearance = 894, + TransmogrifyNotEquipped = 895, + VoidDepositFull = 896, + VoidWithdrawFull = 897, + VoidStorageWrapped = 898, + VoidStorageStackable = 899, + VoidStorageUnbound = 900, + VoidStorageRepair = 901, + VoidStorageCharges = 902, + VoidStorageQuest = 903, + VoidStorageConjured = 904, + VoidStorageMail = 905, + VoidStorageBag = 906, + VoidTransferStorageFull = 907, + VoidTransferInvFull = 908, + VoidTransferInternalError = 909, + VoidTransferItemInvalid = 910, + DifficultyDisabledInLfg = 911, + VoidStorageUnique = 912, + VoidStorageLoot = 913, + VoidStorageHoliday = 914, + VoidStorageDuration = 915, + VoidStorageLoadFailed = 916, + VoidStorageInvalidItem = 917, + ParentalControlsChatMuted = 918, + SorStartExperienceIncomplete = 919, + SorInvalidEmail = 920, + SorInvalidComment = 921, + ChallengeModeResetCooldownS = 922, + ChallengeModeResetKeystone = 923, + PetJournalAlreadyInLoadout = 924, + ReportSubmittedSuccessfully = 925, + ReportSubmissionFailed = 926, + SuggestionSubmittedSuccessfully = 927, + BugSubmittedSuccessfully = 928, + ChallengeModeEnabled = 929, + ChallengeModeDisabled = 930, + PetbattleCreateFailed = 931, + PetbattleNotHere = 932, + PetbattleNotHereOnTransport = 933, + PetbattleNotHereUnevenGround = 934, + PetbattleNotHereObstructed = 935, + PetbattleNotWhileInCombat = 936, + PetbattleNotWhileDead = 937, + PetbattleNotWhileFlying = 938, + PetbattleTargetInvalid = 939, + PetbattleTargetOutOfRange = 940, + PetbattleTargetNotCapturable = 941, + PetbattleNotATrainer = 942, + PetbattleDeclined = 943, + PetbattleInBattle = 944, + PetbattleInvalidLoadout = 945, + PetbattleAllPetsDead = 946, + PetbattleNoPetsInSlots = 947, + PetbattleNoAccountLock = 948, + PetbattleWildPetTapped = 949, + PetbattleRestrictedAccount = 950, + PetbattleOpponentNotAvailable = 951, + PetbattleNotWhileInMatchedBattle = 952, + CantHaveMorePetsOfThatType = 953, + CantHaveMorePets = 954, + PvpMapNotFound = 955, + PvpMapNotSet = 956, + PetbattleQueueQueued = 957, + PetbattleQueueAlreadyQueued = 958, + PetbattleQueueJoinFailed = 959, + PetbattleQueueJournalLock = 960, + PetbattleQueueRemoved = 961, + PetbattleQueueProposalDeclined = 962, + PetbattleQueueProposalTimeout = 963, + PetbattleQueueOpponentDeclined = 964, + PetbattleQueueRequeuedInternal = 965, + PetbattleQueueRequeuedRemoved = 966, + PetbattleQueueSlotLocked = 967, + PetbattleQueueSlotEmpty = 968, + PetbattleQueueSlotNoTracker = 969, + PetbattleQueueSlotNoSpecies = 970, + PetbattleQueueSlotCantBattle = 971, + PetbattleQueueSlotRevoked = 972, + PetbattleQueueSlotDead = 973, + PetbattleQueueSlotNoPet = 974, + PetbattleQueueNotWhileNeutral = 975, + PetbattleGameTimeLimitWarning = 976, + PetbattleGameRoundsLimitWarning = 977, + HasRestriction = 978, + ItemUpgradeItemTooLowLevel = 979, + ItemUpgradeNoPath = 980, + ItemUpgradeNoMoreUpgrades = 981, + BonusRollEmpty = 982, + ChallengeModeFull = 983, + ChallengeModeInProgress = 984, + ChallengeModeIncorrectKeystone = 985, + BattletagFriendNotFound = 986, + BattletagFriendNotValid = 987, + BattletagFriendNotAllowed = 988, + BattletagFriendThrottled = 989, + BattletagFriendSuccess = 990, + PetTooHighLevelToUncage = 991, + PetbattleInternal = 992, + CantCagePetYet = 993, + NoLootInChallengeMode = 994, + QuestPetBattleVictoriesPvpIi = 995, + RoleCheckAlreadyInProgress = 996, + RecruitAFriendAccountLimit = 997, + RecruitAFriendFailed = 998, + SetLootPersonal = 999, + SetLootMethodFailedCombat = 1000, + ReagentBankFull = 1001, + ReagentBankLocked = 1002, + GarrisonBuildingExists = 1003, + GarrisonInvalidPlot = 1004, + GarrisonInvalidBuildingid = 1005, + GarrisonInvalidPlotBuilding = 1006, + GarrisonRequiresBlueprint = 1007, + GarrisonNotEnoughCurrency = 1008, + GarrisonNotEnoughGold = 1009, + GarrisonCompleteMissionWrongFollowerType = 1010, + AlreadyUsingLfgList = 1011, + RestrictedAccountLfgListTrial = 1012, + ToyUseLimitReached = 1013, + ToyAlreadyKnown = 1014, + TransmogSetAlreadyKnown = 1015, + NotEnoughCurrency = 1016, + SpecIsDisabled = 1017, + FeatureRestrictedTrial = 1018, + CantBeObliterated = 1019, + CantBeScrapped = 1020, + CantBeRecrafted = 1021, + ArtifactRelicDoesNotMatchArtifact = 1022, + MustEquipArtifact = 1023, + CantDoThatRightNow = 1024, + AffectingCombat = 1025, + EquipmentManagerCombatSwapS = 1026, + EquipmentManagerBagsFull = 1027, + EquipmentManagerMissingItemS = 1028, + MovieRecordingWarningPerf = 1029, + MovieRecordingWarningDiskFull = 1030, + MovieRecordingWarningNoMovie = 1031, + MovieRecordingWarningRequirements = 1032, + MovieRecordingWarningCompressing = 1033, + NoChallengeModeReward = 1034, + ClaimedChallengeModeReward = 1035, + ChallengeModePeriodResetSs = 1036, + CantDoThatChallengeModeActive = 1037, + TalentFailedRestArea = 1038, + CannotAbandonLastPet = 1039, + TestCvarSetSss = 1040, + QuestTurnInFailReason = 1041, + ClaimedChallengeModeRewardOld = 1042, + TalentGrantedByAura = 1043, + ChallengeModeAlreadyComplete = 1044, + GlyphTargetNotAvailable = 1045, + PvpWarmodeToggleOn = 1046, + PvpWarmodeToggleOff = 1047, + SpellFailedLevelRequirement = 1048, + SpellFailedCantFlyHere = 1049, + BattlegroundJoinRequiresLevel = 1050, + BattlegroundJoinDisqualified = 1051, + BattlegroundJoinDisqualifiedNoName = 1052, + VoiceChatGenericUnableToConnect = 1053, + VoiceChatServiceLost = 1054, + VoiceChatChannelNameTooShort = 1055, + VoiceChatChannelNameTooLong = 1056, + VoiceChatChannelAlreadyExists = 1057, + VoiceChatTargetNotFound = 1058, + VoiceChatTooManyRequests = 1059, + VoiceChatPlayerSilenced = 1060, + VoiceChatParentalDisableAll = 1061, + VoiceChatDisabled = 1062, + NoPvpReward = 1063, + ClaimedPvpReward = 1064, + AzeriteEssenceSelectionFailedEssenceNotUnlocked = 1065, + AzeriteEssenceSelectionFailedCantRemoveEssence = 1066, + AzeriteEssenceSelectionFailedConditionFailed = 1067, + AzeriteEssenceSelectionFailedRestArea = 1068, + AzeriteEssenceSelectionFailedSlotLocked = 1069, + AzeriteEssenceSelectionFailedNotAtForge = 1070, + AzeriteEssenceSelectionFailedHeartLevelTooLow = 1071, + AzeriteEssenceSelectionFailedNotEquipped = 1072, + SocketingRequiresPunchcardredGem = 1073, + SocketingPunchcardredGemOnlyInPunchcardredslot = 1074, + SocketingRequiresPunchcardyellowGem = 1075, + SocketingPunchcardyellowGemOnlyInPunchcardyellowslot = 1076, + SocketingRequiresPunchcardblueGem = 1077, + SocketingPunchcardblueGemOnlyInPunchcardblueslot = 1078, + SocketingRequiresDominationShard = 1079, + SocketingDominationShardOnlyInDominationslot = 1080, + SocketingRequiresCypherGem = 1081, + SocketingCypherGemOnlyInCypherslot = 1082, + SocketingRequiresTinkerGem = 1083, + SocketingTinkerGemOnlyInTinkerslot = 1084, + SocketingRequiresPrimordialGem = 1085, + SocketingPrimordialGemOnlyInPrimordialslot = 1086, + LevelLinkingResultLinked = 1087, + LevelLinkingResultUnlinked = 1088, + ClubFinderErrorPostClub = 1089, + ClubFinderErrorApplyClub = 1090, + ClubFinderErrorRespondApplicant = 1091, + ClubFinderErrorCancelApplication = 1092, + ClubFinderErrorTypeAcceptApplication = 1093, + ClubFinderErrorTypeNoInvitePermissions = 1094, + ClubFinderErrorTypeNoPostingPermissions = 1095, + ClubFinderErrorTypeApplicantList = 1096, + ClubFinderErrorTypeApplicantListNoPerm = 1097, + ClubFinderErrorTypeFinderNotAvailable = 1098, + ClubFinderErrorTypeGetPostingIds = 1099, + ClubFinderErrorTypeJoinApplication = 1100, + ClubFinderErrorTypeRealmNotEligible = 1101, + ClubFinderErrorTypeFlaggedRename = 1102, + ClubFinderErrorTypeFlaggedDescriptionChange = 1103, + ItemInteractionNotEnoughGold = 1104, + ItemInteractionNotEnoughCurrency = 1105, + ItemInteractionNoConversionOutput = 1106, + PlayerChoiceErrorPendingChoice = 1107, + SoulbindInvalidConduit = 1108, + SoulbindInvalidConduitItem = 1109, + SoulbindInvalidTalent = 1110, + SoulbindDuplicateConduit = 1111, + ActivateSoulbindS = 1112, + ActivateSoulbindFailedRestArea = 1113, + CantUseProfanity = 1114, + NotInPetBattle = 1115, + NotInNpe = 1116, + NoSpec = 1117, + NoDominationshardOverwrite = 1118, + UseWeeklyRewardsDisabled = 1119, + CrossFactionGroupJoined = 1120, + CantTargetUnfriendlyInOverworld = 1121, + EquipablespellsSlotsFull = 1122, + ItemModAppearanceGroupAlreadyKnown = 1123, + CantBulkSellItemWithRefund = 1124, + WowLabsPartyErrorTypePartyIsFull = 1125, + WowLabsPartyErrorTypeMaxInviteSent = 1126, + WowLabsPartyErrorTypePlayerAlreadyInvited = 1127, + WowLabsPartyErrorTypePartyInviteInvalid = 1128, + WowLabsLobbyMatchmakerErrorEnterQueueFailed = 1129, + WowLabsLobbyMatchmakerErrorLeaveQueueFailed = 1130, + TargetIsSelfFoundCannotTrade = 1131, + PlayerIsSelfFoundCannotTrade = 1132, + MailRecepientIsSelfFoundCannotReceiveMail = 1133, + PlayerIsSelfFoundCannotSendMail = 1134, + PlayerIsSelfFoundCannotUseAuctionHouse = 1135, + MailTargetCannotReceiveMail = 1136, } public enum SceneFlags diff --git a/Source/Framework/Database/Databases/HotfixDatabase.cs b/Source/Framework/Database/Databases/HotfixDatabase.cs index 96304ac98..96cddf952 100644 --- a/Source/Framework/Database/Databases/HotfixDatabase.cs +++ b/Source/Framework/Database/Databases/HotfixDatabase.cs @@ -9,7 +9,8 @@ namespace Framework.Database { // Achievement.db2 PrepareStatement(HotfixStatements.SEL_ACHIEVEMENT, "SELECT Description, Title, Reward, ID, InstanceID, Faction, Supercedes, Category, MinimumCriteria, " + - "Points, Flags, UiOrder, IconFileID, RewardItemID, CriteriaTree, SharesCriteria, CovenantID FROM achievement WHERE (`VerifiedBuild` > 0) = ?"); + "Points, Flags, UiOrder, IconFileID, RewardItemID, CriteriaTree, SharesCriteria, CovenantID, HiddenBeforeDisplaySeason, LegacyAfterTimeEvent" + + " FROM achievement WHERE (`VerifiedBuild` > 0) = ?"); PrepareStatement(HotfixStatements.SEL_ACHIEVEMENT_LOCALE, "SELECT ID, Description_lang, Title_lang, Reward_lang FROM achievement_locale" + " WHERE (`VerifiedBuild` > 0) = ? AND locale = ?"); @@ -20,9 +21,9 @@ namespace Framework.Database // AdventureJournal.db2 PrepareStatement(HotfixStatements.SEL_ADVENTURE_JOURNAL, "SELECT ID, Name, Description, ButtonText, RewardDescription, ContinueDescription, Type, " + - "PlayerConditionID, Flags, ButtonActionType, TextureFileDataID, LfgDungeonID, QuestID, BattleMasterListID, PriorityMin, PriorityMax, ItemID, " + - "ItemQuantity, CurrencyType, CurrencyQuantity, UiMapID, BonusPlayerConditionID1, BonusPlayerConditionID2, BonusValue1, BonusValue2" + - " FROM adventure_journal WHERE (`VerifiedBuild` > 0) = ?"); + "PlayerConditionID, Flags, ButtonActionType, TextureFileDataID, LfgDungeonID, QuestID, BattleMasterListID, PriorityMin, PriorityMax, " + + "CurrencyType, CurrencyQuantity, UiMapID, BonusPlayerConditionID1, BonusPlayerConditionID2, BonusValue1, BonusValue2 FROM adventure_journal" + + " WHERE (`VerifiedBuild` > 0) = ?"); PrepareStatement(HotfixStatements.SEL_ADVENTURE_JOURNAL_LOCALE, "SELECT ID, Name_lang, Description_lang, ButtonText_lang, RewardDescription_lang, " + "ContinueDescription_lang FROM adventure_journal_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?"); diff --git a/Source/Framework/GameMath/AxisAlignedBox.cs b/Source/Framework/GameMath/AxisAlignedBox.cs index 5e448dd8a..a62b9e90b 100644 --- a/Source/Framework/GameMath/AxisAlignedBox.cs +++ b/Source/Framework/GameMath/AxisAlignedBox.cs @@ -296,6 +296,14 @@ namespace Framework.GameMath return v; } + public Vector3 extent() + { + if (Lo.IsEmpty()) + return Vector3.Zero; + + return Hi - Lo; + } + public static AxisAlignedBox operator +(AxisAlignedBox box, Vector3 v) { AxisAlignedBox outt = new(); diff --git a/Source/Framework/GameMath/Ray.cs b/Source/Framework/GameMath/Ray.cs index 972631192..96bf0bea2 100644 --- a/Source/Framework/GameMath/Ray.cs +++ b/Source/Framework/GameMath/Ray.cs @@ -210,6 +210,11 @@ namespace Framework.GameMath { return Vector3.Divide(Vector3.One, Direction); } + + public Ray bumpedRay(float distance) + { + return new Ray(Origin + Direction * distance, Direction); + } } #region RayConverter class diff --git a/Source/Framework/IO/Zlib/Deflate.cs b/Source/Framework/IO/Zlib/Deflate.cs index d9502a791..600e96e95 100644 --- a/Source/Framework/IO/Zlib/Deflate.cs +++ b/Source/Framework/IO/Zlib/Deflate.cs @@ -618,11 +618,10 @@ namespace Framework.IO if(strm==null||strm.state==null||dictionary==null) return Z_STREAM_ERROR; - deflate_state s=strm.state as deflate_state; - if(s==null||s.wrap==2||(s.wrap==1&&s.status!=INIT_STATE)) - return Z_STREAM_ERROR; + if (strm.state is not deflate_state s || s.wrap == 2 || (s.wrap == 1 && s.status != INIT_STATE)) + return Z_STREAM_ERROR; - if(s.wrap!=0) strm.adler=adler32(strm.adler, dictionary, dictLength); + if (s.wrap!=0) strm.adler=adler32(strm.adler, dictionary, dictLength); if(length : SSLSocket, IAbstractSocket + public abstract class BaseHttpSocket : SocketBase, IAbstractSocket { - public BaseSocket(Socket socket) : base(socket) { } + public BaseHttpSocket(Socket socket, bool useSSL = false) : base(socket, useSSL) { } + + public async override Task HandshakeHandler(Exception exception = null) + { + if (exception != null) + { + Log.outError(LogFilter.Http, $"{GetClientInfo()} SSL Handshake failed {exception.Message}"); + CloseSocket(); + return; + } + + await AsyncRead(); + } public async override void ReadHandler(byte[] data, int receivedLength) { @@ -114,5 +127,6 @@ namespace Framework.Networking.Http protected AsyncCallbackProcessor _queryProcessor = new(); protected SessionState _state; + protected ISocket socket; } } \ No newline at end of file diff --git a/Source/Framework/Networking/Http/HttpSslSocket.cs b/Source/Framework/Networking/Http/HttpSslSocket.cs deleted file mode 100644 index f85cf4589..000000000 --- a/Source/Framework/Networking/Http/HttpSslSocket.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; -using System.Security.Cryptography.X509Certificates; -using Framework.Configuration; - -namespace Framework.Networking.Http -{ - public class SslSocket : BaseSocket - { - X509Certificate2 _certificate; - - public SslSocket(Socket socket) : base(socket) - { - _certificate = new X509Certificate2(ConfigMgr.GetDefaultValue("CertificatesFile", "./BNetServer.pfx")); - } - - public async override void Start() - { - await AsyncHandshake(_certificate); - } - - public async override Task HandshakeHandler(Exception exception = null) - { - if (exception != null) - { - Log.outError(LogFilter.Http, $"{GetClientInfo()} SSL Handshake failed {exception.Message}"); - CloseSocket(); - return; - } - - await AsyncRead(); - } - } -} diff --git a/Source/Framework/Networking/SSLSocket.cs b/Source/Framework/Networking/SSLSocket.cs deleted file mode 100644 index 817cafd7e..000000000 --- a/Source/Framework/Networking/SSLSocket.cs +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using System; -using System.Net; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; - -namespace Framework.Networking -{ - public abstract class SSLSocket : ISocket, IDisposable - { - Socket _socket; - internal SslStream _stream; - IPEndPoint _remoteEndPoint; - byte[] _receiveBuffer; - - protected SSLSocket(Socket socket) - { - _socket = socket; - _remoteEndPoint = (IPEndPoint)_socket.RemoteEndPoint; - _receiveBuffer = new byte[ushort.MaxValue]; - - _stream = new SslStream(new NetworkStream(socket), false); - } - - public virtual void Dispose() - { - _receiveBuffer = null; - _stream.Dispose(); - } - - public abstract void Start(); - - public virtual bool Update() - { - return _socket.Connected; - } - - public IPAddress GetRemoteIpAddress() - { - return _remoteEndPoint.Address; - } - - public async Task AsyncRead() - { - if (!IsOpen()) - return; - - try - { - var result = await _stream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length); - if (result == 0) - { - CloseSocket(); - return; - } - - ReadHandler(_receiveBuffer, result); - } - catch (Exception ex) - { - Log.outDebug(LogFilter.Network, ex.Message); - } - } - - public async Task AsyncHandshake(X509Certificate2 certificate) - { - try - { - await _stream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls12, false); - } - catch (Exception ex) - { - await HandshakeHandler(ex); - return; - } - - await HandshakeHandler(); - } - - public abstract Task HandshakeHandler(Exception ex = null); - - public abstract void ReadHandler(byte[] data, int receivedLength); - - public async Task AsyncWrite(byte[] data) - { - if (!IsOpen()) - return; - - try - { - await _stream.WriteAsync(data, 0, data.Length); - } - catch (Exception ex) - { - Log.outException(ex); - } - } - - public void CloseSocket() - { - try - { - _socket.Shutdown(SocketShutdown.Both); - _socket.Close(); - } - catch (Exception ex) - { - Log.outDebug(LogFilter.Network, $"WorldSocket.CloseSocket: {GetRemoteIpAddress()} errored when shutting down socket: {ex.Message}"); - } - } - - public virtual void OnClose() { Dispose(); } - - public bool IsOpen() { return _socket.Connected; } - - public void SetNoDelay(bool enable) - { - _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, enable); - } - } -} diff --git a/Source/Framework/Networking/SocketBase.cs b/Source/Framework/Networking/SocketBase.cs index bdfe185ba..d573da230 100644 --- a/Source/Framework/Networking/SocketBase.cs +++ b/Source/Framework/Networking/SocketBase.cs @@ -2,8 +2,13 @@ // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. using System; +using System.IO; using System.Net; +using System.Net.Security; using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; namespace Framework.Networking { @@ -15,92 +20,126 @@ namespace Framework.Networking void CloseSocket(); } + public delegate Task SocketReadCallback(byte[] data, int receivedLength); + public abstract class SocketBase : ISocket, IDisposable { Socket _socket; - IPEndPoint _remoteIPEndPoint; + Stream _stream; + IPEndPoint _remoteEndPoint; + byte[] _receiveBuffer; - SocketAsyncEventArgs receiveSocketAsyncEventArgsWithCallback; - SocketAsyncEventArgs receiveSocketAsyncEventArgs; - - public delegate void SocketReadCallback(SocketAsyncEventArgs args); - - protected SocketBase(Socket socket) + protected SocketBase(Socket socket, bool useSSL = false) { _socket = socket; - _remoteIPEndPoint = (IPEndPoint)_socket.RemoteEndPoint; + _remoteEndPoint = (IPEndPoint)_socket.RemoteEndPoint; + _receiveBuffer = new byte[ushort.MaxValue]; - receiveSocketAsyncEventArgsWithCallback = new SocketAsyncEventArgs(); - receiveSocketAsyncEventArgsWithCallback.SetBuffer(new byte[0x4000], 0, 0x4000); - - receiveSocketAsyncEventArgs = new SocketAsyncEventArgs(); - receiveSocketAsyncEventArgs.SetBuffer(new byte[0x4000], 0, 0x4000); - receiveSocketAsyncEventArgs.Completed += (sender, args) => ProcessReadAsync(args); + if (useSSL) + _stream = new SslStream(new NetworkStream(socket), false); + else + _stream = new NetworkStream(socket); } public virtual void Dispose() { - _socket.Dispose(); + _receiveBuffer = null; + _stream.Dispose(); } - public virtual void Start() { } + public abstract void Start(); public virtual bool Update() { return IsOpen(); } - public IPEndPoint GetRemoteIpAddress() + public IPAddress GetRemoteIpAddress() { - return _remoteIPEndPoint; + return _remoteEndPoint.Address; } - public void AsyncReadWithCallback(SocketReadCallback callback) + public IPEndPoint GetRemoteIpEndPoint() + { + return _remoteEndPoint; + } + + public async void AsyncReadWithCallback(SocketReadCallback callback) { if (!IsOpen()) return; - receiveSocketAsyncEventArgsWithCallback.Completed += (sender, args) => callback(args); - receiveSocketAsyncEventArgsWithCallback.SetBuffer(0, 0x4000); - if (!_socket.ReceiveAsync(receiveSocketAsyncEventArgsWithCallback)) - callback(receiveSocketAsyncEventArgsWithCallback); - } - - public void AsyncRead() - { - if (!IsOpen()) - return; - - receiveSocketAsyncEventArgs.SetBuffer(0, 0x4000); - if (!_socket.ReceiveAsync(receiveSocketAsyncEventArgs)) - ProcessReadAsync(receiveSocketAsyncEventArgs); - } - - void ProcessReadAsync(SocketAsyncEventArgs args) - { - if (args.SocketError != SocketError.Success) + try { - CloseSocket(); + var result = await _stream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length); + if (result == 0) + { + CloseSocket(); + return; + } + + await callback(_receiveBuffer, result); + } + catch (Exception ex) + { + Log.outDebug(LogFilter.Network, ex.Message); + } + } + + public async Task AsyncRead() + { + if (!IsOpen()) + return; + + try + { + var result = await _stream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length); + if (result == 0) + { + CloseSocket(); + return; + } + + ReadHandler(_receiveBuffer, result); + } + catch (Exception ex) + { + Log.outDebug(LogFilter.Network, ex.Message); + } + } + + public async Task AsyncHandshake(X509Certificate2 certificate) + { + try + { + await (_stream as SslStream).AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls12, false); + } + catch (Exception ex) + { + await HandshakeHandler(ex); return; } - if (args.BytesTransferred == 0) - { - CloseSocket(); - return; - } - - ReadHandler(args); + await HandshakeHandler(); } - public abstract void ReadHandler(SocketAsyncEventArgs args); + public virtual Task HandshakeHandler(Exception exception = null) { return null; } - public void AsyncWrite(byte[] data) + public abstract void ReadHandler(byte[] data, int receivedLength); + + public async Task AsyncWrite(byte[] data) { if (!IsOpen()) return; - _socket.Send(data); + try + { + await _stream.WriteAsync(data, 0, data.Length); + } + catch (Exception ex) + { + Log.outException(ex); + } } public void CloseSocket() diff --git a/Source/Framework/Util/Extensions.cs b/Source/Framework/Util/Extensions.cs index 84776a600..5441a22ba 100644 --- a/Source/Framework/Util/Extensions.cs +++ b/Source/Framework/Util/Extensions.cs @@ -300,6 +300,11 @@ namespace System return kZMat * (kYMat * kXMat); } + public static bool IsEmpty(this Vector3 vector3) + { + return float.IsNaN(vector3.X) || float.IsNaN(vector3.Y) || float.IsNaN(vector3.Z); + } + #region Strings public static bool IsEmpty(this string str) { diff --git a/Source/Game/Achievements/AchievementManager.cs b/Source/Game/Achievements/AchievementManager.cs index a1c1636f0..f5f279f73 100644 --- a/Source/Game/Achievements/AchievementManager.cs +++ b/Source/Game/Achievements/AchievementManager.cs @@ -506,14 +506,26 @@ namespace Game.Achievements //! Since no common attributes were found, (not even in titleRewardFlags field) //! we explicitly check by ID. Maybe in the future we could move the achievement_reward //! condition fields to the condition system. - uint titleId = reward.TitleId[achievement.Id == 1793 ? (int)_owner.GetNativeGender() : (_owner.GetTeam() == Team.Alliance ? 0 : 1)]; - if (titleId != 0) + uint titleId = 0; + if (achievement.Id == 1793) + titleId = reward.TitleId[(int)_owner.GetNativeGender()]; + else { - CharTitlesRecord titleEntry = CliDB.CharTitlesStorage.LookupByKey(titleId); - if (titleEntry != null) - _owner.SetTitle(titleEntry); + switch (_owner.GetTeam()) + { + case Team.Alliance: + titleId = reward.TitleId[0]; + break; + case Team.Horde: + titleId = reward.TitleId[1]; + break; + } } + var titleEntry = CliDB.CharTitlesStorage.LookupByKey(titleId); + if (titleEntry != null) + _owner.SetTitle(titleEntry); + // mail if (reward.SenderCreatureId != 0) { diff --git a/Source/Game/Achievements/CriteriaHandler.cs b/Source/Game/Achievements/CriteriaHandler.cs index 5dc2be945..20fa86ebf 100644 --- a/Source/Game/Achievements/CriteriaHandler.cs +++ b/Source/Game/Achievements/CriteriaHandler.cs @@ -1254,8 +1254,7 @@ namespace Game.Achievements } case ModifierTreeType.PlayerMeetsCondition: // 2 { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(reqValue); - if (playerCondition == null || !ConditionManager.IsPlayerMeetingCondition(referencePlayer, playerCondition)) + if (!ConditionManager.IsPlayerMeetingCondition(referencePlayer, reqValue)) return false; break; } @@ -1520,8 +1519,7 @@ namespace Game.Achievements if (refe == null || !refe.IsPlayer()) return false; - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(reqValue); - if (playerCondition == null || !ConditionManager.IsPlayerMeetingCondition(refe.ToPlayer(), playerCondition)) + if (!ConditionManager.IsPlayerMeetingCondition(refe.ToPlayer(), reqValue)) return false; break; } diff --git a/Source/Game/Arenas/Arena.cs b/Source/Game/Arenas/Arena.cs index 441ba79fc..d540f6a0c 100644 --- a/Source/Game/Arenas/Arena.cs +++ b/Source/Game/Arenas/Arena.cs @@ -102,7 +102,7 @@ namespace Game.Arenas { // if the player was a match participant, calculate rating - ArenaTeam winnerArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(GetOtherTeam(bgPlayer.Team))); + ArenaTeam winnerArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(SharedConst.GetOtherTeam(bgPlayer.Team))); ArenaTeam loserArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(bgPlayer.Team)); // left a rated match while the encounter was in progress, consider as loser @@ -110,9 +110,9 @@ namespace Game.Arenas { Player player = _GetPlayer(guid, bgPlayer.OfflineRemoveTime != 0, "Arena.RemovePlayerAtLeave"); if (player != null) - loserArenaTeam.MemberLost(player, GetArenaMatchmakerRating(GetOtherTeam(bgPlayer.Team))); + loserArenaTeam.MemberLost(player, GetArenaMatchmakerRating(SharedConst.GetOtherTeam(bgPlayer.Team))); else - loserArenaTeam.OfflineMemberLost(guid, GetArenaMatchmakerRating(GetOtherTeam(bgPlayer.Team))); + loserArenaTeam.OfflineMemberLost(guid, GetArenaMatchmakerRating(SharedConst.GetOtherTeam(bgPlayer.Team))); } } } @@ -147,14 +147,14 @@ namespace Game.Arenas // In case of arena draw, follow this logic: // winnerArenaTeam => ALLIANCE, loserArenaTeam => HORDE ArenaTeam winnerArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner == Team.Other ? Team.Alliance : winner)); - ArenaTeam loserArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner == Team.Other ? Team.Horde : GetOtherTeam(winner))); + ArenaTeam loserArenaTeam = Global.ArenaTeamMgr.GetArenaTeamById(GetArenaTeamIdForTeam(winner == Team.Other ? Team.Horde : SharedConst.GetOtherTeam(winner))); if (winnerArenaTeam != null && loserArenaTeam != null && winnerArenaTeam != loserArenaTeam) { // In case of arena draw, follow this logic: // winnerMatchmakerRating => ALLIANCE, loserMatchmakerRating => HORDE loserTeamRating = loserArenaTeam.GetRating(); - loserMatchmakerRating = GetArenaMatchmakerRating(winner == Team.Other ? Team.Horde : GetOtherTeam(winner)); + loserMatchmakerRating = GetArenaMatchmakerRating(winner == Team.Other ? Team.Horde : SharedConst.GetOtherTeam(winner)); winnerTeamRating = winnerArenaTeam.GetRating(); winnerMatchmakerRating = GetArenaMatchmakerRating(winner == Team.Other ? Team.Alliance : winner); @@ -168,7 +168,7 @@ namespace Game.Arenas loserTeamRating, loserChange, loserMatchmakerRating, loserMatchmakerChange); SetArenaMatchmakerRating(winner, (uint)(winnerMatchmakerRating + winnerMatchmakerChange)); - SetArenaMatchmakerRating(GetOtherTeam(winner), (uint)(loserMatchmakerRating + loserMatchmakerChange)); + SetArenaMatchmakerRating(SharedConst.GetOtherTeam(winner), (uint)(loserMatchmakerRating + loserMatchmakerChange)); // bg team that the client expects is different to TeamId // alliance 1, horde 0 @@ -176,7 +176,7 @@ namespace Game.Arenas byte loserTeam = (byte)(winner == Team.Alliance ? PvPTeamId.Horde : PvPTeamId.Alliance); _arenaTeamScores[winnerTeam].Assign(winnerTeamRating, (uint)(winnerTeamRating + winnerChange), winnerMatchmakerRating, GetArenaMatchmakerRating(winner)); - _arenaTeamScores[loserTeam].Assign(loserTeamRating, (uint)(loserTeamRating + loserChange), loserMatchmakerRating, GetArenaMatchmakerRating(GetOtherTeam(winner))); + _arenaTeamScores[loserTeam].Assign(loserTeamRating, (uint)(loserTeamRating + loserChange), loserMatchmakerRating, GetArenaMatchmakerRating(SharedConst.GetOtherTeam(winner))); Log.outDebug(LogFilter.Arena, "Arena match Type: {0} for Team1Id: {1} - Team2Id: {2} ended. WinnerTeamId: {3}. Winner rating: +{4}, Loser rating: {5}", GetArenaType(), GetArenaTeamIdByIndex(BattleGroundTeamId.Alliance), GetArenaTeamIdByIndex(BattleGroundTeamId.Horde), winnerArenaTeam.GetId(), winnerChange, loserChange); diff --git a/Source/Game/Arenas/Zones/BladesEdgeArena.cs b/Source/Game/Arenas/Zones/BladesEdgeArena.cs deleted file mode 100644 index b25a71a22..000000000 --- a/Source/Game/Arenas/Zones/BladesEdgeArena.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Game.BattleGrounds; -using Game.Entities; -using Game.Networking.Packets; -using System; - -namespace Game.Arenas -{ - public class BladesEdgeArena : Arena - { - public BladesEdgeArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - taskScheduler.Update(diff); - } - - public override void StartingEventCloseDoors() - { - for (int i = BladeEdgeObjectTypes.Door1; i <= BladeEdgeObjectTypes.Door4; ++i) - SpawnBGObject(i, BattlegroundConst.RespawnImmediately); - - for (int i = BladeEdgeObjectTypes.Buff1; i <= BladeEdgeObjectTypes.Buff2; ++i) - SpawnBGObject(i, BattlegroundConst.RespawnOneDay); - } - - public override void StartingEventOpenDoors() - { - for (int i = BladeEdgeObjectTypes.Door1; i <= BladeEdgeObjectTypes.Door4; ++i) - DoorOpen(i); - - taskScheduler.Schedule(TimeSpan.FromSeconds(5), task => - { - for (int i = BladeEdgeObjectTypes.Door1; i <= BladeEdgeObjectTypes.Door2; ++i) - DelObject(i); - }); - - for (int i = BladeEdgeObjectTypes.Buff1; i <= BladeEdgeObjectTypes.Buff2; ++i) - SpawnBGObject(i, 60); - } - - public override bool SetupBattleground() - { - bool result = true; - result &= AddObject(BladeEdgeObjectTypes.Door1, BladeEfgeGameObjects.Door1, 6287.277f, 282.1877f, 3.810925f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, BattlegroundConst.RespawnImmediately); - result &= AddObject(BladeEdgeObjectTypes.Door2, BladeEfgeGameObjects.Door2, 6189.546f, 241.7099f, 3.101481f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, BattlegroundConst.RespawnImmediately); - result &= AddObject(BladeEdgeObjectTypes.Door3, BladeEfgeGameObjects.Door3, 6299.116f, 296.5494f, 3.308032f, 0.8813917f, 0, 0, 0.4265689f, 0.9044551f, BattlegroundConst.RespawnImmediately); - result &= AddObject(BladeEdgeObjectTypes.Door4, BladeEfgeGameObjects.Door4, 6177.708f, 227.3481f, 3.604374f, -2.260201f, 0, 0, 0.9044551f, -0.4265689f, BattlegroundConst.RespawnImmediately); - if (!result) - { - Log.outError(LogFilter.Sql, "BatteGroundBE: Failed to spawn door object!"); - return false; - } - - result &= AddObject(BladeEdgeObjectTypes.Buff1, BladeEfgeGameObjects.Buff1, 6249.042f, 275.3239f, 11.22033f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120); - result &= AddObject(BladeEdgeObjectTypes.Buff2, BladeEfgeGameObjects.Buff2, 6228.26f, 249.566f, 11.21812f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120); - if (!result) - { - Log.outError(LogFilter.Sql, "BladesEdgeArena: Failed to spawn buff object!"); - return false; - } - - return true; - } - } - - struct BladeEdgeObjectTypes - { - public const int Door1 = 0; - public const int Door2 = 1; - public const int Door3 = 2; - public const int Door4 = 3; - public const int Buff1 = 4; - public const int Buff2 = 5; - public const int Max = 6; - } - - struct BladeEfgeGameObjects - { - public const uint Door1 = 183971; - public const uint Door2 = 183973; - public const uint Door3 = 183970; - public const uint Door4 = 183972; - public const uint Buff1 = 184663; - public const uint Buff2 = 184664; - } -} diff --git a/Source/Game/Arenas/Zones/DalaranSewers.cs b/Source/Game/Arenas/Zones/DalaranSewers.cs deleted file mode 100644 index d21078030..000000000 --- a/Source/Game/Arenas/Zones/DalaranSewers.cs +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Framework.Dynamic; -using Game.BattleGrounds; -using Game.Entities; -using Game.Networking.Packets; -using System; - -namespace Game.Arenas -{ - class DalaranSewersArena : Arena - { - uint _pipeKnockBackTimer; - uint _pipeKnockBackCount; - - public DalaranSewersArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) - { - _events = new EventMap(); - } - - public override void StartingEventCloseDoors() - { - for (int i = DalaranSewersObjectTypes.Door1; i <= DalaranSewersObjectTypes.Door2; ++i) - SpawnBGObject(i, BattlegroundConst.RespawnImmediately); - } - - public override void StartingEventOpenDoors() - { - for (int i = DalaranSewersObjectTypes.Door1; i <= DalaranSewersObjectTypes.Door2; ++i) - DoorOpen(i); - - for (int i = DalaranSewersObjectTypes.Buff1; i <= DalaranSewersObjectTypes.Buff2; ++i) - SpawnBGObject(i, 60); - - _events.ScheduleEvent(DalaranSewersEvents.WaterfallWarning, DalaranSewersData.WaterfallTimerMin, DalaranSewersData.WaterfallTimerMax); - //_events.ScheduleEvent(DalaranSewersEvents.PipeKnockback, DalaranSewersData.PipeKnockbackFirstDelay); - - _pipeKnockBackCount = 0; - _pipeKnockBackTimer = DalaranSewersData.PipeKnockbackFirstDelay; - - SpawnBGObject(DalaranSewersObjectTypes.Water2, BattlegroundConst.RespawnImmediately); - - DoorOpen(DalaranSewersObjectTypes.Water1); // Turn off collision - DoorOpen(DalaranSewersObjectTypes.Water2); - - // Remove effects of Demonic Circle Summon - foreach (var pair in GetPlayers()) - { - Player player = _GetPlayer(pair, "BattlegroundDS::StartingEventOpenDoors"); - if (player != null) - player.RemoveAurasDueToSpell(DalaranSewersSpells.DemonicCircle); - } - } - - public override bool SetupBattleground() - { - bool result = true; - result &= AddObject(DalaranSewersObjectTypes.Door1, DalaranSewersGameObjects.Door1, 1350.95f, 817.2f, 20.8096f, 3.15f, 0, 0, 0.99627f, 0.0862864f, BattlegroundConst.RespawnImmediately); - result &= AddObject(DalaranSewersObjectTypes.Door2, DalaranSewersGameObjects.Door2, 1232.65f, 764.913f, 20.0729f, 6.3f, 0, 0, 0.0310211f, -0.999519f, BattlegroundConst.RespawnImmediately); - if (!result) - { - Log.outError(LogFilter.Sql, "DalaranSewersArena: Failed to spawn door object!"); - return false; - } - - // buffs - result &= AddObject(DalaranSewersObjectTypes.Buff1, DalaranSewersGameObjects.Buff1, 1291.7f, 813.424f, 7.11472f, 4.64562f, 0, 0, 0.730314f, -0.683111f, 120); - result &= AddObject(DalaranSewersObjectTypes.Buff2, DalaranSewersGameObjects.Buff2, 1291.7f, 768.911f, 7.11472f, 1.55194f, 0, 0, 0.700409f, 0.713742f, 120); - if (!result) - { - Log.outError(LogFilter.Sql, "DalaranSewersArena: Failed to spawn buff object!"); - return false; - } - - result &= AddObject(DalaranSewersObjectTypes.Water1, DalaranSewersGameObjects.Water1, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120); - result &= AddObject(DalaranSewersObjectTypes.Water2, DalaranSewersGameObjects.Water2, 1291.56f, 790.837f, 7.1f, 3.14238f, 0, 0, 0.694215f, -0.719768f, 120); - result &= AddCreature(DalaranSewersData.NpcWaterSpout, DalaranSewersCreatureTypes.WaterfallKnockback, 1292.587f, 790.2205f, 7.19796f, 3.054326f, BattleGroundTeamId.Neutral, BattlegroundConst.RespawnImmediately) != null; - result &= AddCreature(DalaranSewersData.NpcWaterSpout, DalaranSewersCreatureTypes.PipeKnockback1, 1369.977f, 817.2882f, 16.08718f, 3.106686f, BattleGroundTeamId.Neutral, BattlegroundConst.RespawnImmediately) != null; - result &= AddCreature(DalaranSewersData.NpcWaterSpout, DalaranSewersCreatureTypes.PipeKnockback2, 1212.833f, 765.3871f, 16.09484f, 0.0f, BattleGroundTeamId.Neutral, BattlegroundConst.RespawnImmediately) != null; - if (!result) - { - Log.outError(LogFilter.Sql, "DalaranSewersArena: Failed to spawn collision object!"); - return false; - } - - return true; - } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - _events.ExecuteEvents(eventId => - { - switch (eventId) - { - case DalaranSewersEvents.WaterfallWarning: - // Add the water - DoorClose(DalaranSewersObjectTypes.Water2); - _events.ScheduleEvent(DalaranSewersEvents.WaterfallOn, DalaranSewersData.WaterWarningDuration); - break; - case DalaranSewersEvents.WaterfallOn: - // Active collision and start knockback timer - DoorClose(DalaranSewersObjectTypes.Water1); - _events.ScheduleEvent(DalaranSewersEvents.WaterfallOff, DalaranSewersData.WaterfallDuration); - _events.ScheduleEvent(DalaranSewersEvents.WaterfallKnockback, DalaranSewersData.WaterfallKnockbackTimer); - break; - case DalaranSewersEvents.WaterfallOff: - // Remove collision and water - DoorOpen(DalaranSewersObjectTypes.Water1); - DoorOpen(DalaranSewersObjectTypes.Water2); - _events.CancelEvent(DalaranSewersEvents.WaterfallKnockback); - _events.ScheduleEvent(DalaranSewersEvents.WaterfallWarning, DalaranSewersData.WaterfallTimerMin, DalaranSewersData.WaterfallTimerMax); - break; - case DalaranSewersEvents.WaterfallKnockback: - { - // Repeat knockback while the waterfall still active - Creature waterSpout = GetBGCreature(DalaranSewersCreatureTypes.WaterfallKnockback); - if (waterSpout != null) - waterSpout.CastSpell(waterSpout, DalaranSewersSpells.WaterSpout, true); - _events.ScheduleEvent(eventId, DalaranSewersData.WaterfallKnockbackTimer); - } - break; - case DalaranSewersEvents.PipeKnockback: - { - for (uint i = DalaranSewersCreatureTypes.PipeKnockback1; i <= DalaranSewersCreatureTypes.PipeKnockback2; ++i) - { - Creature waterSpout = GetBGCreature(i); - if (waterSpout != null) - waterSpout.CastSpell(waterSpout, DalaranSewersSpells.Flush, true); - } - } - break; - } - }); - - if (_pipeKnockBackCount < DalaranSewersData.PipeKnockbackTotalCount) - { - if (_pipeKnockBackTimer < diff) - { - for (uint i = DalaranSewersCreatureTypes.PipeKnockback1; i <= DalaranSewersCreatureTypes.PipeKnockback2; ++i) - { - Creature waterSpout = GetBGCreature(i); - if (waterSpout != null) - waterSpout.CastSpell(waterSpout, DalaranSewersSpells.Flush, true); - } - - ++_pipeKnockBackCount; - _pipeKnockBackTimer = DalaranSewersData.PipeKnockbackDelay; - } - else - _pipeKnockBackTimer -= diff; - } - } - - public override void SetData(uint dataId, uint value) - { - base.SetData(dataId, value); - if (dataId == DalaranSewersData.PipeKnockbackCount) - _pipeKnockBackCount = value; - } - - public override uint GetData(uint dataId) - { - if (dataId == DalaranSewersData.PipeKnockbackCount) - return _pipeKnockBackCount; - - return base.GetData(dataId); - } - } - - struct DalaranSewersEvents - { - public const int WaterfallWarning = 1; // Water starting to fall, but no LoS Blocking nor movement blocking - public const uint WaterfallOn = 2; // LoS and Movement blocking active - public const uint WaterfallOff = 3; - public const uint WaterfallKnockback = 4; - - public const uint PipeKnockback = 5; - } - - struct DalaranSewersObjectTypes - { - public const int Door1 = 0; - public const int Door2 = 1; - public const int Water1 = 2; // Collision - public const int Water2 = 3; - public const int Buff1 = 4; - public const int Buff2 = 5; - public const int Max = 6; - } - - struct DalaranSewersGameObjects - { - public const uint Door1 = 192642; - public const uint Door2 = 192643; - public const uint Water1 = 194395; // Collision - public const uint Water2 = 191877; - public const uint Buff1 = 184663; - public const uint Buff2 = 184664; - } - - struct DalaranSewersCreatureTypes - { - public const int WaterfallKnockback = 0; - public const int PipeKnockback1 = 1; - public const int PipeKnockback2 = 2; - public const int Max = 3; - } - - struct DalaranSewersData - { - // These values are NOT blizzlike... need the correct data! - public static TimeSpan WaterfallTimerMin = TimeSpan.FromSeconds(30); - public static TimeSpan WaterfallTimerMax = TimeSpan.FromSeconds(60); - public static TimeSpan WaterWarningDuration = TimeSpan.FromSeconds(5); - public static TimeSpan WaterfallDuration = TimeSpan.FromSeconds(30); - public static TimeSpan WaterfallKnockbackTimer = TimeSpan.FromSeconds(1.5); - - public static uint PipeKnockbackFirstDelay = 5000; - public static uint PipeKnockbackDelay = 3000; - public const uint PipeKnockbackTotalCount = 2; - public const uint PipeKnockbackCount = 1; - - public const uint NpcWaterSpout = 28567; - } - - struct DalaranSewersSpells - { - public const uint Flush = 57405; // Visual And Target Selector For The Starting Knockback From The Pipe - public const uint FlushKnockback = 61698; // Knockback Effect For Previous Spell (Triggered, Not Needed To Be Cast) - public const uint WaterSpout = 58873; // Knockback Effect Of The Central Waterfall - - public const uint DemonicCircle = 48018; // Demonic Circle Summon - } -} diff --git a/Source/Game/Arenas/Zones/NagrandArena.cs b/Source/Game/Arenas/Zones/NagrandArena.cs deleted file mode 100644 index d8f8925b4..000000000 --- a/Source/Game/Arenas/Zones/NagrandArena.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Game.BattleGrounds; -using Game.Entities; -using Game.Networking.Packets; -using System; - -namespace Game.Arenas -{ - public class NagrandArena : Arena - { - public NagrandArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - taskScheduler.Update(diff); - } - - public override void StartingEventCloseDoors() - { - for (int i = NagrandArenaObjectTypes.Door1; i <= NagrandArenaObjectTypes.Door4; ++i) - SpawnBGObject(i, BattlegroundConst.RespawnImmediately); - } - - public override void StartingEventOpenDoors() - { - for (int i = NagrandArenaObjectTypes.Door1; i <= NagrandArenaObjectTypes.Door4; ++i) - DoorOpen(i); - - taskScheduler.Schedule(TimeSpan.FromSeconds(5), task => - { - for (int i = NagrandArenaObjectTypes.Door1; i <= NagrandArenaObjectTypes.Door2; ++i) - DelObject(i); - }); - - for (int i = NagrandArenaObjectTypes.Buff1; i <= NagrandArenaObjectTypes.Buff2; ++i) - SpawnBGObject(i, 60); - } - - public override bool SetupBattleground() - { - bool result = true; - result &= AddObject(NagrandArenaObjectTypes.Door1, NagrandArenaObjects.Door1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, BattlegroundConst.RespawnImmediately); - result &= AddObject(NagrandArenaObjectTypes.Door2, NagrandArenaObjects.Door2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, BattlegroundConst.RespawnImmediately); - result &= AddObject(NagrandArenaObjectTypes.Door3, NagrandArenaObjects.Door3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, BattlegroundConst.RespawnImmediately); - result &= AddObject(NagrandArenaObjectTypes.Door4, NagrandArenaObjects.Door4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, BattlegroundConst.RespawnImmediately); - if (!result) - { - Log.outError(LogFilter.Sql, "NagrandArena: Failed to spawn door object!"); - return false; - } - - result &= AddObject(NagrandArenaObjectTypes.Buff1, NagrandArenaObjects.Buff1, 4009.189941f, 2895.250000f, 13.052700f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120); - result &= AddObject(NagrandArenaObjectTypes.Buff2, NagrandArenaObjects.Buff2, 4103.330078f, 2946.350098f, 13.051300f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120); - if (!result) - { - Log.outError(LogFilter.Sql, "NagrandArena: Failed to spawn buff object!"); - return false; - } - - return true; - } - } - - struct NagrandArenaObjectTypes - { - public const int Door1 = 0; - public const int Door2 = 1; - public const int Door3 = 2; - public const int Door4 = 3; - public const int Buff1 = 4; - public const int Buff2 = 5; - public const int Max = 6; - } - - struct NagrandArenaObjects - { - public const uint Door1 = 183978; - public const uint Door2 = 183980; - public const uint Door3 = 183977; - public const uint Door4 = 183979; - public const uint Buff1 = 184663; - public const uint Buff2 = 184664; - } -} diff --git a/Source/Game/Arenas/Zones/RingofValor.cs b/Source/Game/Arenas/Zones/RingofValor.cs deleted file mode 100644 index 0e10ec047..000000000 --- a/Source/Game/Arenas/Zones/RingofValor.cs +++ /dev/null @@ -1,225 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Framework.Dynamic; -using Game.BattleGrounds; -using Game.Entities; -using Game.Networking.Packets; -using System; - -namespace Game.Arenas -{ - class RingofValorArena : Arena - { - public RingofValorArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) - { - _events = new EventMap(); - } - - public override bool SetupBattleground() - { - bool result = true; - result &= AddObject(RingofValorObjectTypes.Elevator1, RingofValorGameObjects.Elevator1, 763.536377f, -294.535767f, 0.505383f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Elevator2, RingofValorGameObjects.Elevator2, 763.506348f, -273.873352f, 0.505383f, 0.000000f, 0, 0, 0, 0); - if (!result) - { - Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn elevator object!"); - return false; - } - - result &= AddObject(RingofValorObjectTypes.Buff1, RingofValorGameObjects.Buff1, 735.551819f, -284.794678f, 28.276682f, 0.034906f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Buff2, RingofValorGameObjects.Buff2, 791.224487f, -284.794464f, 28.276682f, 2.600535f, 0, 0, 0, 0); - if (!result) - { - Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn buff object!"); - return false; - } - - result &= AddObject(RingofValorObjectTypes.Fire1, RingofValorGameObjects.Fire1, 743.543457f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Fire2, RingofValorGameObjects.Fire2, 782.971802f, -283.799469f, 28.286655f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Firedoor1, RingofValorGameObjects.Firedoor1, 743.711060f, -284.099609f, 27.542587f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Firedoor2, RingofValorGameObjects.Firedoor2, 783.221252f, -284.133362f, 27.535686f, 0.000000f, 0, 0, 0, 0); - if (!result) - { - Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn fire/firedoor object!"); - return false; - } - - result &= AddObject(RingofValorObjectTypes.Gear1, RingofValorGameObjects.Gear1, 763.664551f, -261.872986f, 26.686588f, 0.000000f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Gear2, RingofValorGameObjects.Gear2, 763.578979f, -306.146149f, 26.665222f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Pulley1, RingofValorGameObjects.Pulley1, 700.722290f, -283.990662f, 39.517582f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Pulley2, RingofValorGameObjects.Pulley2, 826.303833f, -283.996429f, 39.517582f, 0.000000f, 0, 0, 0, 0); - if (!result) - { - Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn gear/pully object!"); - return false; - } - - result &= AddObject(RingofValorObjectTypes.Pilar1, RingofValorGameObjects.Pilar1, 763.632385f, -306.162384f, 25.909504f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Pilar2, RingofValorGameObjects.Pilar2, 723.644287f, -284.493256f, 24.648525f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Pilar3, RingofValorGameObjects.Pilar3, 763.611145f, -261.856750f, 25.909504f, 0.000000f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.Pilar4, RingofValorGameObjects.Pilar4, 802.211609f, -284.493256f, 24.648525f, 0.000000f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.PilarCollision1, RingofValorGameObjects.PilarCollision1, 763.632385f, -306.162384f, 30.639660f, 3.141593f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.PilarCollision2, RingofValorGameObjects.PilarCollision2, 723.644287f, -284.493256f, 32.382710f, 0.000000f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.PilarCollision3, RingofValorGameObjects.PilarCollision3, 763.611145f, -261.856750f, 30.639660f, 0.000000f, 0, 0, 0, 0); - result &= AddObject(RingofValorObjectTypes.PilarCollision4, RingofValorGameObjects.PilarCollision4, 802.211609f, -284.493256f, 32.382710f, 3.141593f, 0, 0, 0, 0); - if (!result) - { - Log.outError(LogFilter.Sql, "RingofValorArena: Failed to spawn pilar object!"); - return false; - } - - return true; - } - - public override void StartingEventOpenDoors() - { - // Buff respawn - SpawnBGObject(RingofValorObjectTypes.Buff1, 90); - SpawnBGObject(RingofValorObjectTypes.Buff2, 90); - // Elevators - DoorOpen(RingofValorObjectTypes.Elevator1); - DoorOpen(RingofValorObjectTypes.Elevator2); - - _events.ScheduleEvent(RingofValorEvents.OpenFences, TimeSpan.FromSeconds(20)); - - // Should be false at first, TogglePillarCollision will do it. - TogglePillarCollision(true); - } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - _events.Update(diff); - - _events.ExecuteEvents(eventId => - { - switch (eventId) - { - case RingofValorEvents.OpenFences: - // Open fire (only at game start) - for (byte i = RingofValorObjectTypes.Fire1; i <= RingofValorObjectTypes.Firedoor2; ++i) - DoorOpen(i); - _events.ScheduleEvent(RingofValorEvents.CloseFire, TimeSpan.FromSeconds(5)); - break; - case RingofValorEvents.CloseFire: - for (byte i = RingofValorObjectTypes.Fire1; i <= RingofValorObjectTypes.Firedoor2; ++i) - DoorClose(i); - // Fire got closed after five seconds, leaves twenty seconds before toggling pillars - _events.ScheduleEvent(RingofValorEvents.SwitchPillars, TimeSpan.FromSeconds(20)); - break; - case RingofValorEvents.SwitchPillars: - TogglePillarCollision(true); - _events.Repeat(TimeSpan.FromSeconds(25)); - break; - } - }); - } - - void TogglePillarCollision(bool enable) - { - // Toggle visual pillars, pulley, gear, and collision based on previous state - for (int i = RingofValorObjectTypes.Pilar1; i <= RingofValorObjectTypes.Gear2; ++i) - { - if (enable) - DoorOpen(i); - else - DoorClose(i); - } - - for (byte i = RingofValorObjectTypes.Pilar2; i <= RingofValorObjectTypes.Pulley2; ++i) - { - if (enable) - DoorClose(i); - else - DoorOpen(i); - } - - for (byte i = RingofValorObjectTypes.Pilar1; i <= RingofValorObjectTypes.PilarCollision4; ++i) - { - GameObject go = GetBGObject(i); - if (go != null) - { - if (i >= RingofValorObjectTypes.PilarCollision1) - { - GameObjectState state = ((go.GetGoInfo().Door.startOpen != 0) == enable) ? GameObjectState.Active : GameObjectState.Ready; - go.SetGoState(state); - } - - foreach (var guid in GetPlayers().Keys) - { - Player player = Global.ObjAccessor.FindPlayer(guid); - if (player != null) - go.SendUpdateToPlayer(player); - } - } - } - } - } - - struct RingofValorEvents - { - public const int OpenFences = 0; - public const int SwitchPillars = 1; - public const int CloseFire = 2; - } - - struct RingofValorObjectTypes - { - public const int Buff1 = 1; - public const int Buff2 = 2; - public const int Fire1 = 3; - public const int Fire2 = 4; - public const int Firedoor1 = 5; - public const int Firedoor2 = 6; - - public const int Pilar1 = 7; - public const int Pilar3 = 8; - public const int Gear1 = 9; - public const int Gear2 = 10; - - public const int Pilar2 = 11; - public const int Pilar4 = 12; - public const int Pulley1 = 13; - public const int Pulley2 = 14; - - public const int PilarCollision1 = 15; - public const int PilarCollision2 = 16; - public const int PilarCollision3 = 17; - public const int PilarCollision4 = 18; - - public const int Elevator1 = 19; - public const int Elevator2= 20; - public const int Max = 21; - } - - struct RingofValorGameObjects - { - public const uint Buff1 = 184663; - public const uint Buff2 = 184664; - public const uint Fire1 = 192704; - public const uint Fire2 = 192705; - - public const uint Firedoor2 = 192387; - public const uint Firedoor1 = 192388; - public const uint Pulley1 = 192389; - public const uint Pulley2 = 192390; - public const uint Gear1 = 192393; - public const uint Gear2 = 192394; - public const uint Elevator1 = 194582; - public const uint Elevator2 = 194586; - - public const uint PilarCollision1 = 194580; // Axe - public const uint PilarCollision2 = 194579; // Arena - public const uint PilarCollision3 = 194581; // Lightning - public const uint PilarCollision4 = 194578; // Ivory - - public const uint Pilar1 = 194583; // Axe - public const uint Pilar2 = 194584; // Arena - public const uint Pilar3 = 194585; // Lightning - public const uint Pilar4 = 194587; // Ivory - } -} diff --git a/Source/Game/Arenas/Zones/RuinsofLordaeron.cs b/Source/Game/Arenas/Zones/RuinsofLordaeron.cs deleted file mode 100644 index beb1ba2cf..000000000 --- a/Source/Game/Arenas/Zones/RuinsofLordaeron.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Game.BattleGrounds; -using Game.Entities; -using Game.Networking.Packets; -using System; - -namespace Game.Arenas -{ - class RuinsofLordaeronArena : Arena - { - public RuinsofLordaeronArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - taskScheduler.Update(diff); - } - - public override bool SetupBattleground() - { - bool result = true; - result &= AddObject(RuinsofLordaeronObjectTypes.Door1, RuinsofLordaeronObjectTypes.Door1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f); - result &= AddObject(RuinsofLordaeronObjectTypes.Door2, RuinsofLordaeronObjectTypes.Door2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f); - if (!result) - { - Log.outError(LogFilter.Sql, "RuinsofLordaeronArena: Failed to spawn door object!"); - return false; - } - - result &= AddObject(RuinsofLordaeronObjectTypes.Buff1, RuinsofLordaeronObjectTypes.Buff1, 1328.719971f, 1632.719971f, 36.730400f, -1.448624f, 0, 0, 0.6626201f, -0.7489557f, 120); - result &= AddObject(RuinsofLordaeronObjectTypes.Buff2, RuinsofLordaeronObjectTypes.Buff2, 1243.300049f, 1699.170044f, 34.872601f, -0.06981307f, 0, 0, 0.03489945f, -0.9993908f, 120); - if (!result) - { - Log.outError(LogFilter.Sql, "RuinsofLordaeronArena: Failed to spawn buff object!"); - return false; - } - - return true; - } - - public override void StartingEventCloseDoors() - { - for (int i = RuinsofLordaeronObjectTypes.Door1; i <= RuinsofLordaeronObjectTypes.Door2; ++i) - SpawnBGObject(i, BattlegroundConst.RespawnImmediately); - } - - public override void StartingEventOpenDoors() - { - for (int i = RuinsofLordaeronObjectTypes.Door1; i <= RuinsofLordaeronObjectTypes.Door2; ++i) - DoorOpen(i); - - taskScheduler.Schedule(TimeSpan.FromSeconds(5), task => - { - for (int i = RuinsofLordaeronObjectTypes.Door1; i <= RuinsofLordaeronObjectTypes.Door2; ++i) - DelObject(i); - }); - - for (int i = RuinsofLordaeronObjectTypes.Buff1; i <= RuinsofLordaeronObjectTypes.Buff2; ++i) - SpawnBGObject(i, 60); - } - } - - struct RuinsofLordaeronObjectTypes - { - public const int Door1 = 0; - public const int Door2 = 1; - public const int Buff1 = 2; - public const int Buff2 = 3; - public const int Max = 4; - } - - struct RuinsofLordaeronGameObjects - { - public const uint Door1 = 185918; - public const uint Door2 = 185917; - public const uint Buff1 = 184663; - public const uint Buff2 = 184664; - } -} diff --git a/Source/Game/Arenas/Zones/TigersPeak.cs b/Source/Game/Arenas/Zones/TigersPeak.cs deleted file mode 100644 index bf458f8bd..000000000 --- a/Source/Game/Arenas/Zones/TigersPeak.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.Arenas -{ - class TigersPeak - { - } -} diff --git a/Source/Game/Arenas/Zones/TolvironArena.cs b/Source/Game/Arenas/Zones/TolvironArena.cs deleted file mode 100644 index 6b9cd0dae..000000000 --- a/Source/Game/Arenas/Zones/TolvironArena.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.Arenas -{ - class TolvironArena - { - } -} diff --git a/Source/Game/BattleFields/BattleField.cs b/Source/Game/BattleFields/BattleField.cs index ed7b81870..06daee22c 100644 --- a/Source/Game/BattleFields/BattleField.cs +++ b/Source/Game/BattleFields/BattleField.cs @@ -174,7 +174,7 @@ namespace Game.BattleFields if (m_PlayersInQueue[player.GetTeamId()].Contains(player.GetGUID())) return; - if (m_PlayersInQueue[player.GetTeamId()].Count <= m_MinPlayer || m_PlayersInQueue[GetOtherTeam(player.GetTeamId())].Count >= m_MinPlayer) + if (m_PlayersInQueue[player.GetTeamId()].Count <= m_MinPlayer || m_PlayersInQueue[SharedConst.GetOtherTeam(player.GetTeamId())].Count >= m_MinPlayer) PlayerAcceptInviteToQueue(player); } @@ -705,7 +705,6 @@ namespace Game.BattleFields // Battlefield - generic methods public uint GetDefenderTeam() { return m_DefenderTeam; } public uint GetAttackerTeam() { return 1 - m_DefenderTeam; } - public int GetOtherTeam(int teamIndex) { return (teamIndex == BattleGroundTeamId.Horde ? BattleGroundTeamId.Alliance : BattleGroundTeamId.Horde); } void SetDefenderTeam(uint team) { m_DefenderTeam = team; } // Called on start diff --git a/Source/Game/BattleGrounds/BattleGround.cs b/Source/Game/BattleGrounds/BattleGround.cs index ddff1b7d7..b9b757e20 100644 --- a/Source/Game/BattleGrounds/BattleGround.cs +++ b/Source/Game/BattleGrounds/BattleGround.cs @@ -40,15 +40,8 @@ namespace Game.BattleGrounds public virtual void Dispose() { - // remove objects and creatures - // (this is done automatically in mapmanager update, when the instance is reset after the reset time) - for (uint i = 0; i < BgCreatures.Length; ++i) - DelCreature(i); - - for (var i = 0; i < BgObjects.Length; ++i) - DelObject(i); - Global.BattlegroundMgr.RemoveBattleground(GetTypeID(), GetInstanceID()); + // unload map if (m_Map != null) { @@ -207,7 +200,7 @@ namespace Game.BattleGrounds } } - public virtual Team GetPrematureWinner() + public Team GetPrematureWinner() { Team winner = Team.Other; if (GetPlayersCountByTeam(Team.Alliance) >= GetMinPlayersPerTeam()) @@ -286,19 +279,12 @@ namespace Game.BattleGrounds return; } - // Setup here, only when at least one player has ported to the map - if (!SetupBattleground()) - { - EndNow(); - return; - } - _preparationStartTime = GameTime.GetGameTime(); foreach (Group group in m_BgRaids) if (group != null) group.StartCountdown(CountdownTimerType.Pvp, TimeSpan.FromSeconds((int)StartDelayTimes[BattlegroundConst.EventIdFirst] / 1000), _preparationStartTime); - StartingEventCloseDoors(); + GetBgMap().GetBattlegroundScript().OnPrepareStage1(); SetStartDelayTime(StartDelayTimes[BattlegroundConst.EventIdFirst]); // First start warning - 2 or 1 Minute if (StartMessageIds[BattlegroundConst.EventIdFirst] != 0) @@ -308,6 +294,7 @@ namespace Game.BattleGrounds else if (GetStartDelayTime() <= (int)StartDelayTimes[BattlegroundConst.EventIdSecond] && !m_Events.HasAnyFlag(BattlegroundEventFlags.Event2)) { m_Events |= BattlegroundEventFlags.Event2; + GetBgMap().GetBattlegroundScript().OnPrepareStage2(); if (StartMessageIds[BattlegroundConst.EventIdSecond] != 0) SendBroadcastText(StartMessageIds[BattlegroundConst.EventIdSecond], ChatMsg.BgSystemNeutral); } @@ -315,6 +302,7 @@ namespace Game.BattleGrounds else if (GetStartDelayTime() <= (int)StartDelayTimes[BattlegroundConst.EventIdThird] && !m_Events.HasAnyFlag(BattlegroundEventFlags.Event3)) { m_Events |= BattlegroundEventFlags.Event3; + GetBgMap().GetBattlegroundScript().OnPrepareStage3(); if (StartMessageIds[BattlegroundConst.EventIdThird] != 0) SendBroadcastText(StartMessageIds[BattlegroundConst.EventIdThird], ChatMsg.BgSystemNeutral); } @@ -323,7 +311,7 @@ namespace Game.BattleGrounds { m_Events |= BattlegroundEventFlags.Event4; - StartingEventOpenDoors(); + GetBgMap().GetBattlegroundScript().OnStart(); if (StartMessageIds[BattlegroundConst.EventIdFourth] != 0) SendBroadcastText(StartMessageIds[BattlegroundConst.EventIdFourth], ChatMsg.RaidBossEmote); @@ -740,6 +728,8 @@ namespace Game.BattleGrounds player.SendPacket(pvpMatchComplete); player.UpdateCriteria(CriteriaType.ParticipateInBattleground, player.GetMapId()); + + GetBgMap().GetBattlegroundScript().OnEnd(winner); } } @@ -1027,6 +1017,8 @@ namespace Game.BattleGrounds // setup BG group membership PlayerAddedToBGCheckIfBGIsRunning(player); AddOrSetPlayerToCorrectBgGroup(player, team); + + GetBgMap().GetBattlegroundScript().OnPlayerJoined(player, isInBattleground); } // this method adds player to his team's bg group, or sets his correct group if player is already in bg group @@ -1104,8 +1096,8 @@ namespace Game.BattleGrounds // 1 player is logging out, if it is the last alive, then end arena! if (IsArena() && player.IsAlive()) - if (GetAlivePlayersCountByTeam(player.GetBGTeam()) <= 1 && GetPlayersCountByTeam(GetOtherTeam(player.GetBGTeam())) != 0) - EndBattleground(GetOtherTeam(player.GetBGTeam())); + if (GetAlivePlayersCountByTeam(player.GetBGTeam()) <= 1 && GetPlayersCountByTeam(SharedConst.GetOtherTeam(player.GetBGTeam())) != 0) + EndBattleground(SharedConst.GetOtherTeam(player.GetBGTeam())); } } @@ -1241,7 +1233,7 @@ namespace Game.BattleGrounds return PlayerScores.LookupByKey(player.GetGUID()); } - public virtual bool UpdatePlayerScore(Player player, ScoreType type, uint value, bool doAddHonor = true) + public bool UpdatePlayerScore(Player player, ScoreType type, uint value, bool doAddHonor = true) { var bgScore = PlayerScores.LookupByKey(player.GetGUID()); if (bgScore == null) // player not found... @@ -1262,99 +1254,6 @@ namespace Game.BattleGrounds score.UpdatePvpStat(pvpStatId, value); } - public bool AddObject(int type, uint entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint respawnTime = 0, GameObjectState goState = GameObjectState.Ready) - { - Map map = FindBgMap(); - if (map == null) - return false; - - Quaternion rotation = new(rotation0, rotation1, rotation2, rotation3); - // Temporally add safety check for bad spawns and send log (object rotations need to be rechecked in sniff) - if (rotation0 == 0 && rotation1 == 0 && rotation2 == 0 && rotation3 == 0) - { - Log.outDebug(LogFilter.Battleground, $"Battleground.AddObject: gameoobject [entry: {entry}, object type: {type}] for BG (map: {GetMapId()}) has zeroed rotation fields, " + - "orientation used temporally, but please fix the spawn"); - - rotation = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(o, 0.0f, 0.0f)); - } - - // Must be created this way, adding to godatamap would add it to the base map of the instance - // and when loading it (in go.LoadFromDB()), a new guid would be assigned to the object, and a new object would be created - // So we must create it specific for this instance - GameObject go = GameObject.CreateGameObject(entry, GetBgMap(), new Position(x, y, z, o), rotation, 255, goState); - if (go == null) - { - Log.outError(LogFilter.Battleground, $"Battleground.AddObject: cannot create gameobject (entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - return false; - } - - // Add to world, so it can be later looked up from HashMapHolder - if (!map.AddToMap(go)) - return false; - - BgObjects[type] = go.GetGUID(); - return true; - } - - public bool AddObject(int type, uint entry, Position pos, float rotation0, float rotation1, float rotation2, float rotation3, uint respawnTime = 0, GameObjectState goState = GameObjectState.Ready) - { - return AddObject(type, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), rotation0, rotation1, rotation2, rotation3, respawnTime, goState); - } - - // Some doors aren't despawned so we cannot handle their closing in gameobject.update() - // It would be nice to correctly implement GO_ACTIVATED state and open/close doors in gameobject code - public void DoorClose(int type) - { - GameObject obj = GetBgMap().GetGameObject(BgObjects[type]); - if (obj != null) - { - // If doors are open, close it - if (obj.GetLootState() == LootState.Activated && obj.GetGoState() != GameObjectState.Ready) - { - obj.SetLootState(LootState.Ready); - obj.SetGoState(GameObjectState.Ready); - } - } - else - Log.outError(LogFilter.Battleground, $"Battleground.DoorClose: door gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - } - - public void DoorOpen(int type) - { - GameObject obj = GetBgMap().GetGameObject(BgObjects[type]); - if (obj != null) - { - obj.SetLootState(LootState.Activated); - obj.SetGoState(GameObjectState.Active); - } - else - Log.outError(LogFilter.Battleground, $"Battleground.DoorOpen: door gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - } - - public GameObject GetBGObject(int type) - { - if (BgObjects[type].IsEmpty()) - return null; - - GameObject obj = GetBgMap().GetGameObject(BgObjects[type]); - if (obj == null) - Log.outError(LogFilter.Battleground, $"Battleground.GetBGObject: gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - - return obj; - } - - public Creature GetBGCreature(uint type) - { - if (BgCreatures[type].IsEmpty()) - return null; - - Creature creature = GetBgMap().GetCreature(BgCreatures[type]); - if (creature == null) - Log.outError(LogFilter.Battleground, $"Battleground.GetBGCreature: creature (type: {type}, {BgCreatures[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - - return creature; - } - public uint GetMapId() { return (uint)_battlegroundTemplate.BattlemasterEntry.MapId[0]; @@ -1364,168 +1263,11 @@ namespace Game.BattleGrounds { m_Map = map; if (map != null) - { _pvpStatIds = Global.DB2Mgr.GetPVPStatIDsForMap(map.GetId()); - OnMapSet(map); - } else _pvpStatIds = null; } - public void SpawnBGObject(int type, uint respawntime) - { - Map map = FindBgMap(); - if (map != null) - { - GameObject obj = map.GetGameObject(BgObjects[type]); - if (obj != null) - { - if (respawntime != 0) - { - obj.SetLootState(LootState.JustDeactivated); - { - GameObjectOverride goOverride = obj.GetGameObjectOverride(); - if (goOverride != null) - if (goOverride.Flags.HasFlag(GameObjectFlags.NoDespawn)) - { - // This function should be called in GameObject::Update() but in case of - // GO_FLAG_NODESPAWN flag the function is never called, so we call it here - obj.SendGameObjectDespawn(); - } - } - } - else if (obj.GetLootState() == LootState.JustDeactivated) - { - // Change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again - obj.SetLootState(LootState.Ready); - } - obj.SetRespawnTime((int)respawntime); - map.AddToMap(obj); - } - } - } - - public virtual Creature AddCreature(uint entry, uint type, float x, float y, float z, float o, int teamIndex = BattleGroundTeamId.Neutral, uint respawntime = 0, Transport transport = null) - { - Map map = FindBgMap(); - if (map == null) - return null; - - if (Global.ObjectMgr.GetCreatureTemplate(entry) == null) - { - Log.outError(LogFilter.Battleground, $"Battleground.AddCreature: creature template (entry: {entry}) does not exist for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - return null; - } - - - if (transport != null) - { - Creature transCreature = transport.SummonPassenger(entry, new Position(x, y, z, o), TempSummonType.ManualDespawn); - if (transCreature != null) - { - BgCreatures[type] = transCreature.GetGUID(); - return transCreature; - } - - return null; - } - - Position pos = new(x, y, z, o); - - Creature creature = Creature.CreateCreature(entry, map, pos); - if (creature == null) - { - Log.outError(LogFilter.Battleground, $"Battleground.AddCreature: cannot create creature (entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - return null; - } - - creature.SetHomePosition(pos); - - if (!map.AddToMap(creature)) - return null; - - BgCreatures[type] = creature.GetGUID(); - - if (respawntime != 0) - creature.SetRespawnDelay(respawntime); - - return creature; - } - - public Creature AddCreature(uint entry, uint type, Position pos, int teamIndex = BattleGroundTeamId.Neutral, uint respawntime = 0, Transport transport = null) - { - return AddCreature(entry, type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex, respawntime, transport); - } - - public bool DelCreature(uint type) - { - if (BgCreatures[type].IsEmpty()) - return true; - - Creature creature = GetBgMap().GetCreature(BgCreatures[type]); - if (creature != null) - { - creature.AddObjectToRemoveList(); - BgCreatures[type].Clear(); - return true; - } - - Log.outError(LogFilter.Battleground, $"Battleground.DelCreature: creature (type: {type}, {BgCreatures[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - BgCreatures[type].Clear(); - return false; - } - - public bool DelObject(int type) - { - if (BgObjects[type].IsEmpty()) - return true; - - GameObject obj = GetBgMap().GetGameObject(BgObjects[type]); - if (obj != null) - { - obj.SetRespawnTime(0); // not save respawn time - obj.Delete(); - BgObjects[type].Clear(); - return true; - } - Log.outError(LogFilter.Battleground, $"Battleground.DelObject: gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - BgObjects[type].Clear(); - return false; - } - - bool RemoveObjectFromWorld(uint type) - { - if (BgObjects[type].IsEmpty()) - return true; - - GameObject obj = GetBgMap().GetGameObject(BgObjects[type]); - if (obj != null) - { - obj.RemoveFromWorld(); - BgObjects[type].Clear(); - return true; - } - Log.outInfo(LogFilter.Battleground, $"Battleground::RemoveObjectFromWorld: gameobject (type: {type}, {BgObjects[type]}) not found for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - return false; - } - - public bool AddSpiritGuide(uint type, float x, float y, float z, float o, int teamIndex) - { - uint entry = (uint)(teamIndex == BattleGroundTeamId.Alliance ? BattlegroundCreatures.A_SpiritGuide : BattlegroundCreatures.H_SpiritGuide); - - if (AddCreature(entry, type, x, y, z, o) != null) - return true; - - Log.outError(LogFilter.Battleground, $"Battleground.AddSpiritGuide: cannot create spirit guide (type: {type}, entry: {entry}) for BG (map: {GetMapId()}, instance id: {m_InstanceID})!"); - EndNow(); - return false; - } - - public bool AddSpiritGuide(uint type, Position pos, int teamIndex = BattleGroundTeamId.Neutral) - { - return AddSpiritGuide(type, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teamIndex); - } - public void SendMessageToAll(CypherStrings entry, ChatMsg msgType, Player source = null) { if (entry == 0) @@ -1598,9 +1340,18 @@ namespace Game.BattleGrounds victim.SetUnitFlag(UnitFlags.Skinnable); RewardXPAtKill(killer, victim); } + + BattlegroundScript script = GetBgMap().GetBattlegroundScript(); + if (script != null) + script.OnPlayerKilled(victim, killer); } - public virtual void HandleKillUnit(Creature creature, Unit killer) { } + public virtual void HandleKillUnit(Creature victim, Unit killer) + { + BattlegroundScript script = GetBgMap().GetBattlegroundScript(); + if (script != null) + script.OnUnitKilled(victim, killer); + } // Return the player's team based on Battlegroundplayer info // Used in same faction arena matches mainly @@ -1612,11 +1363,6 @@ namespace Game.BattleGrounds return Team.Other; } - public Team GetOtherTeam(Team team) - { - return team != 0 ? ((team == Team.Alliance) ? Team.Horde : Team.Alliance) : Team.Other; - } - public bool IsPlayerInBattleground(ObjectGuid guid) { return m_Players.ContainsKey(guid); @@ -1658,15 +1404,6 @@ namespace Game.BattleGrounds return count; } - public int GetObjectType(ObjectGuid guid) - { - for (int i = 0; i < BgObjects.Length; ++i) - if (BgObjects[i] == guid) - return i; - Log.outError(LogFilter.Battleground, $"Battleground.GetObjectType: player used gameobject ({guid}) which is not in internal data for BG (map: {GetMapId()}, instance id: {m_InstanceID}), cheating?"); - return -1; - } - public void SetBgRaid(Team team, Group bg_raid) { Group old_raid = m_BgRaids[GetTeamIndexByTeamId(team)]; @@ -1677,23 +1414,6 @@ namespace Game.BattleGrounds m_BgRaids[GetTeamIndexByTeamId(team)] = bg_raid; } - public virtual WorldSafeLocsEntry GetClosestGraveyard(Player player) - { - return Global.ObjectMgr.GetClosestGraveyard(player, GetPlayerTeam(player.GetGUID()), player); - } - - public override void TriggerGameEvent(uint gameEventId, WorldObject source = null, WorldObject target = null) - { - ProcessEvent(target, gameEventId, source); - GameEvents.TriggerForMap(gameEventId, GetBgMap(), source, target); - foreach (var guid in GetPlayers().Keys) - { - Player player = Global.ObjAccessor.FindPlayer(guid); - if (player != null) - GameEvents.TriggerForPlayer(gameEventId, player); - } - } - public void SetBracket(PvpDifficultyRecord bracketEntry) { _pvpDifficultyEntry = bracketEntry; @@ -1714,17 +1434,6 @@ namespace Game.BattleGrounds return 0; } - public virtual void HandleAreaTrigger(Player player, uint trigger, bool entered) - { - Log.outDebug(LogFilter.Battleground, "Unhandled AreaTrigger {0} in Battleground {1}. Player coords (x: {2}, y: {3}, z: {4})", - trigger, player.GetMapId(), player.GetPositionX(), player.GetPositionY(), player.GetPositionZ()); - } - - public virtual bool SetupBattleground() - { - return true; - } - public string GetName() { return _battlegroundTemplate.BattlemasterEntry.Name[Global.WorldMgr.GetDefaultDbcLocale()]; @@ -1801,13 +1510,9 @@ namespace Game.BattleGrounds return m_Players.LookupByKey(playerGuid); } - // Called when valid BattlegroundMap is assigned to the battleground - public virtual void OnMapSet(BattlegroundMap map) { } - - public virtual void StartingEventCloseDoors() { } - public virtual void StartingEventOpenDoors() { } - - public virtual void DestroyGate(Player player, GameObject go) { } + public void AddPoint(Team team, uint points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] += points; } + public void SetTeamPoint(Team team, uint points = 0) { m_TeamScores[GetTeamIndexByTeamId(team)] = points; } + void RemovePoint(Team team, uint points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] -= points; } public uint GetInstanceID() { return m_InstanceID; } public BattlegroundStatus GetStatus() { return m_Status; } @@ -1878,14 +1583,6 @@ namespace Game.BattleGrounds public void SetArenaMatchmakerRating(Team team, uint MMR) { m_ArenaTeamMMR[GetTeamIndexByTeamId(team)] = MMR; } public uint GetArenaMatchmakerRating(Team team) { return m_ArenaTeamMMR[GetTeamIndexByTeamId(team)]; } - // Battleground events - public virtual void EventPlayerDroppedFlag(Player player) { } - public virtual void EventPlayerClickedOnFlag(Player player, GameObject target_obj) { } - - public override void ProcessEvent(WorldObject obj, uint eventId, WorldObject invoker = null) { } - - public virtual void HandlePlayerResurrect(Player player) { } - public virtual WorldSafeLocsEntry GetExploitTeleportLocation(Team team) { return null; } public virtual bool HandlePlayerUnderMap(Player player) { return false; } @@ -1895,12 +1592,6 @@ namespace Game.BattleGrounds bool CanAwardArenaPoints() { return GetMinLevel() >= 71; } - public virtual ObjectGuid GetFlagPickerGUID(int teamIndex = -1) { return ObjectGuid.Empty; } - public virtual void SetDroppedFlagGUID(ObjectGuid guid, int teamIndex = -1) { } - public virtual void HandleQuestComplete(uint questid, Player player) { } - public virtual bool CanActivateGO(int entry, uint team) { return true; } - public virtual bool IsSpellAllowed(uint spellId, Player player) { return true; } - public virtual void RemovePlayer(Player player, ObjectGuid guid, Team team) { } public virtual bool PreUpdateImpl(uint diff) { return true; } @@ -1930,9 +1621,6 @@ namespace Game.BattleGrounds public uint[] m_TeamScores = new uint[SharedConst.PvpTeamsCount]; - protected ObjectGuid[] BgObjects;// = new Dictionary(); - protected ObjectGuid[] BgCreatures;// = new Dictionary(); - public uint[] Buff_Entries = { BattlegroundConst.SpeedBuff, BattlegroundConst.RegenBuff, BattlegroundConst.BerserkerBuff }; // Battleground diff --git a/Source/Game/BattleGrounds/BattleGroundManager.cs b/Source/Game/BattleGrounds/BattleGroundManager.cs index 0e01c5aca..85ad2db4c 100644 --- a/Source/Game/BattleGrounds/BattleGroundManager.cs +++ b/Source/Game/BattleGrounds/BattleGroundManager.cs @@ -3,13 +3,7 @@ using Framework.Constants; using Framework.Database; -using Game.BattleGrounds.Zones; -using Game.BattleGrounds.Zones.AlteracValley; -using Game.BattleGrounds.Zones.ArathisBasin; -using Game.BattleGrounds.Zones.EyeofStorm; -using Game.BattleGrounds.Zones.IsleOfConquest; -using Game.BattleGrounds.Zones.StrandOfAncients; -using Game.BattleGrounds.Zones.WarsongGluch; +using Game.Arenas; using Game.DataStorage; using Game.Entities; using Game.Networking.Packets; @@ -201,6 +195,60 @@ namespace Game.BattleGrounds return null; } + public void LoadBattlegroundScriptTemplate() + { + uint oldMSTime = Time.GetMSTime(); + + // 0 1 2 + SQLResult result = DB.World.Query("SELECT MapId, BattlemasterListId, ScriptName FROM battleground_scripts"); + if (result.IsEmpty()) + { + Log.outInfo(LogFilter.ServerLoading, "Loaded 0 battleground scripts. DB table `battleground_scripts` is empty!"); + return; + } + + uint count = 0; + do + { + uint mapID = result.Read(0); + + var mapEntry = CliDB.MapStorage.LookupByKey(mapID); + if (mapEntry == null || !mapEntry.IsBattlegroundOrArena()) + { + Log.outError(LogFilter.Sql, $"BattlegroundMgr::LoadBattlegroundScriptTemplate: bad mapid {mapID}! Map doesn't exist or is not a battleground/arena!"); + continue; + } + + BattlegroundTypeId bgTypeId = (BattlegroundTypeId)result.Read(1); + if (bgTypeId != BattlegroundTypeId.None && !_battlegroundTemplates.ContainsKey(bgTypeId)) + { + Log.outError(LogFilter.Sql, $"BattlegroundMgr::LoadBattlegroundScriptTemplate: bad battlemasterlist id {bgTypeId}! Battleground doesn't exist or is not supported in battleground_template!"); + continue; + } + + BattlegroundScriptTemplate scriptTemplate = new(); + scriptTemplate.MapId = mapID; + scriptTemplate.Id = bgTypeId; + scriptTemplate.ScriptId = Global.ObjectMgr.GetScriptId(result.Read(2)); + + _battlegroundScriptTemplates[(mapID, bgTypeId)] = scriptTemplate; + + ++count; + } while (result.NextRow()); + + Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} battleground scripts in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); + } + + public BattlegroundScriptTemplate FindBattlegroundScriptTemplate(uint mapId, BattlegroundTypeId bgTypeId) + { + BattlegroundScriptTemplate scriptTemplate = _battlegroundScriptTemplates.LookupByKey((mapId, bgTypeId)); + if (scriptTemplate != null) + return scriptTemplate; + + // fall back to 0 for no specific battleground type id + return _battlegroundScriptTemplates.LookupByKey((mapId, BattlegroundTypeId.None)); + } + uint CreateClientVisibleInstanceId(BattlegroundTypeId bgTypeId, BattlegroundBracketId bracket_id) { if (IsArenaType(bgTypeId)) @@ -250,56 +298,10 @@ namespace Game.BattleGrounds } Battleground bg = null; - // create a copy of the BG template - switch (bgTypeId) - { - case BattlegroundTypeId.AV: - bg = new BgAlteracValley(bg_template); - break; - case BattlegroundTypeId.WS: - case BattlegroundTypeId.WgCtf: - bg = new BgWarsongGluch(bg_template); - break; - case BattlegroundTypeId.AB: - case BattlegroundTypeId.DomAb: - bg = new BgArathiBasin(bg_template); - break; - case BattlegroundTypeId.NA: - bg = new BgNagrandArena(bg_template); - break; - case BattlegroundTypeId.BE: - bg = new BgBladesEdgeArena(bg_template); - break; - case BattlegroundTypeId.EY: - bg = new BgEyeofStorm(bg_template); - break; - case BattlegroundTypeId.RL: - bg = new BgRuinsOfLordaernon(bg_template); - break; - case BattlegroundTypeId.SA: - bg = new BgStrandOfAncients(bg_template); - break; - case BattlegroundTypeId.DS: - bg = new BgDalaranSewers(bg_template); - break; - case BattlegroundTypeId.RV: - bg = new BgTheRingOfValor(bg_template); - break; - case BattlegroundTypeId.IC: - bg = new BgIsleofConquest(bg_template); - break; - case BattlegroundTypeId.TP: - bg = new BgTwinPeaks(bg_template); - break; - case BattlegroundTypeId.BFG: - bg = new BgBattleforGilneas(bg_template); - break; - case BattlegroundTypeId.RB: - case BattlegroundTypeId.AA: - case BattlegroundTypeId.RandomEpic: - default: - return null; - } + if (bg_template.IsArena()) + bg = new Arena(bg_template); + else + bg = new Battleground(bg_template); bg.SetBracket(bracketEntry); bg.SetInstanceID(Global.MapMgr.GenerateInstanceId()); @@ -723,6 +725,7 @@ namespace Game.BattleGrounds Dictionary mBattleMastersMap = new(); Dictionary _battlegroundTemplates = new(); Dictionary _battlegroundMapTemplates = new(); + Dictionary<(uint, BattlegroundTypeId), BattlegroundScriptTemplate> _battlegroundScriptTemplates = new(); struct ScheduledQueueUpdate { @@ -808,4 +811,11 @@ namespace Game.BattleGrounds return BattlemasterEntry.MaxLevel; } } + + public class BattlegroundScriptTemplate + { + public uint MapId; + public BattlegroundTypeId Id; + public uint ScriptId; + } } diff --git a/Source/Game/BattleGrounds/BattleGroundScript.cs b/Source/Game/BattleGrounds/BattleGroundScript.cs new file mode 100644 index 000000000..4126c3573 --- /dev/null +++ b/Source/Game/BattleGrounds/BattleGroundScript.cs @@ -0,0 +1,136 @@ +// Copyright (c) CypherCore All rights reserved. +// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. + +using Game.Maps; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Framework.Constants; +using Game.Entities; +using System.Numerics; + +namespace Game.BattleGrounds +{ + public class BattlegroundScript : ZoneScript + { + protected BattlegroundMap battlegroundMap; + protected Battleground battleground; + + public BattlegroundScript(BattlegroundMap map) + { + battlegroundMap = map; + battleground = map.GetBG(); + } + + public virtual Team GetPrematureWinner() + { + Team winner = Team.Other; + if (battleground.GetPlayersCountByTeam(Team.Alliance) >= battleground.GetMinPlayersPerTeam()) + winner = Team.Alliance; + else if (battleground.GetPlayersCountByTeam(Team.Horde) >= battleground.GetMinPlayersPerTeam()) + winner = Team.Horde; + + return winner; + } + + public override void TriggerGameEvent(uint gameEventId, WorldObject source = null, WorldObject target = null) + { + ProcessEvent(target, gameEventId, source); + GameEvents.TriggerForMap(gameEventId, battlegroundMap, source, target); + foreach (var (playerGuid, _) in battleground.GetPlayers()) + { + Player player = Global.ObjAccessor.FindPlayer(playerGuid); + if (player != null) + GameEvents.TriggerForPlayer(gameEventId, player); + } + } + + public void UpdateWorldState(int worldStateId, int value, bool hidden = false) + { + Global.WorldStateMgr.SetValue(worldStateId, value, hidden, battlegroundMap); + } + + public void UpdateWorldState(int worldStateId, bool value, bool hidden = false) + { + Global.WorldStateMgr.SetValue(worldStateId, value ? 1 : 0, hidden, battlegroundMap); + } + + public virtual void OnInit() { } + public virtual void OnUpdate(uint diff) { } + public virtual void OnPrepareStage1() { } + public virtual void OnPrepareStage2() { } + public virtual void OnPrepareStage3() { } + public virtual void OnStart() { } + public virtual void OnEnd(Team winner) { } + public virtual void OnPlayerJoined(Player player, bool inBattleground) { } + public virtual void OnPlayerLeft(Player player) { } + public virtual void OnPlayerKilled(Player victim, Player killer) { } + public virtual void OnUnitKilled(Creature victim, Unit killer) { } + } + + public class ArenaScript : BattlegroundScript + { + public ArenaScript(BattlegroundMap map) : base(map) { } + + public GameObject CreateObject(uint entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, GameObjectState goState = GameObjectState.Ready) + { + Quaternion rot = new(rotation0, rotation1, rotation2, rotation3); + // Temporally add safety check for bad spawns and send log (object rotations need to be rechecked in sniff) + if (rotation0 == 0 && rotation1 == 0 && rotation2 == 0 && rotation3 == 0) + { + Log.outDebug(LogFilter.Battleground, $"Battleground::AddObject: gameoobject [entry: {entry}] for BG (map: {battlegroundMap.GetId()}) has zeroed rotation fields, " + + "orientation used temporally, but please fix the spawn"); + + rot = Quaternion.CreateFromRotationMatrix(Extensions.fromEulerAnglesZYX(o, 0.0f, 0.0f)); + } + + // Must be created this way, adding to godatamap would add it to the base map of the instance + // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created + // So we must create it specific for this instance + GameObject go = GameObject.CreateGameObject(entry, battlegroundMap, new Position(x, y, z, o), rot, 255, goState); + if (go == null) + { + Log.outError(LogFilter.Battleground, $"Battleground::AddObject: cannot create gameobject (entry: {entry}) for BG (map: {battlegroundMap.GetId()}, instance id: {battleground.GetInstanceID()})!"); + return null; + } + + if (!battlegroundMap.AddToMap(go)) + { + go.Dispose(); + return null; + } + + return go; + } + + public Creature CreateCreature(uint entry, float x, float y, float z, float o) + { + if (Global.ObjectMgr.GetCreatureTemplate(entry) == null) + { + Log.outError(LogFilter.Battleground, $"Battleground::AddCreature: creature template (entry: {entry}) does not exist for BG (map: {battlegroundMap.GetId()}, instance id: {battleground.GetInstanceID()})!"); + return null; + } + + Position pos = new(x, y, z, o); + + Creature creature = Creature.CreateCreature(entry, battlegroundMap, pos); + if (creature == null) + { + Log.outError(LogFilter.Battleground, $"Battleground::AddCreature: cannot create creature (entry: {entry}) for BG (map: {battlegroundMap.GetId()}, instance id: {battleground.GetInstanceID()})!"); + return null; + } + + creature.SetHomePosition(pos); + + if (!battlegroundMap.AddToMap(creature)) + { + creature.Dispose(); + return null; + } + + return creature; + } + } +} \ No newline at end of file diff --git a/Source/Game/BattleGrounds/Zones/AlteracValley.cs b/Source/Game/BattleGrounds/Zones/AlteracValley.cs deleted file mode 100644 index a8492208f..000000000 --- a/Source/Game/BattleGrounds/Zones/AlteracValley.cs +++ /dev/null @@ -1,1412 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Game.Entities; -using System; -using System.Collections.Generic; - -namespace Game.BattleGrounds.Zones.AlteracValley -{ - class BgAlteracValley : Battleground - { - int[] _teamResources = new int[SharedConst.PvpTeamsCount]; - uint[][] m_Team_QuestStatus = new uint[SharedConst.PvpTeamsCount][]; //[x][y] x=team y=questcounter - - AVNodeInfo[] _nodes = new AVNodeInfo[(int)AVNodes.Max]; - - TimeTracker _mineResourceTimer; //ticks for both teams - - AlteracValleyMineInfo[] _mineInfo = new AlteracValleyMineInfo[2]; - - TimeTracker[] _captainBuffTimer = new TimeTracker[SharedConst.PvpTeamsCount]; - - bool[] _isInformedNearVictory = new bool[SharedConst.PvpTeamsCount]; - List _doorGUIDs = new(); - ObjectGuid _balindaGUID; - ObjectGuid _galvangarGUID; - List _heraldGUIDs = new(); - - public BgAlteracValley(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) - { - _teamResources = [MiscConst.ScoreInitialPoints, MiscConst.ScoreInitialPoints]; - _isInformedNearVictory = [false, false]; - - for (byte i = 0; i < 2; i++) //forloop for both teams (it just make 0 == alliance and 1 == horde also for both mines 0=north 1=south - { - for (byte j = 0; j < 9; j++) - m_Team_QuestStatus[i][j] = 0; - - _captainBuffTimer[i] = new(120000 + RandomHelper.URand(0, 4) * 60); //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes @todo get the right times - } - - _mineInfo[(byte)AlteracValleyMine.North] = new AlteracValleyMineInfo(Team.Other, new StaticMineInfo(WorldStateIds.IrondeepMineOwner, WorldStateIds.IrondeepMineAllianceControlled, WorldStateIds.IrondeepMineHordeControlled, WorldStateIds.IrondeepMineTroggControlled, (byte)TextIds.IrondeepMineAllianceTaken, (byte)TextIds.IrondeepMineHordeTaken)); - _mineInfo[(byte)AlteracValleyMine.South] = new AlteracValleyMineInfo(Team.Other, new StaticMineInfo(WorldStateIds.ColdtoothMineOwner, WorldStateIds.ColdtoothMineAllianceControlled, WorldStateIds.ColdtoothMineHordeControlled, WorldStateIds.ColdtoothMineKoboldControlled, (byte)TextIds.ColdtoothMineAllianceTaken, (byte)TextIds.ColdtoothMineHordeTaken)); - - for (AVNodes i = AVNodes.FirstaidStation; i <= AVNodes.StoneheartGrave; ++i) //alliance graves - InitNode(i, Team.Alliance, false); - for (AVNodes i = AVNodes.DunbaldarSouth; i <= AVNodes.StoneheartBunker; ++i) //alliance towers - InitNode(i, Team.Alliance, true); - for (AVNodes i = AVNodes.IcebloodGrave; i <= AVNodes.FrostwolfHut; ++i) //horde graves - InitNode(i, Team.Horde, false); - for (AVNodes i = AVNodes.IcebloodTower; i <= AVNodes.FrostwolfWtower; ++i) //horde towers - InitNode(i, Team.Horde, true); - InitNode(AVNodes.SnowfallGrave, Team.Other, false); //give snowfall neutral owner - - _mineResourceTimer = new(MiscConst.MineResourceTimer); - - StartMessageIds[BattlegroundConst.EventIdSecond] = (uint)BroadcastTextIds.StartOneMinute; - StartMessageIds[BattlegroundConst.EventIdThird] = (uint)BroadcastTextIds.StartHalfMinute; - StartMessageIds[BattlegroundConst.EventIdFourth] = (uint)BroadcastTextIds.BattleHasBegun; - } - - public override void HandleKillPlayer(Player player, Player killer) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - base.HandleKillPlayer(player, killer); - UpdateScore(GetPlayerTeam(player.GetGUID()), -1); - } - - public override void HandleKillUnit(Creature unit, Unit killer) - { - Log.outDebug(LogFilter.Battleground, "bg_av HandleKillUnit {}", unit.GetEntry()); - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - switch ((CreatureIds)unit.GetEntry()) - { - case CreatureIds.Vanndar: - { - UpdateWorldState((int)WorldStateIds.VandaarAlive, 0); - CastSpellOnTeam(MiscConst.SpellCompleteAlteracValleyQuest, Team.Horde); //this is a spell which finishes a quest where a player has to kill the boss - RewardReputationToTeam(MiscConst.FactionFrostwolfClan, MiscConst.RepGainBoss, Team.Horde); - RewardHonorToTeam(GetBonusHonorFromKill(MiscConst.HonorKillBonusBoss), Team.Horde); - EndBattleground(Team.Horde); - break; - } - case CreatureIds.Drekthar: - { - UpdateWorldState((int)WorldStateIds.DrektharAlive, 0); - CastSpellOnTeam(MiscConst.SpellCompleteAlteracValleyQuest, Team.Alliance); //this is a spell which finishes a quest where a player has to kill the boss - RewardReputationToTeam(MiscConst.FactionStormpikeGuard, MiscConst.RepGainBoss, Team.Alliance); - RewardHonorToTeam(GetBonusHonorFromKill(MiscConst.HonorKillBonusBoss), Team.Alliance); - EndBattleground(Team.Alliance); - break; - } - case CreatureIds.Balinda: - { - UpdateWorldState((int)WorldStateIds.BalindaAlive, 0); - RewardReputationToTeam(MiscConst.FactionFrostwolfClan, MiscConst.RepGainCaptain, Team.Horde); - RewardHonorToTeam(GetBonusHonorFromKill(MiscConst.HonorKillBonusCaptain), Team.Horde); - UpdateScore(Team.Alliance, MiscConst.ResourceLossCaptain); - Creature herald = FindHerald("bg_av_herald_horde_win"); - if (herald != null) - herald.GetAI().Talk((uint)TextIds.StormpikeGeneralDead); - break; - } - case CreatureIds.Galvangar: - { - UpdateWorldState((int)WorldStateIds.GalvagarAlive, 0); - RewardReputationToTeam(MiscConst.FactionStormpikeGuard, MiscConst.RepGainCaptain, Team.Alliance); - RewardHonorToTeam(GetBonusHonorFromKill(MiscConst.HonorKillBonusCaptain), Team.Alliance); - UpdateScore(Team.Horde, MiscConst.ResourceLossCaptain); - Creature herald = FindHerald("bg_av_herald_alliance_win"); - if (herald != null) - herald.GetAI().Talk((uint)TextIds.FrostwolfGeneralDead); - break; - } - case CreatureIds.Morloch: - { - // if mine is not owned by morloch, then nothing happens - if (_mineInfo[(byte)AlteracValleyMine.North].Owner != Team.Other) - break; - - Team killerTeam = GetPlayerTeam((killer.GetCharmerOrOwnerPlayerOrPlayerItself() ?? killer).GetGUID()); - ChangeMineOwner(AlteracValleyMine.North, killerTeam); - break; - } - case CreatureIds.TaskmasterSnivvle: - { - if (_mineInfo[(byte)AlteracValleyMine.South].Owner != Team.Other) - break; - - Team killerTeam = GetPlayerTeam((killer.GetCharmerOrOwnerPlayerOrPlayerItself() ?? killer).GetGUID()); - ChangeMineOwner(AlteracValleyMine.South, killerTeam); - break; - } - case CreatureIds.UmiThorson: - case CreatureIds.Keetar: - { - Team killerTeam = GetPlayerTeam((killer.GetCharmerOrOwnerPlayerOrPlayerItself() ?? killer).GetGUID()); - ChangeMineOwner(AlteracValleyMine.North, killerTeam); - break; - } - case CreatureIds.AgiRumblestomp: - case CreatureIds.MashaSwiftcut: - { - Team killerTeam = GetPlayerTeam((killer.GetCharmerOrOwnerPlayerOrPlayerItself() ?? killer).GetGUID()); - ChangeMineOwner(AlteracValleyMine.South, killerTeam); - break; - } - } - } - - public override void HandleQuestComplete(uint questid, Player player) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return;//maybe we should log this, cause this must be a cheater or a big bug - Team team = GetPlayerTeam(player.GetGUID()); - int teamIndex = GetTeamIndexByTeamId(team); - /// @todo add reputation, events (including quest not available anymore, next quest available, go/npc de/spawning)and maybe honor - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed", questid); - switch ((QuestIds)questid) - { - case QuestIds.AScraps1: - case QuestIds.AScraps2: - case QuestIds.HScraps1: - case QuestIds.HScraps2: - m_Team_QuestStatus[teamIndex][0] += 20; - break; - case QuestIds.ACommander1: - case QuestIds.HCommander1: - m_Team_QuestStatus[teamIndex][1]++; - RewardReputationToTeam((uint)team, 1, team); - if (m_Team_QuestStatus[teamIndex][1] == 30) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - break; - case QuestIds.ACommander2: - case QuestIds.HCommander2: - m_Team_QuestStatus[teamIndex][2]++; - RewardReputationToTeam((uint)team, 1, team); - if (m_Team_QuestStatus[teamIndex][2] == 60) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - break; - case QuestIds.ACommander3: - case QuestIds.HCommander3: - m_Team_QuestStatus[teamIndex][3]++; - RewardReputationToTeam((uint)team, 1, team); - if (m_Team_QuestStatus[teamIndex][3] == 120) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - break; - case QuestIds.ABoss1: - case QuestIds.HBoss1: - m_Team_QuestStatus[teamIndex][4] += 4; //you can turn in 5 or 1 item.. - goto case QuestIds.ABoss2; - case QuestIds.ABoss2: - case QuestIds.HBoss2: - m_Team_QuestStatus[teamIndex][4]++; - if (m_Team_QuestStatus[teamIndex][4] >= 200) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - UpdateWorldState((int)(teamIndex == BattleGroundTeamId.Alliance ? WorldStateIds.IvusStormCrystalCount : WorldStateIds.LokholarStormpikeSoldiersBloodCount), (int)m_Team_QuestStatus[teamIndex][4]); - break; - case QuestIds.ANearMine: - case QuestIds.HNearMine: - m_Team_QuestStatus[teamIndex][5]++; - if (m_Team_QuestStatus[teamIndex][5] == 28) - { - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - if (m_Team_QuestStatus[teamIndex][6] == 7) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here - ground assault ready", questid); - } - break; - case QuestIds.AOtherMine: - case QuestIds.HOtherMine: - m_Team_QuestStatus[teamIndex][6]++; - if (m_Team_QuestStatus[teamIndex][6] == 7) - { - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - if (m_Team_QuestStatus[teamIndex][5] == 20) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here - ground assault ready", questid); - } - break; - case QuestIds.ARiderHide: - case QuestIds.HRiderHide: - m_Team_QuestStatus[teamIndex][7]++; - if (m_Team_QuestStatus[teamIndex][7] == 25) - { - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - if (m_Team_QuestStatus[teamIndex][8] == 25) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here - rider assault ready", questid); - } - break; - case QuestIds.ARiderTame: - case QuestIds.HRiderTame: - m_Team_QuestStatus[teamIndex][8]++; - if (m_Team_QuestStatus[teamIndex][8] == 25) - { - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here", questid); - if (m_Team_QuestStatus[teamIndex][7] == 25) - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed (need to implement some events here - rider assault ready", questid); - } - break; - default: - Log.outDebug(LogFilter.Battleground, "BG_AV Quest {} completed but is not interesting at all", questid); - break; - } - } - - void UpdateScore(Team team, short points) - { - Cypher.Assert(team == Team.Alliance || team == Team.Horde); - int teamindex = GetTeamIndexByTeamId(team); - _teamResources[teamindex] += points; - - UpdateWorldState((int)(teamindex == BattleGroundTeamId.Horde ? WorldStateIds.HordeReinforcements : WorldStateIds.AllianceReinforcements), _teamResources[teamindex]); - if (points < 0) - { - if (_teamResources[teamindex] < 1) - { - _teamResources[teamindex] = 0; - EndBattleground(teamindex == BattleGroundTeamId.Horde ? Team.Alliance : Team.Horde); - } - else if (!_isInformedNearVictory[teamindex] && _teamResources[teamindex] < MiscConst.NearLosePoints) - { - if (teamindex == BattleGroundTeamId.Alliance) - SendBroadcastText((uint)BroadcastTextIds.AllianceNearLose, ChatMsg.BgSystemAlliance); - else - SendBroadcastText((uint)BroadcastTextIds.HordeNearLose, ChatMsg.BgSystemHorde); - PlaySoundToAll((uint)SoundsId.NearVictory); - _isInformedNearVictory[teamindex] = true; - } - } - } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - _mineResourceTimer.Update(diff); - if (_mineResourceTimer.Passed()) - { - foreach (AlteracValleyMineInfo info in _mineInfo) - { - if (info.Owner == Team.Other) - continue; - - UpdateScore(info.Owner, 1); - } - - _mineResourceTimer.Reset(MiscConst.MineResourceTimer); - } - - for (byte i = BattleGroundTeamId.Alliance; i <= BattleGroundTeamId.Horde; i++) - { - if (!IsCaptainAlive(i)) - continue; - - _captainBuffTimer[i].Update(diff); - if (_captainBuffTimer[i].Passed()) - { - if (i == 0) - { - CastSpellOnTeam((uint)AVBuffs.ACaptain, Team.Alliance); - Creature creature = GetBgMap().GetCreature(_balindaGUID); - if (creature != null) - creature.GetAI().DoAction(MiscConst.ActionBuffYell); - } - else - { - CastSpellOnTeam((uint)AVBuffs.HCaptain, Team.Horde); - Creature creature = GetBgMap().GetCreature(_galvangarGUID); - if (creature != null) - creature.GetAI().DoAction(MiscConst.ActionBuffYell); - } - - _captainBuffTimer[i].Reset(120000 + RandomHelper.URand(0, 4) * 60000); //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes @todo get the right times - } - } - } - - bool IsCaptainAlive(uint teamId) - { - if (teamId == BattleGroundTeamId.Horde) - return GetBgMap().GetWorldStateValue((int)WorldStateIds.GalvagarAlive) == 1; - else if (teamId == BattleGroundTeamId.Alliance) - return GetBgMap().GetWorldStateValue((int)WorldStateIds.BalindaAlive) == 1; - - return false; - } - - public override void StartingEventOpenDoors() - { - Log.outDebug(LogFilter.Battleground, "BG_AV: start spawning mine stuff"); - - UpdateWorldState((int)WorldStateIds.ShowHordeReinforcements, 1); - UpdateWorldState((int)WorldStateIds.ShowAllianceReinforcements, 1); - - // Achievement: The Alterac Blitz - TriggerGameEvent(MiscConst.EventStartBattle); - - foreach (ObjectGuid guid in _doorGUIDs) - { - GameObject gameObject = GetBgMap().GetGameObject(guid); - if (gameObject != null) - { - gameObject.UseDoorOrButton(); - TimeSpan delay = gameObject.GetEntry() == (uint)GameObjectIds.GhostGate ? TimeSpan.Zero : TimeSpan.FromSeconds(3); - gameObject.DespawnOrUnsummon(delay); - } - } - } - - public override void EndBattleground(Team winner) - { - //calculate bonuskills for both teams: - //first towers: - uint[] kills = [0, 0]; - uint[] rep = [0, 0]; - - for (int i = (int)AVNodes.DunbaldarSouth; i <= (int)AVNodes.FrostwolfWtower; ++i) - { - if (_nodes[i].State == AVStates.PointControled) - { - if (_nodes[i].Owner == Team.Alliance) - { - rep[BattleGroundTeamId.Alliance] += MiscConst.RepGainSurvivingTower; - kills[BattleGroundTeamId.Alliance] += MiscConst.HonorKillBonusSurvivingTower; - } - else - { - rep[BattleGroundTeamId.Horde] += MiscConst.RepGainSurvivingTower; - kills[BattleGroundTeamId.Horde] += MiscConst.HonorKillBonusSurvivingTower; - } - } - } - - for (byte i = BattleGroundTeamId.Alliance; i <= BattleGroundTeamId.Horde; ++i) - { - if (IsCaptainAlive(i)) - { - kills[i] += MiscConst.HonorKillBonusSurvivingCaptain; - rep[i] += MiscConst.RepGainSurvivingCaptain; - } - if (rep[i] != 0) - RewardReputationToTeam(i == 0 ? MiscConst.FactionStormpikeGuard : MiscConst.FactionFrostwolfClan, rep[i], i == 0 ? Team.Alliance : Team.Horde); - if (kills[i] != 0) - RewardHonorToTeam(GetBonusHonorFromKill(kills[i]), i == 0 ? Team.Alliance : Team.Horde); - } - - /// @todo add enterevademode for all attacking creatures - base.EndBattleground(winner); - } - - void RemovePlayer(Player player, ObjectGuid guid, uint team) - { - if (player == null) - { - Log.outError(LogFilter.Battleground, "bg_AV no player at remove"); - return; - } - /// @todo search more buffs - player.RemoveAurasDueToSpell((uint)AVBuffs.Armor); - } - - void EventPlayerDestroyedPoint(GameObject gameobject) - { - if (gameobject == null) - return; - - AVNodes node = GetNodeThroughObject(gameobject.GetEntry()); - DestroyNode(node); - UpdateNodeWorldState(node); - - Team owner = _nodes[(int)node].Owner; - if (IsTower(node)) - { - UpdateScore((owner == Team.Alliance) ? Team.Horde : Team.Alliance, MiscConst.ResourceLossTower); - RewardReputationToTeam(owner == Team.Alliance ? MiscConst.FactionStormpikeGuard : MiscConst.FactionFrostwolfClan, MiscConst.RepGainDestroyTower, owner); - RewardHonorToTeam(GetBonusHonorFromKill(MiscConst.HonorKillBonusDestroyTower), owner); - } - - StaticNodeInfo nodeInfo = GetStaticNodeInfo(node); - if (nodeInfo != null) - { - Creature herald = FindHerald(nodeInfo.HordeOrDestroy); - if (herald != null) - herald.GetAI().Talk(owner == Team.Alliance ? nodeInfo.AllianceCapture : nodeInfo.HordeCapture); - } - - GetBgMap().UpdateSpawnGroupConditions(); - } - - public override void DoAction(uint actionId, WorldObject source, WorldObject target) - { - switch (actionId) - { - case MiscConst.ActionCaptureCaptuableObject: - EventPlayerDestroyedPoint(source.ToGameObject()); - break; - case MiscConst.ActionInteractCapturableObject: - if (target != null && source != null && source.IsPlayer()) - HandleInteractCapturableObject(source.ToPlayer(), target.ToGameObject()); - break; - default: - Log.outError(LogFilter.Battleground, "BattlegroundAV::DoAction: {}. Unhandled action.", actionId); - break; - } - } - - void ChangeMineOwner(AlteracValleyMine mine, Team team, bool initial = false) - { - if (team != Team.Alliance && team != Team.Horde) - team = Team.Other; - - AlteracValleyMineInfo mineInfo = _mineInfo[(int)mine]; - - if (mineInfo.Owner == team && !initial) - return; - - mineInfo.Owner = team; - - SendMineWorldStates(mine); - - byte textId = team == Team.Alliance ? mineInfo.StaticInfo.TextIdAlliance : mineInfo.StaticInfo.TextIdHorde; - - string stringId = team == Team.Alliance ? "bg_av_herald_mine_alliance" : "bg_av_herald_mine_horde"; - - Creature herald = FindHerald(stringId); - if (herald != null) - herald.GetAI().Talk(textId); - } - - AVNodes GetNodeThroughObject(uint objectId) - { - switch ((GameObjectIds)objectId) - { - case GameObjectIds.AidStationAllianceControlled: - case GameObjectIds.AidStationHordeContested: - case GameObjectIds.AidStationHordeControlled: - case GameObjectIds.AidStationAllianceContested: - return AVNodes.FirstaidStation; - case GameObjectIds.StormpikeAllianceControlled: - case GameObjectIds.StormpikeHordeContested: - case GameObjectIds.StormpikeHordeControlled: - case GameObjectIds.StormpikeAllianceContested: - return AVNodes.StormpikeGrave; - case GameObjectIds.StonehearthHordeContested: - case GameObjectIds.StonehearthHordeControlled: - case GameObjectIds.StonehearthAllianceContested: - case GameObjectIds.StonehearthAllianceControlled: - return AVNodes.StoneheartGrave; - case GameObjectIds.SnowfallNeutral: - case GameObjectIds.SnowfallHordeContested: - case GameObjectIds.SnowfallAllianceContested: - case GameObjectIds.SnowfallHordeControlled: - case GameObjectIds.SnowfallAllianceControlled: - return AVNodes.SnowfallGrave; - case GameObjectIds.IcebloodHordeControlled: - case GameObjectIds.IcebloodAllianceContested: - case GameObjectIds.IcebloodAllianceControlled: - case GameObjectIds.IcebloodHordeContested: - return AVNodes.IcebloodGrave; - case GameObjectIds.FrostwolfHordeControlled: - case GameObjectIds.FrostwolfAllianceContested: - case GameObjectIds.FrostwolfAllianceControlled: - case GameObjectIds.FrostwolfHordeContested: - return AVNodes.FrostwolfGrave; - case GameObjectIds.FrostwolfHutHordeControlled: - case GameObjectIds.FrostwolfHutAllianceContested: - case GameObjectIds.FrostwolfHutAllianceControlled: - case GameObjectIds.FrostwolfHutHordeContested: - return AVNodes.FrostwolfHut; - case GameObjectIds.SouthBunkerControlledTowerBanner: - case GameObjectIds.SouthBunkerControlledBanner: - case GameObjectIds.SouthBunkerContestedBanner: - case GameObjectIds.SouthBunkerContestedTowerBanner: - return AVNodes.DunbaldarSouth; - case GameObjectIds.NorthBunkerControlledTowerBanner: - case GameObjectIds.NorthBunkerControlledBanner: - case GameObjectIds.NorthBunkerContestedBanner: - case GameObjectIds.NorthBunkerContestedTowerBanner: - return AVNodes.DunbaldarNorth; - case GameObjectIds.EastTowerControlledTowerBanner: - case GameObjectIds.EastTowerControlledBanner: - case GameObjectIds.EastTowerContestedBanner: - case GameObjectIds.EastTowerContestedTowerBanner: - return AVNodes.FrostwolfEtower; - case GameObjectIds.WestTowerControlledTowerBanner: - case GameObjectIds.WestTowerControlledBanner: - case GameObjectIds.WestTowerContestedBanner: - case GameObjectIds.WestTowerContestedTowerBanner: - return AVNodes.FrostwolfWtower; - case GameObjectIds.TowerPointControlledTowerBanner: - case GameObjectIds.TowerPointControlledBanner: - case GameObjectIds.TowerPointContestedBanner: - case GameObjectIds.TowerPointContestedTowerBanner: - return AVNodes.TowerPoint; - case GameObjectIds.IcebloodTowerControlledTowerBanner: - case GameObjectIds.IcebloodTowerControlledBanner: - case GameObjectIds.IcebloodTowerContestedBanner: - case GameObjectIds.IcebloodTowerContestedTowerBanner: - return AVNodes.IcebloodTower; - case GameObjectIds.StonehearthBunkerControlledTowerBanner: - case GameObjectIds.StonehearthBunkerControlledBanner: - case GameObjectIds.StonehearthBunkerContestedBanner: - case GameObjectIds.StonehearthBunkerContestedTowerBanner: - return AVNodes.StoneheartBunker; - case GameObjectIds.IcewingBunkerControlledTowerBanner: - case GameObjectIds.IcewingBunkerControlledBanner: - case GameObjectIds.IcewingBunkerContestedBanner: - case GameObjectIds.IcewingBunkerContestedTowerBanner: - return AVNodes.IcewingBunker; - default: - Log.outError(LogFilter.Battleground, $"BattlegroundAV: ERROR! GetPlace got a wrong objectId {objectId}"); - //ABORT(); - return 0; - } - } - - void HandleInteractCapturableObject(Player player, GameObject target) - { - if (player == null || target == null) - return; - - switch ((GameObjectIds)target.GetEntry()) - { - case GameObjectIds.AidStationAllianceControlled: - case GameObjectIds.AidStationHordeControlled: - case GameObjectIds.FrostwolfAllianceControlled: - case GameObjectIds.FrostwolfHordeControlled: - case GameObjectIds.FrostwolfHutAllianceControlled: - case GameObjectIds.FrostwolfHutHordeControlled: - case GameObjectIds.IcebloodAllianceControlled: - case GameObjectIds.IcebloodHordeControlled: - case GameObjectIds.StonehearthAllianceControlled: - case GameObjectIds.StonehearthHordeControlled: - case GameObjectIds.StormpikeAllianceControlled: - case GameObjectIds.StormpikeHordeControlled: - // Snowfall - case GameObjectIds.SnowfallNeutral: - case GameObjectIds.SnowfallAllianceControlled: - case GameObjectIds.SnowfallHordeControlled: - // Towers - case GameObjectIds.EastTowerControlledBanner: - case GameObjectIds.WestTowerControlledBanner: - case GameObjectIds.TowerPointControlledBanner: - case GameObjectIds.IcebloodTowerControlledBanner: - case GameObjectIds.StonehearthBunkerControlledBanner: - case GameObjectIds.IcewingBunkerControlledBanner: - case GameObjectIds.SouthBunkerControlledBanner: - case GameObjectIds.NorthBunkerControlledBanner: - EventPlayerAssaultsPoint(player, target.GetEntry()); - break; - // Graveyards - case GameObjectIds.AidStationAllianceContested: - case GameObjectIds.AidStationHordeContested: - case GameObjectIds.FrostwolfAllianceContested: - case GameObjectIds.FrostwolfHordeContested: - case GameObjectIds.FrostwolfHutAllianceContested: - case GameObjectIds.FrostwolfHutHordeContested: - case GameObjectIds.IcebloodAllianceContested: - case GameObjectIds.IcebloodHordeContested: - case GameObjectIds.StonehearthAllianceContested: - case GameObjectIds.StonehearthHordeContested: - case GameObjectIds.StormpikeAllianceContested: - case GameObjectIds.StormpikeHordeContested: - // Towers - case GameObjectIds.EastTowerContestedBanner: - case GameObjectIds.WestTowerContestedBanner: - case GameObjectIds.TowerPointContestedBanner: - case GameObjectIds.IcebloodTowerContestedBanner: - case GameObjectIds.StonehearthBunkerContestedBanner: - case GameObjectIds.IcewingBunkerContestedBanner: - case GameObjectIds.SouthBunkerContestedBanner: - case GameObjectIds.NorthBunkerContestedBanner: - EventPlayerDefendsPoint(player, target.GetEntry()); - break; - // Snowfall Special cases (Either Defend/Assault) - case GameObjectIds.SnowfallAllianceContested: - case GameObjectIds.SnowfallHordeContested: - { - AVNodes node = GetNodeThroughObject(target.GetEntry()); - if (_nodes[(int)node].TotalOwner == Team.Other) - EventPlayerAssaultsPoint(player, target.GetEntry()); - else - EventPlayerDefendsPoint(player, target.GetEntry()); - break; - } - default: - break; - } - } - - void EventPlayerDefendsPoint(Player player, uint obj) - { - AVNodes node = GetNodeThroughObject(obj); - - Team owner = _nodes[(int)node].Owner; - Team team = GetPlayerTeam(player.GetGUID()); - - if (owner == team || _nodes[(int)node].State != AVStates.PointAssaulted) - return; - - Log.outDebug(LogFilter.Battleground, "player defends point object: {} node: {}", obj, node); - if (_nodes[(int)node].PrevOwner != team) - { - Log.outError(LogFilter.Battleground, "BG_AV: player defends point which doesn't belong to his team {}", node); - return; - } - - DefendNode(node, team); - UpdateNodeWorldState(node); - - StaticNodeInfo nodeInfo = GetStaticNodeInfo(node); - if (nodeInfo != null) - { - string stringId; - - if (IsTower(node)) - stringId = nodeInfo.AllianceOrDefend; - else - stringId = team == Team.Alliance ? nodeInfo.AllianceOrDefend : nodeInfo.HordeOrDestroy; - - Creature herald = FindHerald(stringId); - if (herald != null) - herald.GetAI().Talk(team == Team.Alliance ? nodeInfo.AllianceCapture : nodeInfo.HordeCapture); - } - - // update the statistic for the defending player - UpdatePvpStat(player, IsTower(node) ? MiscConst.PvpStatTowersDefended : MiscConst.PvpStatGraveyardsDefended, 1); - GetBgMap().UpdateSpawnGroupConditions(); - } - - void EventPlayerAssaultsPoint(Player player, uint obj) - { - AVNodes node = GetNodeThroughObject(obj); - Team owner = _nodes[(int)node].Owner; //maybe name it prevowner - Team team = GetPlayerTeam(player.GetGUID()); - - Log.outDebug(LogFilter.Battleground, "bg_av: player assaults point object {} node {}", obj, node); - if (owner == team || team == _nodes[(int)node].TotalOwner) - return; //surely a gm used this object - - AssaultNode(node, team); - UpdateNodeWorldState(node); - - StaticNodeInfo nodeInfo = GetStaticNodeInfo(node); - if (nodeInfo != null) - { - string stringId; - if (IsTower(node)) - stringId = nodeInfo.HordeOrDestroy; - else - stringId = team == Team.Alliance ? nodeInfo.AllianceOrDefend : nodeInfo.HordeOrDestroy; - - Creature herald = FindHerald(stringId); - if (herald != null) - herald.GetAI().Talk(team == Team.Alliance ? nodeInfo.AllianceAttack : nodeInfo.HordeAttack); - } - - // update the statistic for the assaulting player - UpdatePvpStat(player, IsTower(node) ? MiscConst.PvpStatTowersAssaulted : MiscConst.PvpStatGraveyardsAssaulted, 1); - GetBgMap().UpdateSpawnGroupConditions(); - } - - void UpdateNodeWorldState(AVNodes node) - { - StaticNodeInfo nodeInfo = GetStaticNodeInfo(node); - if (nodeInfo != null) - { - Team owner = _nodes[(int)node].Owner; - AVStates state = _nodes[(int)node].State; - - UpdateWorldState(nodeInfo.AllianceAssault, owner == Team.Alliance && state == AVStates.PointAssaulted); - UpdateWorldState(nodeInfo.AllianceControl, owner == Team.Alliance && state >= AVStates.PointDestroyed); - UpdateWorldState(nodeInfo.HordeAssault, owner == Team.Horde && state == AVStates.PointAssaulted); - UpdateWorldState(nodeInfo.HordeControl, owner == Team.Horde && state >= AVStates.PointDestroyed); - if (nodeInfo.Owner != 0) - UpdateWorldState(nodeInfo.Owner, owner == Team.Horde ? 2 : owner == Team.Alliance ? 1 : 0); - } - - if (node == AVNodes.SnowfallGrave) - UpdateWorldState((int)WorldStateIds.SnowfallGraveyardUncontrolled, _nodes[(int)node].Owner == Team.Other); - } - - void SendMineWorldStates(AlteracValleyMine mine) - { - AlteracValleyMineInfo mineInfo = _mineInfo[(byte)mine]; - UpdateWorldState(mineInfo.StaticInfo.WorldStateHordeControlled, mineInfo.Owner == Team.Horde); - UpdateWorldState(mineInfo.StaticInfo.WorldStateAllianceControlled, mineInfo.Owner == Team.Alliance); - UpdateWorldState(mineInfo.StaticInfo.WorldStateNeutralControlled, mineInfo.Owner == Team.Other); - UpdateWorldState(mineInfo.StaticInfo.WorldStateOwner, mineInfo.Owner == Team.Horde ? 2 : mineInfo.Owner == Team.Alliance ? 1 : 0); - } - - public override WorldSafeLocsEntry GetExploitTeleportLocation(Team team) - { - return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? MiscConst.ExploitTeleportLocationAlliance : MiscConst.ExploitTeleportLocationHorde); - } - - public override bool SetupBattleground() - { - return true; - } - - void AssaultNode(AVNodes node, Team team) - { - _nodes[(int)node].PrevOwner = _nodes[(int)node].Owner; - _nodes[(int)node].Owner = team; - _nodes[(int)node].PrevState = _nodes[(int)node].State; - _nodes[(int)node].State = AVStates.PointAssaulted; - } - - void DestroyNode(AVNodes node) - { - _nodes[(int)node].TotalOwner = _nodes[(int)node].Owner; - _nodes[(int)node].PrevOwner = _nodes[(int)node].Owner; - _nodes[(int)node].PrevState = _nodes[(int)node].State; - _nodes[(int)node].State = (_nodes[(int)node].Tower) ? AVStates.PointDestroyed : AVStates.PointControled; - } - - void InitNode(AVNodes node, Team team, bool tower) - { - _nodes[(int)node].TotalOwner = team; - _nodes[(int)node].Owner = team; - _nodes[(int)node].PrevOwner = 0; - _nodes[(int)node].State = AVStates.PointControled; - _nodes[(int)node].PrevState = _nodes[(int)node].State; - _nodes[(int)node].State = AVStates.PointControled; - _nodes[(int)node].Tower = tower; - } - - void DefendNode(AVNodes node, Team team) - { - _nodes[(int)node].PrevOwner = _nodes[(int)node].Owner; - _nodes[(int)node].Owner = team; - _nodes[(int)node].PrevState = _nodes[(int)node].State; - _nodes[(int)node].State = AVStates.PointControled; - } - - public override Team GetPrematureWinner() - { - int allianceScore = _teamResources[GetTeamIndexByTeamId(Team.Alliance)]; - int hordeScore = _teamResources[GetTeamIndexByTeamId(Team.Horde)]; - - if (allianceScore > hordeScore) - return Team.Alliance; - else if (hordeScore > allianceScore) - return Team.Horde; - - return base.GetPrematureWinner(); - } - - public override void OnGameObjectCreate(GameObject gameObject) - { - switch ((GameObjectIds)gameObject.GetEntry()) - { - case GameObjectIds.GhostGate: - case GameObjectIds.Gate: - _doorGUIDs.Add(gameObject.GetGUID()); - break; - default: - break; - } - } - - public override void OnCreatureCreate(Creature creature) - { - switch ((CreatureIds)creature.GetEntry()) - { - case CreatureIds.Galvangar: - _galvangarGUID = creature.GetGUID(); - break; - case CreatureIds.Balinda: - _balindaGUID = creature.GetGUID(); - break; - case CreatureIds.Herald: - _heraldGUIDs.Add(creature.GetGUID()); - break; - default: - break; - } - } - - public override uint GetData(uint dataId) - { - var getDefenderTierForTeam = DefenderTier (int teamId) => - { - if (m_Team_QuestStatus[teamId][0] < 500) - return DefenderTier.Defender; - - if (m_Team_QuestStatus[teamId][0] < 1000) - return DefenderTier.Seasoned; - - if (m_Team_QuestStatus[teamId][0] < 1500) - return DefenderTier.Veteran; - - return DefenderTier.Champion; - }; - - switch (dataId) - { - case MiscConst.DataDefenderTierAlliance: - return (uint)getDefenderTierForTeam(BattleGroundTeamId.Alliance); - case MiscConst.DataDefenderTierHorde: - return (uint)getDefenderTierForTeam(BattleGroundTeamId.Horde); - default: - return base.GetData(dataId); - } - } - - Creature FindHerald(string stringId) - { - foreach (ObjectGuid guid in _heraldGUIDs) - { - Creature creature = GetBgMap().GetCreature(guid); - if (creature != null && creature.HasStringId(stringId)) - return creature; - } - - return null; - } - - StaticNodeInfo GetStaticNodeInfo(AVNodes node) - { - for (byte i = 0; i < (int)AVNodes.Max; ++i) - if (MiscConst.BGAVNodeInfo[i].NodeId == node) - return MiscConst.BGAVNodeInfo[i]; - - return null; - } - - bool IsTower(AVNodes node) { return _nodes[(int)node].Tower; } - } - - struct AVNodeInfo - { - public AVStates State; - public AVStates PrevState; - public Team TotalOwner; - public Team Owner; - public Team PrevOwner; - public bool Tower; - } - - struct StaticMineInfo - { - public int WorldStateOwner; - public int WorldStateAllianceControlled; - public int WorldStateHordeControlled; - public int WorldStateNeutralControlled; - public byte TextIdAlliance; - public byte TextIdHorde; - - public StaticMineInfo(WorldStateIds worldStateOwner, WorldStateIds worldStateAllianceControlled, WorldStateIds worldStateHordeControlled, WorldStateIds worldStateNeutralControlled, byte textIdAlliance, byte textIdHorde) - { - WorldStateOwner = (int)worldStateOwner; - WorldStateAllianceControlled = (int)worldStateAllianceControlled; - WorldStateHordeControlled = (int)worldStateHordeControlled; - WorldStateNeutralControlled = (int)worldStateNeutralControlled; - TextIdAlliance = textIdAlliance; - TextIdHorde = textIdHorde; - } - } - - struct AlteracValleyMineInfo - { - public Team Owner; - public StaticMineInfo StaticInfo; - - public AlteracValleyMineInfo(Team owner, StaticMineInfo staticMineInfo) - { - Owner = owner; - StaticInfo = staticMineInfo; - } - } - - public class StaticNodeInfo - { - public AVNodes NodeId; - public byte AllianceCapture; - public byte AllianceAttack; - public byte HordeCapture; - public byte HordeAttack; - public int AllianceControl; - public int AllianceAssault; - public int HordeControl; - public int HordeAssault; - public int Owner; - public string AllianceOrDefend; - public string HordeOrDestroy; - - public StaticNodeInfo(AVNodes nodeId, byte allianceCapture, byte allianceAttack, byte hordeCapture, byte hordeAttack, int allianceControl, int allianceAssault, int hordeControl, int hordeAssault, int owner, string allianceOrDefend, string hordeOrDestroy) - { - NodeId = nodeId; - AllianceCapture = allianceCapture; - AllianceAttack = allianceAttack; - HordeCapture = hordeCapture; - HordeAttack = hordeAttack; - AllianceControl = allianceControl; - AllianceAssault = allianceAssault; - HordeControl = hordeControl; - HordeAssault = hordeAssault; - Owner = owner; - AllianceOrDefend = allianceOrDefend; - HordeOrDestroy = hordeOrDestroy; - } - } - - #region Constants - struct MiscConst - { - public const int ActionBuffYell = -30001; - public const int ActionInteractCapturableObject = 1; - public const int ActionCaptureCaptuableObject = 2; - - public const uint ExploitTeleportLocationAlliance = 3664; - public const uint ExploitTeleportLocationHorde = 3665; - - public const int DataDefenderTierHorde = 1; - public const int DataDefenderTierAlliance = 2; - - public const int DefenderTierDefender = 0; - public const int DefenderTierSeasoned = 1; - public const int DefenderTierVeteran = 2; - public const int DefenderTierChampion = 3; - - public const uint NearLosePoints = 140; - - public const uint PvpStatTowersAssaulted = 61; - public const uint PvpStatGraveyardsAssaulted = 63; - public const uint PvpStatTowersDefended = 64; - public const uint PvpStatGraveyardsDefended = 65; - public const uint PvpStatSecondaryObjectives = 82; - - public const uint HonorKillBonusBoss = 4; - public const uint HonorKillBonusCaptain = 3; - public const uint HonorKillBonusSurvivingTower = 2; - public const uint HonorKillBonusSurvivingCaptain = 2; - public const uint HonorKillBonusDestroyTower = 3; - - public const uint RepGainBoss = 350; - public const uint RepGainCaptain = 125; - public const uint RepGainDestroyTower = 12; - public const uint RepGainSurvivingTower = 12; - public const uint RepGainSurvivingCaptain = 125; - - public const int ResourceLossTower = -75; - public const int ResourceLossCaptain = -100; - - public const uint SpellCompleteAlteracValleyQuest = 23658; - - public const uint FactionFrostwolfClan = 729; - public const uint FactionStormpikeGuard = 730; - - public const int ScoreInitialPoints = 700; - public const int EventStartBattle = 9166; // Achievement: The Alterac Blitz - - public static TimeSpan MineResourceTimer = TimeSpan.FromSeconds(45); - - public static StaticNodeInfo[] BGAVNodeInfo = - { - new(AVNodes.FirstaidStation, 47, 48, 45, 46, 1325, 1326, 1327, 1328, 0, "bg_av_herald_stormpike_aid_station_alliance", "bg_av_herald_stormpike_aid_station_horde"), // Stormpike First Aid Station - new(AVNodes.StormpikeGrave, 1, 2, 3, 4, 1333, 1335, 1334, 1336, 0, "bg_av_herald_stormpike_alliance", "bg_av_herald_stormpike_horde"), // Stormpike Graveyard - new(AVNodes.StoneheartGrave, 55, 56, 53, 54, 1302, 1304, 1301, 1303, 0, "bg_av_herald_stonehearth_alliance", "bg_av_herald_stonehearth_horde"), // Stoneheart Graveyard - new(AVNodes.SnowfallGrave, 5, 6, 7, 8, 1341, 1343, 1342, 1344, 0, "bg_av_herald_snowfall_alliance", "bg_av_herald_snowfall_horde"), // Snowfall Graveyard - new(AVNodes.IcebloodGrave, 59, 60, 57, 58, 1346, 1348, 1347, 1349, 0, "bg_av_herald_iceblood_alliance", "bg_av_herald_iceblood_horde"), // Iceblood Graveyard - new(AVNodes.FrostwolfGrave, 9, 10, 11, 12, 1337, 1339, 1338, 1340, 0, "bg_av_herald_frostwolf_alliance", "bg_av_herald_frostwolf_horde"), // Frostwolf Graveyard - new(AVNodes.FrostwolfHut, 51, 52, 49, 50, 1329, 1331, 1330, 1332, 0, "bg_av_herald_frostwolf_hut_alliance", "bg_av_herald_frostwolf_hut_horde"), // Frostwolf Hut - new(AVNodes.DunbaldarSouth, 16, 15, 14, 13, 1361, 1375, 1370, 1378, 1181, "bg_av_herald_south_bunker_defend", "bg_av_herald_south_bunker_attack"), // Dunbaldar South Bunker - new(AVNodes.DunbaldarNorth, 20, 19, 18, 17, 1362, 1374, 1371, 1379, 1182, "bg_av_herald_north_bunker_defend", "bg_av_herald_south_bunker_attack"), // Dunbaldar North Bunker - new(AVNodes.IcewingBunker, 24, 23, 22, 21, 1363, 1376, 1372, 1380, 1183, "bg_av_herald_icewing_bunker_defend", "bg_av_herald_icewing_bunker_attack"), // Icewing Bunker - new(AVNodes.StoneheartBunker, 28, 27, 26, 25, 1364, 1377, 1373, 1381, 1184, "bg_av_herald_stonehearth_bunker_defend", "bg_av_herald_stonehearth_bunker_attack"), // Stoneheart Bunker - new(AVNodes.IcebloodTower, 44, 43, 42, 41, 1368, 1390, 1385, 1395, 1188, "bg_av_herald_iceblood_tower_defend", "bg_av_herald_iceblood_tower_attack"), // Iceblood Tower - new(AVNodes.TowerPoint, 40, 39, 38, 37, 1367, 1389, 1384, 1394, 1187, "bg_av_herald_tower_point_defend", "bg_av_herald_tower_point_attack"), // Tower Point - new(AVNodes.FrostwolfEtower, 36, 35, 34, 33, 1366, 1388, 1383, 1393, 1186, "bg_av_herald_east_tower_defend", "bg_av_herald_east_tower_attack"), // Frostwolf East Tower - new(AVNodes.FrostwolfWtower, 32, 31, 30, 29, 1365, 1387, 1382, 1392, 1185, "bg_av_herald_west_tower_defend", "bg_av_herald_west_tower_attack"), // Frostwolf West Tower - }; - } - - enum DefenderTier - { - Defender, - Seasoned, - Veteran, - Champion - } - - enum BroadcastTextIds - { - StartOneMinute = 10638, - StartHalfMinute = 10639, - BattleHasBegun = 10640, - - AllianceNearLose = 23210, - HordeNearLose = 23211 - } - - enum SoundsId - { - NearVictory = 8456, /// @Todo: Not Confirmed Yet - - AllianceAssaults = 8212, //Tower, Grave + Enemy Boss If Someone Tries To Attack Him - HordeAssaults = 8174, - AllianceGood = 8173, //If Something Good Happens For The Team: Wins(Maybe Only Through Killing The Boss), Captures Mine Or Grave, Destroys Tower And Defends Grave - HordeGood = 8213, - BothTowerDefend = 8192, - - AllianceCaptain = 8232, //Gets Called When Someone Attacks Them And At The Beginning After 5min+Rand(X)*10sec (Maybe Buff) - HordeCaptain = 8333 - } - - enum AlteracValleyMine - { - North = 0, - South - } - - enum CreatureIds - { - Vanndar = 11948, - Drekthar = 11946, - Balinda = 11949, - Galvangar = 11947, - Morloch = 11657, - UmiThorson = 13078, - Keetar = 13079, - TaskmasterSnivvle = 11677, - AgiRumblestomp = 13086, - MashaSwiftcut = 13088, - Herald = 14848, - - StormpikeDefender = 12050, - FrostwolfGuardian = 12053, - SeasonedDefender = 13326, - SeasonedGuardian = 13328, - VeteranDefender = 13331, - VeteranGuardian = 13332, - ChampionDefender = 13422, - ChampionGuardian = 13421 - } - - enum GameObjectIds - { - BannerA = 178925, // Can Only Be Used By Horde - BannerH = 178943, // Can Only Be Used By Alliance - BannerContA = 178940, // Can Only Be Used By Horde - BannerContH = 179435, // Can Only Be Used By Alliance - - BannerAB = 178365, - BannerHB = 178364, - BannerContAB = 179286, - BannerContHB = 179287, - BannerSnowfallN = 180418, - - //Snowfall Eyecandy Banner: - SnowfallCandyA = 179044, - SnowfallCandyPa = 179424, - SnowfallCandyH = 179064, - SnowfallCandyPh = 179425, - - //Banners On Top Of Towers: - TowerBannerA = 178927, //[Ph] Alliance A1 Tower Banner Big - TowerBannerH = 178955, //[Ph] Horde H1 Tower Banner Big - TowerBannerPa = 179446, //[Ph] Alliance H1 Tower Pre-Banner Big - TowerBannerPh = 179436, //[Ph] Horde A1 Tower Pre-Banner Big - - //Auras - AuraA = 180421, - AuraH = 180422, - AuraN = 180423, - AuraAS = 180100, - AuraHS = 180101, - AuraNS = 180102, - - Gate = 180424, - GhostGate = 180322, - - //Mine Supplies - MineN = 178785, - MineS = 178784, - - Fire = 179065, - Smoke = 179066, - - // Towers - SouthBunkerControlledTowerBanner = 178927, - SouthBunkerControlledBanner = 178925, - SouthBunkerContestedBanner = 179435, - SouthBunkerContestedTowerBanner = 179436, - - NorthBunkerControlledTowerBanner = 178932, - NorthBunkerControlledBanner = 178929, - NorthBunkerContestedBanner = 179439, - NorthBunkerContestedTowerBanner = 179440, - - EastTowerControlledTowerBanner = 178956, - EastTowerControlledBanner = 178944, - EastTowerContestedBanner = 179449, - EastTowerContestedTowerBanner = 179450, - - WestTowerControlledTowerBanner = 178955, - WestTowerControlledBanner = 178943, - WestTowerContestedBanner = 179445, - WestTowerContestedTowerBanner = 179446, - - TowerPointControlledTowerBanner = 178957, - TowerPointControlledBanner = 178945, - TowerPointContestedBanner = 179453, - TowerPointContestedTowerBanner = 179454, - - IcebloodTowerControlledTowerBanner = 178958, - IcebloodTowerControlledBanner = 178946, - IcebloodTowerContestedBanner = 178940, - IcebloodTowerContestedTowerBanner = 179458, - - StonehearthBunkerControlledTowerBanner = 178948, - StonehearthBunkerControlledBanner = 178936, - StonehearthBunkerContestedBanner = 179443, - StonehearthBunkerContestedTowerBanner = 179444, - - IcewingBunkerControlledTowerBanner = 178947, - IcewingBunkerControlledBanner = 178935, - IcewingBunkerContestedBanner = 179441, - IcewingBunkerContestedTowerBanner = 179442, - - // Graveyards - AidStationAllianceControlled = 179465, - AidStationHordeContested = 179468, - AidStationHordeControlled = 179467, - AidStationAllianceContested = 179466, - - StormpikeAllianceControlled = 178389, - StormpikeHordeContested = 179287, - StormpikeHordeControlled = 178388, - StormpikeAllianceContested = 179286, - - StonehearthHordeContested = 179310, - StonehearthHordeControlled = 179285, - StonehearthAllianceContested = 179308, - StonehearthAllianceControlled = 179284, - - SnowfallNeutral = 180418, - SnowfallHordeContested = 180420, - SnowfallAllianceContested = 180419, - SnowfallHordeControlled = 178364, - SnowfallAllianceControlled = 178365, - - IcebloodHordeControlled = 179483, - IcebloodAllianceContested = 179482, - IcebloodAllianceControlled = 179481, - IcebloodHordeContested = 179484, - - FrostwolfHordeControlled = 178393, - FrostwolfAllianceContested = 179304, - FrostwolfAllianceControlled = 178394, - FrostwolfHordeContested = 179305, - - FrostwolfHutHordeControlled = 179472, - FrostwolfHutAllianceContested = 179471, - FrostwolfHutAllianceControlled = 179470, - FrostwolfHutHordeContested = 179473 - } - - public enum AVNodes - { - FirstaidStation = 0, - StormpikeGrave = 1, - StoneheartGrave = 2, - SnowfallGrave = 3, - IcebloodGrave = 4, - FrostwolfGrave = 5, - FrostwolfHut = 6, - DunbaldarSouth = 7, - DunbaldarNorth = 8, - IcewingBunker = 9, - StoneheartBunker = 10, - IcebloodTower = 11, - TowerPoint = 12, - FrostwolfEtower = 13, - FrostwolfWtower = 14, - - Max = 15 - } - - enum AVBuffs - { - Armor = 21163, - ACaptain = 23693, //the buff which the alliance captain does - HCaptain = 22751 //the buff which the horde captain does - } - - enum AVStates - { - PointNeutral = 0, - PointAssaulted = 1, - PointDestroyed = 2, - PointControled = 3 - } - - enum WorldStateIds - { - AllianceReinforcements = 3127, - HordeReinforcements = 3128, - ShowHordeReinforcements = 3133, - ShowAllianceReinforcements = 3134, - MaxReinforcements = 3136, - - // Graves - // Alliance - //Stormpike First Aid Station - StormpikeAidStationAllianceControlled = 1325, - StormpikeAidStationInConflictAllianceAttacking = 1326, - StormpikeAidStationHordeControlled = 1327, - StormpikeAidStationInConflictHordeAttacking = 1328, - //Stormpike Graveyard - StormpikeGraveyardAllianceControlled = 1333, - StormpikeGraveyardInConflictAllianceAttacking = 1335, - StormpikeGraveyardHordeControlled = 1334, - StormpikeGraveyardInConflictHordeAttacking = 1336, - //Stoneheart Grave - StonehearthGraveyardAllianceControlled = 1302, - StonehearthGraveyardInConflictAllianceAttacking = 1304, - StonehearthGraveyardHordeControlled = 1301, - StonehearthGraveyardInConflictHordeAttacking = 1303, - //Neutral - //Snowfall Grave - SnowfallGraveyardUncontrolled = 1966, - SnowfallGraveyardAllianceControlled = 1341, - SnowfallGraveyardInConflictAllianceAttacking = 1343, - SnowfallGraveyardHordeControlled = 1342, - SnowfallGraveyardInConflictHordeAttacking = 1344, - //Horde - //Iceblood Grave - IcebloodGraveyardAllianceControlled = 1346, - IcebloodGraveyardInConflictAllianceAttacking = 1348, - IcebloodGraveyardHordeControlled = 1347, - IcebloodGraveyardInConflictHordeAttacking = 1349, - //Frostwolf Grave - FrostwolfGraveyardAllianceControlled = 1337, - FrostwolfGraveyardInConflictAllianceAttacking = 1339, - FrostwolfGraveyardHordeControlled = 1338, - FrostwolfGraveyardInConflictHordeAttacking = 1340, - //Frostwolf Hut - FrostwolfReliefHutAllianceControlled = 1329, - FrostwolfReliefHutInConflictAllianceAttacking = 1331, - FrostwolfReliefHutHordeControlled = 1330, - FrostwolfReliefHutInConflictHordeAttacking = 1332, - - //Towers - //Alliance - //Dunbaldar South Bunker - DunBaldarSouthBunkerOwner = 1181, - DunBaldarSouthBunkerAllianceControlled = 1361, - DunBaldarSouthBunkerDestroyed = 1370, - DunBaldarSouthBunkerInConflictHordeAttacking = 1378, - DunBaldarSouthBunkerInConflictAllianceAttacking = 1374, // Unused - //Dunbaldar North Bunker - DunBaldarNorthBunkerOwner = 1182, - DunBaldarNorthBunkerAllianceControlled = 1362, - DunBaldarNorthBunkerDestroyed = 1371, - DunBaldarNorthBunkerInConflictHordeAttacking = 1379, - DunBaldarNorthBunkerInConflictAllianceAttacking = 1375, // Unused - //Icewing Bunker - IcewingBunkerOwner = 1183, - IcewingBunkerAllianceControlled = 1363, - IcewingBunkerDestroyed = 1372, - IcewingBunkerInConflictHordeAttacking = 1380, - IcewingBunkerInConflictAllianceAttacking = 1376, // Unused - //Stoneheart Bunker - StonehearthBunkerOwner = 1184, - StonehearthBunkerAllianceControlled = 1364, - StonehearthBunkerDestroyed = 1373, - StonehearthBunkerInConflictHordeAttacking = 1381, - StonehearthBunkerInConflictAllianceAttacking = 1377, // Unused - //Horde - //Iceblood Tower - IcebloodTowerOwner = 1187, - IcebloodTowerDestroyed = 1368, - IcebloodTowerHordeControlled = 1385, - IcebloodTowerInConflictAllianceAttacking = 1390, - IcebloodTowerInConflictHordeAttacking = 1395, // Unused - //Tower Point - TowerPointOwner = 1188, - TowerPointDestroyed = 1367, - TowerPointHordeControlled = 1384, - TowerPointInConflictAllianceAttacking = 1389, - TowerPointInConflictHordeAttacking = 1394, // Unused - //Frostwolf West - WestFrostwolfTowerOwner = 1185, - WestFrostwolfTowerDestroyed = 1365, - WestFrostwolfTowerHordeControlled = 1382, - WestFrostwolfTowerInConflictAllianceAttacking = 1387, - WestFrostwolfTowerInConflictHordeAttacking = 1392, // Unused - //Frostwolf East - EastFrostwolfTowerOwner = 1186, - EastFrostwolfTowerDestroyed = 1366, - EastFrostwolfTowerHordeControlled = 1383, - EastFrostwolfTowerInConflictAllianceAttacking = 1388, - EastFrostwolfTowerInConflictHordeAttacking = 1393, // Unused - - //Mines - IrondeepMineOwner = 801, - IrondeepMineTroggControlled = 1360, - IrondeepMineAllianceControlled = 1358, - IrondeepMineHordeControlled = 1359, - - ColdtoothMineOwner = 804, - ColdtoothMineKoboldControlled = 1357, - ColdtoothMineAllianceControlled = 1355, - ColdtoothMineHordeControlled = 1356, - - //Turnins - IvusStormCrystalCount = 1043, - IvusStormCrystalMax = 1044, - LokholarStormpikeSoldiersBloodCount = 923, - LokholarStormpikeSoldiersBloodMax = 922, - - //Bosses - DrektharAlive = 601, - VandaarAlive = 602, - - //Captains - GalvagarAlive = 1352, - BalindaAlive = 1351, - } - - enum QuestIds - { - AScraps1 = 7223, - AScraps2 = 6781, - HScraps1 = 7224, - HScraps2 = 6741, - ACommander1 = 6942, //Soldier - HCommander1 = 6825, - ACommander2 = 6941, //Leutnant - HCommander2 = 6826, - ACommander3 = 6943, //Commander - HCommander3 = 6827, - ABoss1 = 7386, // 5 Cristal/Blood - HBoss1 = 7385, - ABoss2 = 6881, // 1 - HBoss2 = 6801, - ANearMine = 5892, //The Mine Near Start Location Of Team - HNearMine = 5893, - AOtherMine = 6982, //The Other Mine ;) - HOtherMine = 6985, - ARiderHide = 7026, - HRiderHide = 7002, - ARiderTame = 7027, - HRiderTame = 7001 - } - - enum TextIds - { - // Herold - // Towers/Graveyards = 1 - 60 - ColdtoothMineAllianceTaken = 61, - IrondeepMineAllianceTaken = 62, - ColdtoothMineHordeTaken = 63, - IrondeepMineHordeTaken = 64, - FrostwolfGeneralDead = 65, /// @Todo: Sound Is Missing - StormpikeGeneralDead = 66, /// @Todo: Sound Is Missing - AllianceWins = 67, // Nyi /// @Todo: Sound Is Missing - HordeWins = 68, // Nyi /// @Todo: Sound Is Missing - - // Taskmaster Snivvle - SnivvleRandom = 0 - } - #endregion -} diff --git a/Source/Game/BattleGrounds/Zones/ArathiBasin.cs b/Source/Game/BattleGrounds/Zones/ArathiBasin.cs deleted file mode 100644 index 6ec5d1a38..000000000 --- a/Source/Game/BattleGrounds/Zones/ArathiBasin.cs +++ /dev/null @@ -1,658 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Game.Entities; -using Game.Maps; -using System; -using System.Collections.Generic; - -namespace Game.BattleGrounds.Zones.ArathisBasin -{ - class BgArathiBasin : Battleground - { - TimeTracker _pointsTimer; - uint[] m_HonorScoreTics = new uint[SharedConst.PvpTeamsCount]; - uint[] m_ReputationScoreTics = new uint[SharedConst.PvpTeamsCount]; - bool m_IsInformedNearVictory; - uint m_HonorTics; - uint m_ReputationTics; - - List _gameobjectsToRemoveOnMatchStart = new(); - List _creaturesToRemoveOnMatchStart = new(); - List _doors = new(); - List _capturePoints = new(); - - public BgArathiBasin(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) - { - m_IsInformedNearVictory = false; - _pointsTimer = new TimeTracker(MiscConst.TickInterval); - - for (byte i = 0; i < SharedConst.PvpTeamsCount; ++i) - { - m_HonorScoreTics[i] = 0; - m_ReputationScoreTics[i] = 0; - } - - m_HonorTics = 0; - m_ReputationTics = 0; - } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() == BattlegroundStatus.InProgress) - { - // Accumulate points - _pointsTimer.Update(diff); - if (_pointsTimer.Passed()) - { - _pointsTimer.Reset(MiscConst.TickInterval); - - _CalculateTeamNodes(out var ally, out var horde); - int[] points = [ally, horde]; - - for (int team = 0; team < SharedConst.PvpTeamsCount; ++team) - { - if (points[team] == 0) - continue; - - m_TeamScores[team] += MiscConst.TickPoints[points[team]]; - m_HonorScoreTics[team] += MiscConst.TickPoints[points[team]]; - m_ReputationScoreTics[team] += MiscConst.TickPoints[points[team]]; - - if (m_ReputationScoreTics[team] >= m_ReputationTics) - { - if (team == BattleGroundTeamId.Alliance) - RewardReputationToTeam(509, 10, Team.Alliance); - else - RewardReputationToTeam(510, 10, Team.Horde); - - m_ReputationScoreTics[team] -= m_ReputationTics; - } - - if (m_HonorScoreTics[team] >= m_HonorTics) - { - RewardHonorToTeam(GetBonusHonorFromKill(1), (team == BattleGroundTeamId.Alliance) ? Team.Alliance : Team.Horde); - m_HonorScoreTics[team] -= m_HonorTics; - } - - if (!m_IsInformedNearVictory && m_TeamScores[team] > MiscConst.WarningNearVictoryScore) - { - if (team == BattleGroundTeamId.Alliance) - { - SendBroadcastText((uint)ABBattlegroundBroadcastTexts.AllianceNearVictory, ChatMsg.BgSystemNeutral); - PlaySoundToAll((uint)SoundIds.NearVictoryAlliance); - } - else - { - SendBroadcastText((uint)ABBattlegroundBroadcastTexts.HordeNearVictory, ChatMsg.BgSystemNeutral); - PlaySoundToAll((uint)SoundIds.NearVictoryHorde); - } - m_IsInformedNearVictory = true; - } - - if (m_TeamScores[team] > MiscConst.MaxTeamScore) - m_TeamScores[team] = MiscConst.MaxTeamScore; - - if (team == BattleGroundTeamId.Alliance) - UpdateWorldState(WorldStateIds.ResourcesAlly, (int)m_TeamScores[team]); - else - UpdateWorldState(WorldStateIds.ResourcesHorde, (int)m_TeamScores[team]); - // update achievement flags - // we increased m_TeamScores[team] so we just need to check if it is 500 more than other teams resources - int otherTeam = (team + 1) % SharedConst.PvpTeamsCount; - if (m_TeamScores[team] > m_TeamScores[otherTeam] + 500) - { - if (team == BattleGroundTeamId.Alliance) - UpdateWorldState(WorldStateIds.Had500DisadvantageHorde, 1); - else - UpdateWorldState(WorldStateIds.Had500DisadvantageAlliance, 1); - } - } - - UpdateWorldState(WorldStateIds.OccupiedBasesAlly, ally); - UpdateWorldState(WorldStateIds.OccupiedBasesHorde, horde); - } - - // Test win condition - if (m_TeamScores[BattleGroundTeamId.Alliance] >= MiscConst.MaxTeamScore) - EndBattleground(Team.Alliance); - else if (m_TeamScores[BattleGroundTeamId.Horde] >= MiscConst.MaxTeamScore) - EndBattleground(Team.Horde); - } - } - - public override void StartingEventOpenDoors() - { - // Achievement: Let's Get This Done - TriggerGameEvent((uint)ABEventIds.StartBattle); - } - - void _CalculateTeamNodes(out int alliance, out int horde) - { - alliance = 0; - horde = 0; - - BattlegroundMap map = FindBgMap(); - if (map != null) - { - foreach (ObjectGuid guid in _capturePoints) - { - GameObject capturePoint = map.GetGameObject(guid); - if (capturePoint != null) - { - int wsValue = map.GetWorldStateValue((int)capturePoint.GetGoInfo().CapturePoint.worldState1); - switch ((BattlegroundCapturePointState)wsValue) - { - case BattlegroundCapturePointState.AllianceCaptured: - ++alliance; - break; - case BattlegroundCapturePointState.HordeCaptured: - ++horde; - break; - default: - break; - } - } - } - } - } - - public override Team GetPrematureWinner() - { - // How many bases each team owns - _CalculateTeamNodes(out var ally, out var horde); - - if (ally > horde) - return Team.Alliance; - else if (horde > ally) - return Team.Horde; - - // If the values are equal, fall back to the original result (based on number of players on each team) - return base.GetPrematureWinner(); - } - - public override void ProcessEvent(WorldObject source, uint eventId, WorldObject invoker) - { - Player player = invoker.ToPlayer(); - - switch ((ABEventIds)eventId) - { - case ABEventIds.StartBattle: - { - foreach (ObjectGuid guid in _creaturesToRemoveOnMatchStart) - { - Creature creature = GetBgMap().GetCreature(guid); - if (creature != null) - creature.DespawnOrUnsummon(); - } - - foreach (ObjectGuid guid in _gameobjectsToRemoveOnMatchStart) - { - GameObject gameObject = GetBgMap().GetGameObject(guid); - if (gameObject != null) - gameObject.DespawnOrUnsummon(); - } - - foreach (ObjectGuid guid in _doors) - { - GameObject gameObject = GetBgMap().GetGameObject(guid); - if (gameObject != null) - { - gameObject.UseDoorOrButton(); - gameObject.DespawnOrUnsummon(TimeSpan.FromSeconds(3)); - } - } - break; - } - case ABEventIds.ContestedBlacksmithAlliance: - UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 1); - UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedBlacksmithAlliance: - UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 2); - UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureBlacksmithAlliance: - UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - break; - case ABEventIds.ContestedBlacksmithHorde: - UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 0); - UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 1); - PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedBlacksmithHorde: - UpdateWorldState(WorldStateIds.BlacksmithAllianceControlState, 0); - UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureBlacksmithHorde: - UpdateWorldState(WorldStateIds.BlacksmithHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - break; - case ABEventIds.ContestedFarmAlliance: - UpdateWorldState(WorldStateIds.FarmAllianceControlState, 1); - UpdateWorldState(WorldStateIds.FarmHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedFarmAlliance: - UpdateWorldState(WorldStateIds.FarmAllianceControlState, 2); - UpdateWorldState(WorldStateIds.FarmHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureFarmAlliance: - UpdateWorldState(WorldStateIds.FarmAllianceControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - break; - case ABEventIds.ContestedFarmHorde: - UpdateWorldState(WorldStateIds.FarmAllianceControlState, 0); - UpdateWorldState(WorldStateIds.FarmHordeControlState, 1); - PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedFarmHorde: - UpdateWorldState(WorldStateIds.FarmAllianceControlState, 0); - UpdateWorldState(WorldStateIds.FarmHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureFarmHorde: - UpdateWorldState(WorldStateIds.FarmHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - break; - case ABEventIds.ContestedGoldMineAlliance: - UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 1); - UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedGoldMineAlliance: - UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 2); - UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureGoldMineAlliance: - UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - break; - case ABEventIds.ContestedGoldMineHorde: - UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 0); - UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 1); - PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedGoldMineHorde: - UpdateWorldState(WorldStateIds.GoldMineAllianceControlState, 0); - UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureGoldMineHorde: - UpdateWorldState(WorldStateIds.GoldMineHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - break; - case ABEventIds.ContestedLumberMillAlliance: - UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 1); - UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedLumberMillAlliance: - UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 2); - UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureLumberMillAlliance: - UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - break; - case ABEventIds.ContestedLumberMillHorde: - UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 0); - UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 1); - PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedLumberMillHorde: - UpdateWorldState(WorldStateIds.LumberMillAllianceControlState, 0); - UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureLumberMillHorde: - UpdateWorldState(WorldStateIds.LumberMillHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - break; - case ABEventIds.ContestedStablesAlliance: - UpdateWorldState(WorldStateIds.StablesAllianceControlState, 1); - UpdateWorldState(WorldStateIds.StablesHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeAssaultedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedStablesAlliance: - UpdateWorldState(WorldStateIds.StablesAllianceControlState, 2); - UpdateWorldState(WorldStateIds.StablesHordeControlState, 0); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureStablesAlliance: - UpdateWorldState(WorldStateIds.StablesAllianceControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedAlliance); - break; - case ABEventIds.ContestedStablesHorde: - UpdateWorldState(WorldStateIds.StablesAllianceControlState, 0); - UpdateWorldState(WorldStateIds.StablesHordeControlState, 1); - PlaySoundToAll((uint)SoundIds.NodeAssaultedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesAssaulted, 1); - break; - case ABEventIds.DefendedStablesHorde: - UpdateWorldState(WorldStateIds.StablesAllianceControlState, 0); - UpdateWorldState(WorldStateIds.StablesHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - if (player != null) - UpdatePvpStat(player, (uint)ArathiBasinPvpStats.BasesDefended, 1); - break; - case ABEventIds.CaptureStablesHorde: - UpdateWorldState(WorldStateIds.StablesHordeControlState, 2); - PlaySoundToAll((uint)SoundIds.NodeCapturedHorde); - break; - default: - Log.outWarn(LogFilter.Battleground, $"BattlegroundAB::ProcessEvent: Unhandled event {eventId}."); - break; - } - } - - public override void OnCreatureCreate(Creature creature) - { - switch ((CreatureIds)creature.GetEntry()) - { - case CreatureIds.TheBlackBride: - case CreatureIds.RadulfLeder: - _creaturesToRemoveOnMatchStart.Add(creature.GetGUID()); - break; - default: - break; - } - } - - public override void OnGameObjectCreate(GameObject gameObject) - { - if (gameObject.GetGoInfo().type == GameObjectTypes.CapturePoint) - _capturePoints.Add(gameObject.GetGUID()); - - switch ((GameobjectIds)gameObject.GetEntry()) - { - case GameobjectIds.GhostGate: - _gameobjectsToRemoveOnMatchStart.Add(gameObject.GetGUID()); - break; - case GameobjectIds.AllianceDoor: - case GameobjectIds.HordeDoor: - _doors.Add(gameObject.GetGUID()); - break; - default: - break; - } - } - - public override bool SetupBattleground() - { - UpdateWorldState(WorldStateIds.ResourcesMax, MiscConst.MaxTeamScore); - UpdateWorldState(WorldStateIds.ResourcesWarning, MiscConst.WarningNearVictoryScore); - - return true; - } - - public override void Reset() - { - //call parent's class reset - base.Reset(); - - for (var i = 0; i < SharedConst.PvpTeamsCount; ++i) - { - m_TeamScores[i] = 0; - m_HonorScoreTics[i] = 0; - m_ReputationScoreTics[i] = 0; - } - - _pointsTimer.Reset(MiscConst.TickInterval); - - m_IsInformedNearVictory = false; - bool isBGWeekend = Global.BattlegroundMgr.IsBGWeekend(GetTypeID()); - m_HonorTics = isBGWeekend ? MiscConst.ABBGWeekendHonorTicks : MiscConst.NotABBGWeekendHonorTicks; - m_ReputationTics = isBGWeekend ? MiscConst.ABBGWeekendReputationTicks : MiscConst.NotABBGWeekendReputationTicks; - - _creaturesToRemoveOnMatchStart.Clear(); - _gameobjectsToRemoveOnMatchStart.Clear(); - _doors.Clear(); - _capturePoints.Clear(); - } - - public override void EndBattleground(Team winner) - { - // Win reward - if (winner == Team.Alliance) - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance); - if (winner == Team.Horde) - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde); - // Complete map_end rewards (even if no team wins) - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde); - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance); - - base.EndBattleground(winner); - } - - public override WorldSafeLocsEntry GetClosestGraveyard(Player player) - { - return Global.ObjectMgr.GetClosestGraveyard(player.GetWorldLocation(), player.GetTeam(), player); - } - - public override WorldSafeLocsEntry GetExploitTeleportLocation(Team team) - { - return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? MiscConst.ExploitTeleportLocationAlliance : MiscConst.ExploitTeleportLocationHorde); - } - } - - #region Constants - struct MiscConst - { - public const uint NotABBGWeekendHonorTicks = 260; - public const uint ABBGWeekendHonorTicks = 160; - public const uint NotABBGWeekendReputationTicks = 160; - public const uint ABBGWeekendReputationTicks = 120; - - public const int WarningNearVictoryScore = 1400; - public const int MaxTeamScore = 1500; - - public const uint ExploitTeleportLocationAlliance = 3705; - public const uint ExploitTeleportLocationHorde = 3706; - - // Tick intervals and given points: case 0, 1, 2, 3, 4, 5 captured nodes - public static TimeSpan TickInterval = TimeSpan.FromSeconds(2); - public static uint[] TickPoints = { 0, 10, 10, 10, 10, 30 }; - } - - enum ABEventIds - { - StartBattle = 9158, // Achievement: Let'S Get This Done - - ContestedStablesHorde = 28523, - CaptureStablesHorde = 28527, - DefendedStablesHorde = 28525, - ContestedStablesAlliance = 28522, - CaptureStablesAlliance = 28526, - DefendedStablesAlliance = 28524, - - ContestedBlacksmithHorde = 8876, - CaptureBlacksmithHorde = 8773, - DefendedBlacksmithHorde = 8770, - ContestedBlacksmithAlliance = 8874, - CaptureBlacksmithAlliance = 8769, - DefendedBlacksmithAlliance = 8774, - - ContestedFarmHorde = 39398, - CaptureFarmHorde = 39399, - DefendedFarmHorde = 39400, - ContestedFarmAlliance = 39401, - CaptureFarmAlliance = 39402, - DefendedFarmAlliance = 39403, - - ContestedGoldMineHorde = 39404, - CaptureGoldMineHorde = 39405, - DefendedGoldMineHorde = 39406, - ContestedGoldMineAlliance = 39407, - CaptureGoldMineAlliance = 39408, - DefendedGoldMineAlliance = 39409, - - ContestedLumberMillHorde = 39387, - CaptureLumberMillHorde = 39388, - DefendedLumberMillHorde = 39389, - ContestedLumberMillAlliance = 39390, - CaptureLumberMillAlliance = 39391, - DefendedLumberMillAlliance = 39392 - } - - struct WorldStateIds - { - public const int OccupiedBasesHorde = 1778; - public const int OccupiedBasesAlly = 1779; - public const int ResourcesAlly = 1776; - public const int ResourcesHorde = 1777; - public const int ResourcesMax = 1780; - public const int ResourcesWarning = 1955; - - public const int StableIcon = 1842; // Stable Map Icon (None) - public const int StableStateAlience = 1767; // Stable Map State (Alience) - public const int StableStateHorde = 1768; // Stable Map State (Horde) - public const int StableStateConAli = 1769; // Stable Map State (Con Alience) - public const int StableStateConHor = 1770; // Stable Map State (Con Horde) - public const int FarmIcon = 1845; // Farm Map Icon (None) - public const int FarmStateAlience = 1772; // Farm State (Alience) - public const int FarmStateHorde = 1773; // Farm State (Horde) - public const int FarmStateConAli = 1774; // Farm State (Con Alience) - public const int FarmStateConHor = 1775; // Farm State (Con Horde) - public const int BlacksmithIcon = 1846; // Blacksmith Map Icon (None) - public const int BlacksmithStateAlience = 1782; // Blacksmith Map State (Alience) - public const int BlacksmithStateHorde = 1783; // Blacksmith Map State (Horde) - public const int BlacksmithStateConAli = 1784; // Blacksmith Map State (Con Alience) - public const int BlacksmithStateConHor = 1785; // Blacksmith Map State (Con Horde) - public const int LumbermillIcon = 1844; // Lumber Mill Map Icon (None) - public const int LumbermillStateAlience = 1792; // Lumber Mill Map State (Alience) - public const int LumbermillStateHorde = 1793; // Lumber Mill Map State (Horde) - public const int LumbermillStateConAli = 1794; // Lumber Mill Map State (Con Alience) - public const int LumbermillStateConHor = 1795; // Lumber Mill Map State (Con Horde) - public const int GoldmineIcon = 1843; // Gold Mine Map Icon (None) - public const int GoldmineStateAlience = 1787; // Gold Mine Map State (Alience) - public const int GoldmineStateHorde = 1788; // Gold Mine Map State (Horde) - public const int GoldmineStateConAli = 1789; // Gold Mine Map State (Con Alience - public const int GoldmineStateConHor = 1790; // Gold Mine Map State (Con Horde) - - public const int Had500DisadvantageAlliance = 3644; - public const int Had500DisadvantageHorde = 3645; - - public const int FarmIconNew = 8808; // Farm Map Icon - public const int LumberMillIconNew = 8805; // Lumber Mill Map Icon - public const int BlacksmithIconNew = 8799; // Blacksmith Map Icon - public const int GoldMineIconNew = 8809; // Gold Mine Map Icon - public const int StablesIconNew = 5834; // Stable Map Icon - - public const int FarmHordeControlState = 17328; - public const int FarmAllianceControlState = 17325; - public const int LumberMillHordeControlState = 17330; - public const int LumberMillAllianceControlState = 17326; - public const int BlacksmithHordeControlState = 17327; - public const int BlacksmithAllianceControlState = 17324; - public const int GoldMineHordeControlState = 17329; - public const int GoldMineAllianceControlState = 17323; - public const int StablesHordeControlState = 17331; - public const int StablesAllianceControlState = 17322; - } - - // Object id templates from DB - enum GameobjectIds - { - CapturePointStables = 227420, - CapturePointBlacksmith = 227522, - CapturePointFarm = 227536, - CapturePointGoldMine = 227538, - CapturePointLumberMill = 227544, - - GhostGate = 180322, - AllianceDoor = 322273, - HordeDoor = 322274 - } - - enum CreatureIds - { - TheBlackBride = 150501, - RadulfLeder = 150505 - } - - struct ABBattlegroundNodes - { - public const int NodeStables = 0; - public const int NodeBlacksmith = 1; - public const int NodeFarm = 2; - public const int NodeLumberMill = 3; - public const int NodeGoldMine = 4; - - public const int DynamicNodesCount = 5; // Dynamic Nodes That Can Be Captured - - public const int SpiritAliance = 5; - public const int SpiritHorde = 6; - - public const int AllCount = 7; // All Nodes (Dynamic And Static) - } - - enum ABBattlegroundBroadcastTexts - { - AllianceNearVictory = 10598, - HordeNearVictory = 10599 - } - - enum SoundIds - { - NodeClaimed = 8192, - NodeCapturedAlliance = 8173, - NodeCapturedHorde = 8213, - NodeAssaultedAlliance = 8212, - NodeAssaultedHorde = 8174, - NearVictoryAlliance = 8456, - NearVictoryHorde = 8457 - } - - enum ArathiBasinPvpStats - { - BasesAssaulted = 926, - BasesDefended = 927, - } - #endregion -} diff --git a/Source/Game/BattleGrounds/Zones/BattleforGilneas.cs b/Source/Game/BattleGrounds/Zones/BattleforGilneas.cs deleted file mode 100644 index 6d029a492..000000000 --- a/Source/Game/BattleGrounds/Zones/BattleforGilneas.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgBattleforGilneas : Battleground - { - public BgBattleforGilneas(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/BladesEdgeArena.cs b/Source/Game/BattleGrounds/Zones/BladesEdgeArena.cs deleted file mode 100644 index 8d14b25bd..000000000 --- a/Source/Game/BattleGrounds/Zones/BladesEdgeArena.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgBladesEdgeArena : Battleground - { - public BgBladesEdgeArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/DalaranSewers.cs b/Source/Game/BattleGrounds/Zones/DalaranSewers.cs deleted file mode 100644 index 0d0f700e2..000000000 --- a/Source/Game/BattleGrounds/Zones/DalaranSewers.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgDalaranSewers : Battleground - { - public BgDalaranSewers(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/DeepwindGorge.cs b/Source/Game/BattleGrounds/Zones/DeepwindGorge.cs deleted file mode 100644 index 6ab8febf6..000000000 --- a/Source/Game/BattleGrounds/Zones/DeepwindGorge.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgDeepwindGorge : Battleground - { - public BgDeepwindGorge(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/EyeofStorm.cs b/Source/Game/BattleGrounds/Zones/EyeofStorm.cs deleted file mode 100644 index e2b4a3310..000000000 --- a/Source/Game/BattleGrounds/Zones/EyeofStorm.cs +++ /dev/null @@ -1,803 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -using Framework.Constants; -using Game.Entities; -using Game.Entities.GameObjectType; -using Game.Maps; -using Game.Spells; -using System; -using System.Collections.Generic; - -namespace Game.BattleGrounds.Zones.EyeofStorm -{ - class BgEyeofStorm : Battleground - { - uint[] m_HonorScoreTics = new uint[SharedConst.PvpTeamsCount]; - uint m_FlagCapturedBgObjectType; // type that should be despawned when flag is captured - - TimeTracker _pointsTimer; - uint m_HonorTics; - - Dictionary _controlZoneHandlers = new(); - List _doorGUIDs = new(); - ObjectGuid _flagGUID; - - // Focused/Brutal Assault - bool _assaultEnabled; - TimeTracker _flagAssaultTimer; - byte _assaultStackCount; - - public BgEyeofStorm(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) - { - m_HonorScoreTics = [0, 0]; - m_FlagCapturedBgObjectType = 0; - m_HonorTics = 0; - _pointsTimer = new(MiscConst.PointsTickTime); - _assaultEnabled = false; - _assaultStackCount = 0; - _flagAssaultTimer = new(MiscConst.FlagAssaultTimer); - } - - public override void PostUpdateImpl(uint diff) - { - if (GetStatus() == BattlegroundStatus.InProgress) - { - _pointsTimer.Update(diff); - if (_pointsTimer.Passed()) - { - _pointsTimer.Reset(MiscConst.PointsTickTime); - - byte baseCountAlliance = GetControlledBaseCount(BattleGroundTeamId.Alliance); - byte baseCountHorde = GetControlledBaseCount(BattleGroundTeamId.Horde); - if (baseCountAlliance > 0) - AddPoints(Team.Alliance, MiscConst.TickPoints[baseCountAlliance - 1]); - if (baseCountHorde > 0) - AddPoints(Team.Horde, MiscConst.TickPoints[baseCountHorde - 1]); - } - - if (_assaultEnabled) - { - _flagAssaultTimer.Update(diff); - if (_flagAssaultTimer.Passed()) - { - _flagAssaultTimer.Reset(MiscConst.FlagAssaultTimer); - _assaultStackCount++; - - // update assault debuff stacks - DoForFlagKeepers(player => ApplyAssaultDebuffToPlayer(player)); - } - } - } - } - - public override void StartingEventOpenDoors() - { - foreach (ObjectGuid door in _doorGUIDs) - { - GameObject gameObject = GetBgMap().GetGameObject(door); - if (gameObject != null) - { - gameObject.UseDoorOrButton(); - gameObject.DespawnOrUnsummon(TimeSpan.FromSeconds(3)); - } - } - - // Achievement: Flurry - TriggerGameEvent(MiscConst.EventStartBattle); - } - - void AddPoints(Team Team, uint Points) - { - int team_index = GetTeamIndexByTeamId(Team); - m_TeamScores[team_index] += Points; - m_HonorScoreTics[team_index] += Points; - if (m_HonorScoreTics[team_index] >= m_HonorTics) - { - RewardHonorToTeam(GetBonusHonorFromKill(1), Team); - m_HonorScoreTics[team_index] -= m_HonorTics; - } - UpdateTeamScore(team_index); - } - - byte GetControlledBaseCount(int teamId) - { - byte baseCount = 0; - foreach (var controlZoneHandler in _controlZoneHandlers) - { - uint point = controlZoneHandler.Value.GetPoint(); - switch (teamId) - { - case BattleGroundTeamId.Alliance: - if (GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex) == 1) - baseCount++; - break; - case BattleGroundTeamId.Horde: - if (GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex) == 1) - baseCount++; - break; - default: - break; - } - } - return baseCount; - } - - void DoForFlagKeepers(Action action) - { - GameObject flag = GetBgMap().GetGameObject(_flagGUID); - if (flag != null) - { - Player carrier = Global.ObjAccessor.FindPlayer(flag.GetFlagCarrierGUID()); - if (carrier != null) - action(carrier); - } - } - - void ResetAssaultDebuff() - { - _assaultEnabled = false; - _assaultStackCount = 0; - _flagAssaultTimer.Reset(MiscConst.FlagAssaultTimer); - DoForFlagKeepers(RemoveAssaultDebuffFromPlayer); - } - - void ApplyAssaultDebuffToPlayer(Player player) - { - if (_assaultStackCount == 0) - return; - - uint spellId = MiscConst.SpellFocusedAssault; - if (_assaultStackCount >= MiscConst.FlagBrutalAssaultStackCount) - { - player.RemoveAurasDueToSpell(MiscConst.SpellFocusedAssault); - spellId = MiscConst.SpellBrutalAssault; - } - - Aura aura = player.GetAura(spellId); - if (aura == null) - { - player.CastSpell(player, spellId, true); - aura = player.GetAura(spellId); - } - - if (aura != null) - aura.SetStackAmount(_assaultStackCount); - } - - void RemoveAssaultDebuffFromPlayer(Player player) - { - player.RemoveAurasDueToSpell(MiscConst.SpellFocusedAssault); - player.RemoveAurasDueToSpell(MiscConst.SpellBrutalAssault); - } - - void UpdateTeamScore(int team) - { - uint score = GetTeamScore(team); - if (score >= ScoreIds.MaxTeamScore) - { - score = ScoreIds.MaxTeamScore; - if (team == BattleGroundTeamId.Alliance) - EndBattleground(Team.Alliance); - else - EndBattleground(Team.Horde); - } - - if (team == BattleGroundTeamId.Alliance) - UpdateWorldState(WorldStateIds.AllianceResources, (int)score); - else - UpdateWorldState(WorldStateIds.HordeResources, (int)score); - } - - public override void EndBattleground(Team winner) - { - // Win reward - if (winner == Team.Alliance) - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance); - if (winner == Team.Horde) - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde); - - // Complete map reward - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Alliance); - RewardHonorToTeam(GetBonusHonorFromKill(1), Team.Horde); - - base.EndBattleground(winner); - } - - void UpdatePointsCount(uint teamId) - { - if (teamId == BattleGroundTeamId.Alliance) - UpdateWorldState(WorldStateIds.AllianceBase, GetControlledBaseCount(BattleGroundTeamId.Alliance)); - else - UpdateWorldState(WorldStateIds.HordeBase, GetControlledBaseCount(BattleGroundTeamId.Horde)); - } - - public override void OnGameObjectCreate(GameObject gameobject) - { - switch (gameobject.GetEntry()) - { - case GameobjectIds.ADoorEyEntry: - case GameobjectIds.HDoorEyEntry: - _doorGUIDs.Add(gameobject.GetGUID()); - break; - case GameobjectIds.Flag2EyEntry: - _flagGUID = gameobject.GetGUID(); - break; - default: - break; - } - } - - public override bool CanCaptureFlag(AreaTrigger areaTrigger, Player player) - { - if (areaTrigger.GetEntry() != MiscConst.AreatriggerCaptureFlag) - return false; - - GameObject flag = GetBgMap().GetGameObject(_flagGUID); - if (flag != null) - { - if (flag.GetFlagCarrierGUID() != player.GetGUID()) - return false; - } - - GameObject controlzone = player.FindNearestGameObjectWithOptions(40.0f, new FindGameObjectOptions() { StringId = "bg_eye_of_the_storm_control_zone" }); - if (controlzone != null) - { - uint point = _controlZoneHandlers[controlzone.GetEntry()].GetPoint(); - switch (GetPlayerTeam(player.GetGUID())) - { - case Team.Alliance: - return GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex) == 1; - case Team.Horde: - return GetBgMap().GetWorldStateValue(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex) == 1; - default: - return false; - } - } - - return false; - } - - public override void OnCaptureFlag(AreaTrigger areaTrigger, Player player) - { - if (areaTrigger.GetEntry() != MiscConst.AreatriggerCaptureFlag) - return; - - uint baseCount = GetControlledBaseCount(GetTeamIndexByTeamId(GetPlayerTeam(player.GetGUID()))); - - GameObject gameObject = GetBgMap().GetGameObject(_flagGUID); - if (gameObject != null) - gameObject.HandleCustomTypeCommand(new SetNewFlagState(FlagState.Respawning, player)); - - Team team = GetPlayerTeam(player.GetGUID()); - if (team == Team.Alliance) - { - SendBroadcastText(BroadcastTextIds.AllianceCapturedFlag, ChatMsg.BgSystemAlliance, player); - PlaySoundToAll(SoundIds.FlagCapturedAlliance); - } - else - { - SendBroadcastText(BroadcastTextIds.HordeCapturedFlag, ChatMsg.BgSystemHorde, player); - PlaySoundToAll(SoundIds.FlagCapturedHorde); - } - - if (baseCount > 0) - AddPoints(team, MiscConst.FlagPoints[baseCount - 1]); - - UpdateWorldState(WorldStateIds.NetherstormFlagStateHorde, (int)EYFlagState.OnBase); - UpdateWorldState(WorldStateIds.NetherstormFlagStateAlliance, (int)EYFlagState.OnBase); - - UpdatePvpStat(player, MiscConst.PvpStatFlagCaptures, 1); - - player.RemoveAurasDueToSpell(MiscConst.SpellNetherstormFlag); - player.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.PvPActive); - } - - public override void OnFlagStateChange(GameObject flagInBase, FlagState oldValue, FlagState newValue, Player player) - { - switch (newValue) - { - case FlagState.InBase: - ResetAssaultDebuff(); - break; - case FlagState.Dropped: - player.CastSpell(player, BattlegroundConst.SpellRecentlyDroppedNeutralFlag, true); - RemoveAssaultDebuffFromPlayer(player); - - UpdateWorldState(WorldStateIds.NetherstormFlagStateHorde, (int)EYFlagState.WaitRespawn); - UpdateWorldState(WorldStateIds.NetherstormFlagStateAlliance, (int)EYFlagState.WaitRespawn); - - if (GetPlayerTeam(player.GetGUID()) == Team.Alliance) - SendBroadcastText(BroadcastTextIds.FlagDropped, ChatMsg.BgSystemAlliance); - else - SendBroadcastText(BroadcastTextIds.FlagDropped, ChatMsg.BgSystemHorde); - break; - case FlagState.Taken: - if (GetPlayerTeam(player.GetGUID()) == Team.Alliance) - { - UpdateWorldState(WorldStateIds.NetherstormFlagStateAlliance, (int)EYFlagState.OnPlayer); - PlaySoundToAll(SoundIds.FlagPickedUpAlliance); - SendBroadcastText(BroadcastTextIds.TakenFlag, ChatMsg.BgSystemAlliance, player); - } - else - { - UpdateWorldState(WorldStateIds.NetherstormFlagStateHorde, (int)EYFlagState.OnPlayer); - PlaySoundToAll(SoundIds.FlagPickedUpHorde); - SendBroadcastText(BroadcastTextIds.TakenFlag, ChatMsg.BgSystemHorde, player); - } - - ApplyAssaultDebuffToPlayer(player); - _assaultEnabled = true; - - player.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.PvPActive); - break; - case FlagState.Respawning: - ResetAssaultDebuff(); - break; - default: - break; - } - - UpdateWorldState(WorldStateIds.NetherstormFlag, (int)newValue); - } - - public override bool SetupBattleground() - { - UpdateWorldState(WorldStateIds.MaxResources, (int)ScoreIds.MaxTeamScore); - - _controlZoneHandlers[GameobjectIds.FrTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.FelReaver); - _controlZoneHandlers[GameobjectIds.BeTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.BloodElf); - _controlZoneHandlers[GameobjectIds.DrTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.DraeneiRuins); - _controlZoneHandlers[GameobjectIds.HuTowerCapEyEntry] = new BgEyeOfStormControlZoneHandler(this, Points.MageTower); - - return true; - } - - public override void Reset() - { - //call parent's class reset - base.Reset(); - - m_TeamScores[BattleGroundTeamId.Alliance] = 0; - m_TeamScores[BattleGroundTeamId.Horde] = 0; - m_HonorScoreTics = [0, 0]; - m_FlagCapturedBgObjectType = 0; - bool isBGWeekend = Global.BattlegroundMgr.IsBGWeekend(GetTypeID()); - m_HonorTics = isBGWeekend ? MiscConst.EYWeekendHonorTicks : MiscConst.NotEYWeekendHonorTicks; - } - - public override void HandleKillPlayer(Player player, Player killer) - { - if (GetStatus() != BattlegroundStatus.InProgress) - return; - - base.HandleKillPlayer(player, killer); - EventPlayerDroppedFlag(player); - } - - public void EventTeamLostPoint(uint teamId, uint point, WorldObject controlZone) - { - if (teamId == BattleGroundTeamId.Alliance) - { - SendBroadcastText(MiscConst.m_LosingPointTypes[point].MessageIdAlliance, ChatMsg.BgSystemAlliance, controlZone); - UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 0); - } - else if (teamId == BattleGroundTeamId.Horde) - { - SendBroadcastText(MiscConst.m_LosingPointTypes[point].MessageIdHorde, ChatMsg.BgSystemHorde, controlZone); - UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex, 0); - } - - UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateControlIndex, 1); - UpdatePointsCount(teamId); - } - - public void EventTeamCapturedPoint(uint teamId, uint point, WorldObject controlZone) - { - if (teamId == BattleGroundTeamId.Alliance) - { - SendBroadcastText(MiscConst.m_CapturingPointTypes[point].MessageIdAlliance, ChatMsg.BgSystemAlliance, controlZone); - UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateAllianceControlledIndex, 1); - } - else if (teamId == BattleGroundTeamId.Horde) - { - SendBroadcastText(MiscConst.m_CapturingPointTypes[point].MessageIdHorde, ChatMsg.BgSystemHorde, controlZone); - UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateHordeControlledIndex, 1); - } - - UpdateWorldState(MiscConst.m_PointsIconStruct[point].WorldStateControlIndex, 0); - UpdatePointsCount(teamId); - } - - public override WorldSafeLocsEntry GetExploitTeleportLocation(Team team) - { - return Global.ObjectMgr.GetWorldSafeLoc(team == Team.Alliance ? MiscConst.ExploitTeleportLocationAlliance : MiscConst.ExploitTeleportLocationHorde); - } - - public override Team GetPrematureWinner() - { - if (GetTeamScore(BattleGroundTeamId.Alliance) > GetTeamScore(BattleGroundTeamId.Horde)) - return Team.Alliance; - else if (GetTeamScore(BattleGroundTeamId.Horde) > GetTeamScore(BattleGroundTeamId.Alliance)) - return Team.Horde; - - return base.GetPrematureWinner(); - } - - public override void ProcessEvent(WorldObject target, uint eventId, WorldObject invoker) - { - base.ProcessEvent(target, eventId, invoker); - - if (invoker != null) - { - GameObject gameobject = invoker.ToGameObject(); - if (gameobject != null) - { - if (gameobject.GetGoType() == GameObjectTypes.ControlZone) - { - if (!_controlZoneHandlers.TryGetValue(gameobject.GetEntry(), out BgEyeOfStormControlZoneHandler handler)) - return; - - var controlzone = gameobject.GetGoInfo().ControlZone; - if (eventId == controlzone.NeutralEventAlliance) - handler.HandleNeutralEventAlliance(gameobject); - else if (eventId == controlzone.NeutralEventHorde) - handler.HandleNeutralEventHorde(gameobject); - else if (eventId == controlzone.ProgressEventAlliance) - handler.HandleProgressEventAlliance(gameobject); - else if (eventId == controlzone.ProgressEventHorde) - handler.HandleProgressEventHorde(gameobject); - } - } - } - } - - void RemovePoint(Team team, uint Points = 1) { m_TeamScores[GetTeamIndexByTeamId(team)] -= Points; } - - void SetTeamPoint(Team team, uint Points = 0) { m_TeamScores[GetTeamIndexByTeamId(team)] = Points; } - } - - struct BgEyeOfStormPointIconsStruct - { - public BgEyeOfStormPointIconsStruct(uint worldStateControlIndex, int worldStateAllianceControlledIndex, int worldStateHordeControlledIndex, uint worldStateAllianceStatusBarIcon, uint worldStateHordeStatusBarIcon) - { - WorldStateControlIndex = worldStateControlIndex; - WorldStateAllianceControlledIndex = worldStateAllianceControlledIndex; - WorldStateHordeControlledIndex = worldStateHordeControlledIndex; - WorldStateAllianceStatusBarIcon = worldStateAllianceStatusBarIcon; - WorldStateHordeStatusBarIcon = worldStateHordeStatusBarIcon; - } - - public uint WorldStateControlIndex; - public int WorldStateAllianceControlledIndex; - public int WorldStateHordeControlledIndex; - public uint WorldStateAllianceStatusBarIcon; - public uint WorldStateHordeStatusBarIcon; - } - - struct BgEyeOfStormLosingPointStruct - { - public BgEyeOfStormLosingPointStruct(int _SpawnNeutralObjectType, int _DespawnObjectTypeAlliance, uint _MessageIdAlliance, int _DespawnObjectTypeHorde, uint _MessageIdHorde) - { - SpawnNeutralObjectType = _SpawnNeutralObjectType; - DespawnObjectTypeAlliance = _DespawnObjectTypeAlliance; - MessageIdAlliance = _MessageIdAlliance; - DespawnObjectTypeHorde = _DespawnObjectTypeHorde; - MessageIdHorde = _MessageIdHorde; - } - - public int SpawnNeutralObjectType; - public int DespawnObjectTypeAlliance; - public uint MessageIdAlliance; - public int DespawnObjectTypeHorde; - public uint MessageIdHorde; - } - - struct BgEyeOfStormCapturingPointStruct - { - public BgEyeOfStormCapturingPointStruct(int _DespawnNeutralObjectType, int _SpawnObjectTypeAlliance, uint _MessageIdAlliance, int _SpawnObjectTypeHorde, uint _MessageIdHorde, uint _GraveyardId) - { - DespawnNeutralObjectType = _DespawnNeutralObjectType; - SpawnObjectTypeAlliance = _SpawnObjectTypeAlliance; - MessageIdAlliance = _MessageIdAlliance; - SpawnObjectTypeHorde = _SpawnObjectTypeHorde; - MessageIdHorde = _MessageIdHorde; - GraveyardId = _GraveyardId; - } - - public int DespawnNeutralObjectType; - public int SpawnObjectTypeAlliance; - public uint MessageIdAlliance; - public int SpawnObjectTypeHorde; - public uint MessageIdHorde; - public uint GraveyardId; - } - - class BgEyeOfStormControlZoneHandler : ControlZoneHandler - { - BgEyeofStorm _battleground; - uint _point; - - public BgEyeOfStormControlZoneHandler(BgEyeofStorm bg, uint point) - { - _battleground = bg; - _point = point; - } - - public override void HandleProgressEventHorde(GameObject controlZone) - { - _battleground.EventTeamCapturedPoint(BattleGroundTeamId.Horde, _point, controlZone); - } - - public override void HandleProgressEventAlliance(GameObject controlZone) - { - _battleground.EventTeamCapturedPoint(BattleGroundTeamId.Alliance, _point, controlZone); - } - - public override void HandleNeutralEventHorde(GameObject controlZone) - { - _battleground.EventTeamLostPoint(BattleGroundTeamId.Horde, _point, controlZone); - } - - public override void HandleNeutralEventAlliance(GameObject controlZone) - { - _battleground.EventTeamLostPoint(BattleGroundTeamId.Alliance, _point, controlZone); - } - - public uint GetPoint() { return _point; } - } - - #region Constants - struct MiscConst - { - public static TimeSpan PointsTickTime = TimeSpan.FromSeconds(2); - public static TimeSpan FlagAssaultTimer = TimeSpan.FromSeconds(30); - public static ushort FlagBrutalAssaultStackCount = 5; - - public const uint EventStartBattle = 13180; // Achievement: Flurry - - public const uint NotEYWeekendHonorTicks = 260; - public const uint EYWeekendHonorTicks = 160; - - public const uint SpellNetherstormFlag = 34976; - // Focused/Brutal Assault - public const uint SpellFocusedAssault = 46392; - public const uint SpellBrutalAssault = 46393; - - public const uint ExploitTeleportLocationAlliance = 3773; - public const uint ExploitTeleportLocationHorde = 3772; - - public static byte[] TickPoints = { 1, 2, 5, 10 }; - public static uint[] FlagPoints = { 75, 85, 100, 500 }; - - public const uint AreatriggerCaptureFlag = 33; - - public const uint PvpStatFlagCaptures = 183; - - public static BgEyeOfStormPointIconsStruct[] m_PointsIconStruct = - { - new BgEyeOfStormPointIconsStruct(WorldStateIds.FelReaverUncontrol, WorldStateIds.FelReaverAllianceControl, WorldStateIds.FelReaverHordeControl, WorldStateIds.FelReaverAllianceControlState, WorldStateIds.FelReaverHordeControlState), - new BgEyeOfStormPointIconsStruct(WorldStateIds.BloodElfUncontrol, WorldStateIds.BloodElfAllianceControl, WorldStateIds.BloodElfHordeControl, WorldStateIds.BloodElfAllianceControlState, WorldStateIds.BloodElfHordeControlState), - new BgEyeOfStormPointIconsStruct(WorldStateIds.DraeneiRuinsUncontrol, WorldStateIds.DraeneiRuinsAllianceControl, WorldStateIds.DraeneiRuinsHordeControl, WorldStateIds.DraeneiRuinsAllianceControlState, WorldStateIds.DraeneiRuinsHordeControlState), - new BgEyeOfStormPointIconsStruct(WorldStateIds.MageTowerUncontrol, WorldStateIds.MageTowerAllianceControl, WorldStateIds.MageTowerHordeControl, WorldStateIds.MageTowerAllianceControlState, WorldStateIds.MageTowerHordeControlState) - }; - public static BgEyeOfStormLosingPointStruct[] m_LosingPointTypes = - { - new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerFelReaverCenter, ObjectTypes.ABannerFelReaverCenter, BroadcastTextIds.AllianceLostFelReaverRuins, ObjectTypes.HBannerFelReaverCenter, BroadcastTextIds.HordeLostFelReaverRuins), - new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerBloodElfCenter, ObjectTypes.ABannerBloodElfCenter, BroadcastTextIds.AllianceLostBloodElfTower, ObjectTypes.HBannerBloodElfCenter, BroadcastTextIds.HordeLostBloodElfTower), - new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerDraeneiRuinsCenter, ObjectTypes.ABannerDraeneiRuinsCenter, BroadcastTextIds.AllianceLostDraeneiRuins, ObjectTypes.HBannerDraeneiRuinsCenter, BroadcastTextIds.HordeLostDraeneiRuins), - new BgEyeOfStormLosingPointStruct(ObjectTypes.NBannerMageTowerCenter, ObjectTypes.ABannerMageTowerCenter, BroadcastTextIds.AllianceLostMageTower, ObjectTypes.HBannerMageTowerCenter, BroadcastTextIds.HordeLostMageTower) - }; - public static BgEyeOfStormCapturingPointStruct[] m_CapturingPointTypes = - { - new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerFelReaverCenter, ObjectTypes.ABannerFelReaverCenter, BroadcastTextIds.AllianceTakenFelReaverRuins, ObjectTypes.HBannerFelReaverCenter, BroadcastTextIds.HordeTakenFelReaverRuins, GaveyardIds.FelReaver), - new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerBloodElfCenter, ObjectTypes.ABannerBloodElfCenter, BroadcastTextIds.AllianceTakenBloodElfTower, ObjectTypes.HBannerBloodElfCenter, BroadcastTextIds.HordeTakenBloodElfTower, GaveyardIds.BloodElf), - new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerDraeneiRuinsCenter, ObjectTypes.ABannerDraeneiRuinsCenter, BroadcastTextIds.AllianceTakenDraeneiRuins, ObjectTypes.HBannerDraeneiRuinsCenter, BroadcastTextIds.HordeTakenDraeneiRuins, GaveyardIds.DraeneiRuins), - new BgEyeOfStormCapturingPointStruct(ObjectTypes.NBannerMageTowerCenter, ObjectTypes.ABannerMageTowerCenter, BroadcastTextIds.AllianceTakenMageTower, ObjectTypes.HBannerMageTowerCenter, BroadcastTextIds.HordeTakenMageTower, GaveyardIds.MageTower) - }; - } - - struct BroadcastTextIds - { - public const uint AllianceTakenFelReaverRuins = 17828; - public const uint HordeTakenFelReaverRuins = 17829; - public const uint AllianceLostFelReaverRuins = 17835; - public const uint HordeLostFelReaverRuins = 17836; - - public const uint AllianceTakenBloodElfTower = 17819; - public const uint HordeTakenBloodElfTower = 17823; - public const uint AllianceLostBloodElfTower = 17831; - public const uint HordeLostBloodElfTower = 17832; - - public const uint AllianceTakenDraeneiRuins = 17827; - public const uint HordeTakenDraeneiRuins = 17826; - public const uint AllianceLostDraeneiRuins = 17833; - public const uint HordeLostDraeneiRuins = 17834; - - public const uint AllianceTakenMageTower = 17824; - public const uint HordeTakenMageTower = 17825; - public const uint AllianceLostMageTower = 17837; - public const uint HordeLostMageTower = 17838; - - public const uint TakenFlag = 18359; - public const uint FlagDropped = 18361; - public const uint FlagReset = 18364; - public const uint AllianceCapturedFlag = 18375; - public const uint HordeCapturedFlag = 18384; - } - - struct WorldStateIds - { - public const int AllianceResources = 1776; - public const int HordeResources = 1777; - public const int MaxResources = 1780; - public const int AllianceBase = 2752; - public const int HordeBase = 2753; - public const int DraeneiRuinsHordeControl = 2733; - public const int DraeneiRuinsAllianceControl = 2732; - public const int DraeneiRuinsUncontrol = 2731; - public const int MageTowerAllianceControl = 2730; - public const int MageTowerHordeControl = 2729; - public const int MageTowerUncontrol = 2728; - public const int FelReaverHordeControl = 2727; - public const int FelReaverAllianceControl = 2726; - public const int FelReaverUncontrol = 2725; - public const int BloodElfHordeControl = 2724; - public const int BloodElfAllianceControl = 2723; - public const int BloodElfUncontrol = 2722; - public const int ProgressBarPercentGrey = 2720; //100 = Empty (Only Grey); 0 = Blue|Red (No Grey) - public const int ProgressBarStatus = 2719; //50 Init!; 48 ... Hordak Bere .. 33 .. 0 = Full 100% Hordacky; 100 = Full Alliance - public const int ProgressBarShow = 2718; //1 Init; 0 Druhy Send - Bez Messagu; 1 = Controlled Aliance - public const int NetherstormFlag = 8863; - //Set To 2 When Flag Is Picked Up; And To 1 If It Is Dropped - public const int NetherstormFlagStateAlliance = 9808; - public const int NetherstormFlagStateHorde = 9809; - - public const int DraeneiRuinsHordeControlState = 17362; - public const int DraeneiRuinsAllianceControlState = 17366; - public const int MageTowerHordeControlState = 17361; - public const int MageTowerAllianceControlState = 17368; - public const int FelReaverHordeControlState = 17364; - public const int FelReaverAllianceControlState = 17367; - public const int BloodElfHordeControlState = 17363; - public const int BloodElfAllianceControlState = 17365; - } - - struct SoundIds - { - //strange ids, but sure about them - public const uint FlagPickedUpAlliance = 8212; - public const uint FlagCapturedHorde = 8213; - public const uint FlagPickedUpHorde = 8174; - public const uint FlagCapturedAlliance = 8173; - public const uint FlagReset = 8192; - } - - struct GameobjectIds - { - public const uint ADoorEyEntry = 184719; //Alliance Door - public const uint HDoorEyEntry = 184720; //Horde Door - public const uint Flag1EyEntry = 184493; //Netherstorm Flag (Generic) - public const uint Flag2EyEntry = 208977; //Netherstorm Flag (Flagstand) - public const uint ABannerEyEntry = 184381; //Visual Banner (Alliance) - public const uint HBannerEyEntry = 184380; //Visual Banner (Horde) - public const uint NBannerEyEntry = 184382; //Visual Banner (Neutral) - public const uint BeTowerCapEyEntry = 184080; //Be Tower Cap Pt - public const uint FrTowerCapEyEntry = 184081; //Fel Reaver Cap Pt - public const uint HuTowerCapEyEntry = 184082; //Human Tower Cap Pt - public const uint DrTowerCapEyEntry = 184083; //Draenei Tower Cap Pt - public const uint SpeedBuffFelReaverEyEntry = 184970; - public const uint RestorationBuffFelReaverEyEntry = 184971; - public const uint BerserkBuffFelReaverEyEntry = 184972; - public const uint SpeedBuffBloodElfEyEntry = 184964; - public const uint RestorationBuffBloodElfEyEntry = 184965; - public const uint BerserkBuffBloodElfEyEntry = 184966; - public const uint SpeedBuffDraeneiRuinsEyEntry = 184976; - public const uint RestorationBuffDraeneiRuinsEyEntry = 184977; - public const uint BerserkBuffDraeneiRuinsEyEntry = 184978; - public const uint SpeedBuffMageTowerEyEntry = 184973; - public const uint RestorationBuffMageTowerEyEntry = 184974; - public const uint BerserkBuffMageTowerEyEntry = 184975; - } - - struct GaveyardIds - { - public const int MainAlliance = 1103; - public const uint MainHorde = 1104; - public const uint FelReaver = 1105; - public const uint BloodElf = 1106; - public const uint DraeneiRuins = 1107; - public const uint MageTower = 1108; - } - - struct Points - { - public const int FelReaver = 0; - public const int BloodElf = 1; - public const int DraeneiRuins = 2; - public const int MageTower = 3; - - public const int PlayersOutOfPoints = 4; - public const int PointsMax = 4; - } - - struct ObjectTypes - { - public const int DoorA = 0; - public const int DoorH = 1; - public const int ABannerFelReaverCenter = 2; - public const int ABannerFelReaverLeft = 3; - public const int ABannerFelReaverRight = 4; - public const int ABannerBloodElfCenter = 5; - public const int ABannerBloodElfLeft = 6; - public const int ABannerBloodElfRight = 7; - public const int ABannerDraeneiRuinsCenter = 8; - public const int ABannerDraeneiRuinsLeft = 9; - public const int ABannerDraeneiRuinsRight = 10; - public const int ABannerMageTowerCenter = 11; - public const int ABannerMageTowerLeft = 12; - public const int ABannerMageTowerRight = 13; - public const int HBannerFelReaverCenter = 14; - public const int HBannerFelReaverLeft = 15; - public const int HBannerFelReaverRight = 16; - public const int HBannerBloodElfCenter = 17; - public const int HBannerBloodElfLeft = 18; - public const int HBannerBloodElfRight = 19; - public const int HBannerDraeneiRuinsCenter = 20; - public const int HBannerDraeneiRuinsLeft = 21; - public const int HBannerDraeneiRuinsRight = 22; - public const int HBannerMageTowerCenter = 23; - public const int HBannerMageTowerLeft = 24; - public const int HBannerMageTowerRight = 25; - public const int NBannerFelReaverCenter = 26; - public const int NBannerFelReaverLeft = 27; - public const int NBannerFelReaverRight = 28; - public const int NBannerBloodElfCenter = 29; - public const int NBannerBloodElfLeft = 30; - public const int NBannerBloodElfRight = 31; - public const int NBannerDraeneiRuinsCenter = 32; - public const int NBannerDraeneiRuinsLeft = 33; - public const int NBannerDraeneiRuinsRight = 34; - public const int NBannerMageTowerCenter = 35; - public const int NBannerMageTowerLeft = 36; - public const int NBannerMageTowerRight = 37; - public const int TowerCapFelReaver = 38; - public const int TowerCapBloodElf = 39; - public const int TowerCapDraeneiRuins = 40; - public const int TowerCapMageTower = 41; - public const int FlagNetherstorm = 42; - public const int FlagFelReaver = 43; - public const int FlagBloodElf = 44; - public const int FlagDraeneiRuins = 45; - public const int FlagMageTower = 46; - //Buffs - public const int SpeedbuffFelReaver = 47; - public const int RegenbuffFelReaver = 48; - public const int BerserkbuffFelReaver = 49; - public const int SpeedbuffBloodElf = 50; - public const int RegenbuffBloodElf = 51; - public const int BerserkbuffBloodElf = 52; - public const int SpeedbuffDraeneiRuins = 53; - public const int RegenbuffDraeneiRuins = 54; - public const int BerserkbuffDraeneiRuins = 55; - public const int SpeedbuffMageTower = 56; - public const int RegenbuffMageTower = 57; - public const int BerserkbuffMageTower = 58; - public const int Max = 59; - } - - struct ScoreIds - { - public const uint WarningNearVictoryScore = 1400; - public const uint MaxTeamScore = 1500; - } - - enum EYFlagState - { - OnBase = 0, - WaitRespawn = 1, - OnPlayer = 2, - OnGround = 3 - } - #endregion -} diff --git a/Source/Game/BattleGrounds/Zones/NagrandArena.cs b/Source/Game/BattleGrounds/Zones/NagrandArena.cs deleted file mode 100644 index da880bc36..000000000 --- a/Source/Game/BattleGrounds/Zones/NagrandArena.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgNagrandArena : Battleground - { - public BgNagrandArena(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/RuinsOfLordaernon.cs b/Source/Game/BattleGrounds/Zones/RuinsOfLordaernon.cs deleted file mode 100644 index a85069a5e..000000000 --- a/Source/Game/BattleGrounds/Zones/RuinsOfLordaernon.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgRuinsOfLordaernon : Battleground - { - public BgRuinsOfLordaernon(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/SilvershardMines.cs b/Source/Game/BattleGrounds/Zones/SilvershardMines.cs deleted file mode 100644 index c90c1caf7..000000000 --- a/Source/Game/BattleGrounds/Zones/SilvershardMines.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgSilvershardMines : Battleground - { - public BgSilvershardMines(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/TempleofKotmogu.cs b/Source/Game/BattleGrounds/Zones/TempleofKotmogu.cs deleted file mode 100644 index f5b2e7398..000000000 --- a/Source/Game/BattleGrounds/Zones/TempleofKotmogu.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgTempleofKotmogu : Battleground - { - public BgTempleofKotmogu(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/TheRingOfValor.cs b/Source/Game/BattleGrounds/Zones/TheRingOfValor.cs deleted file mode 100644 index 9eda22c5a..000000000 --- a/Source/Game/BattleGrounds/Zones/TheRingOfValor.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgTheRingOfValor : Battleground - { - public BgTheRingOfValor(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/BattleGrounds/Zones/TwinPeaks.cs b/Source/Game/BattleGrounds/Zones/TwinPeaks.cs deleted file mode 100644 index 7e39a5ae8..000000000 --- a/Source/Game/BattleGrounds/Zones/TwinPeaks.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) CypherCore All rights reserved. -// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - -namespace Game.BattleGrounds.Zones -{ - class BgTwinPeaks : Battleground - { - public BgTwinPeaks(BattlegroundTemplate battlegroundTemplate) : base(battlegroundTemplate) { } - } -} diff --git a/Source/Game/Chat/Channels/ChannelManager.cs b/Source/Game/Chat/Channels/ChannelManager.cs index b28bc368f..5d0cb8b33 100644 --- a/Source/Game/Chat/Channels/ChannelManager.cs +++ b/Source/Game/Chat/Channels/ChannelManager.cs @@ -90,15 +90,15 @@ namespace Game.Chat public static ChannelManager ForTeam(Team team) { if (WorldConfig.GetBoolValue(WorldCfg.AllowTwoSideInteractionChannel)) - return allianceChannelMgr; // cross-faction + return neutralChannelMgr; // cross-faction - if (team == Team.Alliance) - return allianceChannelMgr; - - if (team == Team.Horde) - return hordeChannelMgr; - - return null; + return team switch + { + Team.Alliance => allianceChannelMgr, + Team.Horde => hordeChannelMgr, + Team.PandariaNeutral => neutralChannelMgr, + _ => null + }; } public static Channel GetChannelForPlayerByNamePart(string namePart, Player playerSearcher) @@ -239,5 +239,6 @@ namespace Game.Chat static ChannelManager allianceChannelMgr = new(Team.Alliance); static ChannelManager hordeChannelMgr = new(Team.Horde); + static ChannelManager neutralChannelMgr = new(Team.PandariaNeutral); } } diff --git a/Source/Game/Chat/Commands/DebugCommands.cs b/Source/Game/Chat/Commands/DebugCommands.cs index 63c9ef459..51d735c69 100644 --- a/Source/Game/Chat/Commands/DebugCommands.cs +++ b/Source/Game/Chat/Commands/DebugCommands.cs @@ -683,17 +683,11 @@ namespace Game.Chat if (linked == "linked") { - Battleground bg = player.GetBattleground(); - if (bg != null) - nearestLoc = bg.GetClosestGraveyard(player); + BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(player.GetMap(), player.GetZoneId()); + if (bf != null) + nearestLoc = bf.GetClosestGraveyard(player); else - { - BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(player.GetMap(), player.GetZoneId()); - if (bf != null) - nearestLoc = bf.GetClosestGraveyard(player); - else - nearestLoc = Global.ObjectMgr.GetClosestGraveyard(player, player.GetTeam(), player); - } + nearestLoc = Global.ObjectMgr.GetClosestGraveyard(player, player.GetTeam(), player); } else { @@ -788,11 +782,7 @@ namespace Game.Chat return false; } - var playerConditionEntry = CliDB.PlayerConditionStorage.LookupByKey(playerConditionId); - if (playerConditionEntry == null) - return false; - - if (ConditionManager.IsPlayerMeetingCondition(target, playerConditionEntry)) + if (ConditionManager.IsPlayerMeetingCondition(target, playerConditionId)) handler.SendSysMessage($"PlayerCondition {playerConditionId} met"); else handler.SendSysMessage($"PlayerCondition {playerConditionId} not met"); diff --git a/Source/Game/Chat/Commands/MessageCommands.cs b/Source/Game/Chat/Commands/MessageCommands.cs index 87680170d..85753c11f 100644 --- a/Source/Game/Chat/Commands/MessageCommands.cs +++ b/Source/Game/Chat/Commands/MessageCommands.cs @@ -123,7 +123,7 @@ namespace Game.Chat if (normalizePlayerName(*playerNameArg)) { - if (Player * player = ObjectAccessor::FindPlayerByName(*playerNameArg)) + if (Player * player = Global.ObjAccessor.FindPlayerByName(*playerNameArg)) { handler->GetSession()->GetPlayer()->RemoveFromWhisperWhiteList(player->GetGUID()); handler->PSendSysMessage(LANG_COMMAND_WHISPEROFFPLAYER, playerNameArg->c_str()); diff --git a/Source/Game/Chat/Commands/NPCCommands.cs b/Source/Game/Chat/Commands/NPCCommands.cs index 2cc83ca84..dcd6801bc 100644 --- a/Source/Game/Chat/Commands/NPCCommands.cs +++ b/Source/Game/Chat/Commands/NPCCommands.cs @@ -839,8 +839,7 @@ namespace Game.Chat { if (a.GetMovementGeneratorType() == MovementGeneratorType.Follow) { - FollowMovementGenerator followMovement = a as FollowMovementGenerator; - return followMovement != null && followMovement.GetTarget() == player; + return a is FollowMovementGenerator followMovement && followMovement.GetTarget() == player; } return false; }); diff --git a/Source/Game/Chat/Hyperlink.cs b/Source/Game/Chat/Hyperlink.cs index aee1b9df9..06064fe8b 100644 --- a/Source/Game/Chat/Hyperlink.cs +++ b/Source/Game/Chat/Hyperlink.cs @@ -17,35 +17,10 @@ namespace Game.Chat if (info == null) return default; - ChatCommandResult errorResult = ChatCommandResult.FromErrorMessage(handler.GetCypherString(CypherStrings.CmdparserLinkdataInvalid)); - // store value - switch (Type.GetTypeCode(type)) - { - case TypeCode.UInt32: - { - if (!uint.TryParse(info.Data, out uint tempValue)) - return errorResult; - - value = tempValue; - break; - } - case TypeCode.UInt64: - { - if (!ulong.TryParse(info.Data, out ulong tempValue)) - return errorResult; - - value = tempValue; - break; - } - case TypeCode.String: - { - value = info.Data; - break; - } - default: - return errorResult; - } + HyperlinkDataTokenizer t = new(info.Data, true); + if (!t.TryConsumeTo(out value, type)) + return new ChatCommandResult(handler.GetCypherString(CypherStrings.CmdparserLinkdataInvalid)); // finally, skip any potential delimiters var (token, next) = info.Tail.Tokenize(); @@ -101,7 +76,6 @@ namespace Game.Chat static byte toHex(char c) { return (byte)((c >= '0' && c <= '9') ? c - '0' + 0x10 : (c >= 'a' && c <= 'f') ? c - 'a' + 0x1a : 0x00); } - //|color|Henchant:recipe_spell_id|h[prof_name: recipe_name]|h|r public static HyperlinkInfo ParseHyperlink(string currentString) { if (currentString.IsEmpty()) diff --git a/Source/Game/Chat/HyperlinkTags.cs b/Source/Game/Chat/HyperlinkTags.cs index f1897c721..d34d2c537 100644 --- a/Source/Game/Chat/HyperlinkTags.cs +++ b/Source/Game/Chat/HyperlinkTags.cs @@ -2,7 +2,11 @@ // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. using Framework.IO; +using Game.DataStorage; using Game.Entities; +using Game.Spells; +using System; +using System.Collections.Generic; namespace Game.Chat { @@ -14,136 +18,95 @@ namespace Game.Chat _allowEmptyTokens = allowEmptyTokens; } - public bool TryConsumeTo(out byte val) + public bool TryConsumeTo(out dynamic val, Type type) { + val = default; + if (IsEmpty()) - { - val = default; return _allowEmptyTokens; + + switch (Type.GetTypeCode(type)) + { + case TypeCode.SByte: + val = _arg.NextByte(":"); + return true; + case TypeCode.Int16: + val = _arg.NextUInt16(":"); + return true; + case TypeCode.Int32: + val = _arg.NextUInt32(":"); + return true; + case TypeCode.Int64: + val = _arg.NextUInt64(":"); + return true; + case TypeCode.Byte: + val = _arg.NextByte(":"); + return true; + case TypeCode.UInt16: + val = _arg.NextUInt16(":"); + return true; + case TypeCode.UInt32: + val = _arg.NextUInt32(":"); + return true; + case TypeCode.UInt64: + val = _arg.NextUInt64(":"); + return true; + case TypeCode.Single: + val = _arg.NextSingle(":"); + return true; + case TypeCode.Double: + val = _arg.NextDouble(":"); + return true; + case TypeCode.String: + val = _arg.NextString(":"); + return true; + case TypeCode.Object: + { + switch (type.Name) + { + case nameof(AchievementRecord): + val = CliDB.AchievementStorage.LookupByKey(_arg.NextUInt32(":")); + if (val != null) + return true; + break; + case nameof(CurrencyTypesRecord): + val = CliDB.CurrencyTypesStorage.LookupByKey(_arg.NextUInt32(":")); + if (val != null) + return true; + break; + case nameof(GameTele): + val = Global.ObjectMgr.GetGameTele(_arg.NextUInt32(":")); + if (val != null) + return true; + break; + case nameof(ItemTemplate): + val = Global.ObjectMgr.GetItemTemplate(_arg.NextUInt32(":")); + if (val != null) + return true; + break; + case nameof(Quest): + val = Global.ObjectMgr.GetQuestTemplate(_arg.NextUInt32(":")); + if (val != null) + return true; + break; + case nameof(SpellInfo): + val = Global.SpellMgr.GetSpellInfo(_arg.NextUInt32(":"), Framework.Constants.Difficulty.None); + if (val != null) + return true; + break; + case nameof(ObjectGuid): + val = ObjectGuid.FromString(_arg.NextString(":")); + if (val != ObjectGuid.FromStringFailed) + return true; + break; + default: + return false; + } + break; + } } - val = _arg.NextByte(":"); - return true; - } - public bool TryConsumeTo(out ushort val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - val = _arg.NextUInt16(":"); - return true; - } - public bool TryConsumeTo(out uint val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextUInt32(":"); - return true; - } - public bool TryConsumeTo(out ulong val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextUInt64(":"); - return true; - } - public bool TryConsumeTo(out sbyte val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextSByte(":"); - return true; - } - public bool TryConsumeTo(out short val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextInt16(":"); - return true; - } - public bool TryConsumeTo(out int val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextInt32(":"); - return true; - } - public bool TryConsumeTo(out long val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextInt64(":"); - return true; - } - public bool TryConsumeTo(out float val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextSingle(":"); - return true; - } - public bool TryConsumeTo(out ObjectGuid val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = ObjectGuid.FromString(_arg.NextString(":")); - return true; - } - public bool TryConsumeTo(out string val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextString(":"); - return true; - } - public bool TryConsumeTo(out bool val) - { - if (IsEmpty()) - { - val = default; - return _allowEmptyTokens; - } - - val = _arg.NextBoolean(":"); - return true; + return false; } public bool IsEmpty() { return _arg.Empty(); } @@ -151,4 +114,4 @@ namespace Game.Chat StringArguments _arg; bool _allowEmptyTokens; } -} +} \ No newline at end of file diff --git a/Source/Game/Collision/BoundingIntervalHierarchy.cs b/Source/Game/Collision/BoundingIntervalHierarchy.cs index 4c88b4bd9..6b12bf7a3 100644 --- a/Source/Game/Collision/BoundingIntervalHierarchy.cs +++ b/Source/Game/Collision/BoundingIntervalHierarchy.cs @@ -19,7 +19,7 @@ namespace Game.Collision void InitEmpty() { - tree= new uint[3]; + tree = new uint[3]; objects = Array.Empty(); bounds = AxisAlignedBox.Zero(); // create space for the first node @@ -76,7 +76,7 @@ namespace Game.Collision rightOrig = right; // save this for later float nodeL = float.PositiveInfinity; float nodeR = float.NegativeInfinity; - for (int i = left; i <= right; ) + for (int i = left; i <= right;) { int obj = (int)dat.indices[i]; float minb = dat.primBound[obj].Lo.GetAt(axis); @@ -306,6 +306,7 @@ namespace Game.Collision } public uint PrimCount() { return (uint)objects.Length; } + public AxisAlignedBox bound() { return bounds; } public void IntersectRay(Ray r, WorkerCallback intersectCallback, ref float maxDist, bool stopAtFirst = false) { @@ -410,7 +411,7 @@ namespace Game.Collision while (n > 0) { bool hit = intersectCallback.Invoke(r, objects[offset], ref maxDist, stopAtFirst); - if (stopAtFirst && hit) + if (stopAtFirst && hit) return; --n; ++offset; diff --git a/Source/Game/Collision/Callbacks.cs b/Source/Game/Collision/Callbacks.cs index 1ebb6c318..68f9fd071 100644 --- a/Source/Game/Collision/Callbacks.cs +++ b/Source/Game/Collision/Callbacks.cs @@ -40,34 +40,41 @@ namespace Game.Collision public class WModelAreaCallback : WorkerCallback { - public WModelAreaCallback(List vals, Vector3 down) + List prims; + public GroupModel[] hit = new GroupModel[3]; + + public WModelAreaCallback(List vals) { prims = vals; - hit = null; - zDist = float.PositiveInfinity; - zVec = down; } - List prims; - public GroupModel hit; - public float zDist; - Vector3 zVec; - public override void Invoke(Vector3 point, uint entry) + public override bool Invoke(Ray ray, uint entry, ref float distance, bool stopAtFirstHit) { - float group_Z; - if (prims[(int)entry].IsInsideObject(point, zVec, out group_Z)) + GroupModel.InsideResult result = prims[(int)entry].IsInsideObject(ray, out float group_Z); + if ( result != GroupModel.InsideResult.OutOfBounds) { - if (group_Z < zDist) + if (result != GroupModel.InsideResult.MaybeInside) { - zDist = group_Z; - hit = prims[(int)entry]; + if (group_Z < distance) + { + distance = group_Z; + hit[(int)result] = prims[(int)entry]; + return true; + } + } + else + hit[(int)result] = prims[(int)entry]; } + return false; } } public class WModelRayCallBack : WorkerCallback { + List models; + public bool hit; + public WModelRayCallBack(List mod) { models = mod; @@ -79,8 +86,6 @@ namespace Game.Collision if (result) hit = true; return hit; } - List models; - public bool hit; } public class GModelRayCallback : WorkerCallback diff --git a/Source/Game/Collision/Models/WorldModel.cs b/Source/Game/Collision/Models/WorldModel.cs index 3ca2d9b89..426ec13a9 100644 --- a/Source/Game/Collision/Models/WorldModel.cs +++ b/Source/Game/Collision/Models/WorldModel.cs @@ -251,19 +251,56 @@ namespace Game.Collision return callback.hit; } - public bool IsInsideObject(Vector3 pos, Vector3 down, out float z_dist) + bool IsInsideOrAboveBound(AxisAlignedBox bounds, Vector3 point) { - z_dist = 0f; - if (triangles.Empty() || !iBound.contains(pos)) - return false; + return point.X >= bounds.Lo.X + && point.Y >= bounds.Lo.Y + && point.Z >= bounds.Lo.Z + && point.X <= bounds.Hi.X + && point.Y <= bounds.Hi.Y; + } - Vector3 rPos = pos - 0.1f * down; - float dist = float.PositiveInfinity; - Ray ray = new(rPos, down); - bool hit = IntersectRay(ray, ref dist, false); - if (hit) - z_dist = dist - 0.1f; - return hit; + public enum InsideResult + { + Inside = 0, + MaybeInside = 1, + Above = 2, + OutOfBounds = -1 + } + + public InsideResult IsInsideObject(Ray ray, out float z_dist) + { + z_dist = 0; + + if (triangles.Empty() || !IsInsideOrAboveBound(iBound, ray.Origin)) + return InsideResult.OutOfBounds; + + if (meshTree.bound().Hi.Z >= ray.Origin.Z) + { + float dist = float.PositiveInfinity; + if (IntersectRay(ray, ref dist, false)) + { + z_dist = dist - 0.1f; + return InsideResult.Inside; + } + if (meshTree.bound().contains(ray.Origin)) + return InsideResult.MaybeInside; + } + else + { + // some group models don't have any floor to intersect with + // so we should attempt to intersect with a model part below this group + // then find back where we originated from (in WorldModel::GetLocationInfo) + float dist = float.PositiveInfinity; + float delta = ray.Origin.Z - meshTree.bound().Hi.Z; + if (IntersectRay(ray.bumpedRay(delta), ref dist, false)) + { + z_dist = dist - 0.1f + delta; + return InsideResult.Above; + } + } + + return InsideResult.OutOfBounds; } public bool GetLiquidLevel(Vector3 pos, out float liqHeight) @@ -321,13 +358,26 @@ namespace Game.Collision if (groupModels.Empty()) return false; - WModelAreaCallback callback = new(groupModels, down); - groupTree.IntersectPoint(p, callback); - if (callback.hit != null) + WModelAreaCallback callback = new(groupModels); + Ray r = new(p - down * 0.1f, down); + float zDist = groupTree.bound().extent().Length(); + groupTree.IntersectRay(r, callback, ref zDist, false); + if (callback.hit[(int)GroupModel.InsideResult.Inside] != null) { info.rootId = (int)RootWMOID; - info.hitModel = callback.hit; - dist = callback.zDist; + info.hitModel = callback.hit[(int)GroupModel.InsideResult.Inside]; + dist = zDist; + return true; + } + + // some group models don't have any floor to intersect with + // so we should attempt to intersect with a model part below the group `p` is in (stored in GroupModel::ABOVE) + // then find back where we originated from (GroupModel::MAYBE_INSIDE) + if (callback.hit[(int)GroupModel.InsideResult.MaybeInside] != null && callback.hit[(int)GroupModel.InsideResult.Above] != null) + { + info.rootId = (int)RootWMOID; + info.hitModel = callback.hit[(int)GroupModel.InsideResult.MaybeInside]; + dist = zDist; return true; } return false; diff --git a/Source/Game/Conditions/Condition.cs b/Source/Game/Conditions/Condition.cs index e155fd9a4..2b61d5725 100644 --- a/Source/Game/Conditions/Condition.cs +++ b/Source/Game/Conditions/Condition.cs @@ -66,7 +66,7 @@ namespace Game.Conditions BattlegroundMap bgMap = map.ToBattlegroundMap(); if (bgMap != null) { - ZoneScript zoneScript = bgMap.GetBG(); + ZoneScript zoneScript = bgMap.GetBattlegroundScript(); switch ((InstanceInfo)ConditionValue3) { case InstanceInfo.Data: @@ -446,11 +446,7 @@ namespace Game.Conditions case ConditionTypes.PlayerCondition: { if (player != null) - { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(ConditionValue1); - if (playerCondition != null) - condMeets = ConditionManager.IsPlayerMeetingCondition(player, playerCondition); - } + condMeets = ConditionManager.IsPlayerMeetingCondition(player, ConditionValue1); break; } case ConditionTypes.PrivateObject: diff --git a/Source/Game/Conditions/ConditionManager.cs b/Source/Game/Conditions/ConditionManager.cs index ffd543562..c420575b2 100644 --- a/Source/Game/Conditions/ConditionManager.cs +++ b/Source/Game/Conditions/ConditionManager.cs @@ -505,6 +505,41 @@ namespace Game foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.Graveyard]) AddToGraveyardData(id, conditions); + bool isPlayerConditionIdUsedByCondition(int playerConditionId, List conditions, Dictionary>> store) + { + return conditions.Any(condition => + { + if (condition.ConditionType == ConditionTypes.PlayerCondition) + { + if (condition.ConditionValue1 == playerConditionId) + return true; + + var playerCondList = store[ConditionSourceType.PlayerCondition].LookupByKey(new ConditionId(0, (int)condition.ConditionValue1, 0)); + if (playerCondList != null) + if (isPlayerConditionIdUsedByCondition(playerConditionId, playerCondList, store)) + return true; + } + else if (condition.ReferenceId != 0) + { + var refList = store[ConditionSourceType.ReferenceCondition].LookupByKey(new ConditionId(condition.ReferenceId, 0, 0)); + if (refList != null) + if (isPlayerConditionIdUsedByCondition(playerConditionId, refList, store)) + return true; + } + return false; + }); + } + + foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.PlayerCondition]) + { + if (isPlayerConditionIdUsedByCondition(id.SourceEntry, conditions, ConditionStorage)) + { + Log.outError(LogFilter.Sql, $"[Condition SourceType: CONDITION_SOURCE_TYPE_PLAYER_CONDITION, SourceGroup: {id.SourceGroup}, SourceEntry: {id.SourceEntry}, SourceId: {id.SourceId}] " + + $"has a circular reference to player condition id {id.SourceEntry}, removed all conditions for this SourceEntry!"); + conditions.Clear(); + } + } + Log.outInfo(LogFilter.ServerLoading, "Loaded {0} conditions in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } @@ -1086,10 +1121,6 @@ namespace Game return false; } break; - case ConditionSourceType.GossipMenu: - case ConditionSourceType.GossipMenuOption: - case ConditionSourceType.SmartEvent: - break; case ConditionSourceType.Graveyard: if (Global.ObjectMgr.FindGraveyardData((uint)cond.SourceEntry, cond.SourceGroup) == null) { @@ -1183,6 +1214,11 @@ namespace Game } break; } + case ConditionSourceType.GossipMenu: + case ConditionSourceType.GossipMenuOption: + case ConditionSourceType.SmartEvent: + case ConditionSourceType.PlayerCondition: + break; default: Log.outError(LogFilter.Sql, $"{cond.ToString()} Invalid ConditionSourceType in `condition` table, ignoring."); return false; @@ -1892,6 +1928,21 @@ namespace Game return 0; } + public static bool IsPlayerMeetingCondition(Player player, uint conditionId) + { + if (conditionId == 0) + return true; + + if (!Global.ConditionMgr.IsObjectMeetingNotGroupedConditions(ConditionSourceType.PlayerCondition, conditionId, player)) + return false; + + var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(conditionId); + if (playerCondition != null) + return IsPlayerMeetingCondition(player, playerCondition); + + return true; + } + public static bool IsPlayerMeetingCondition(Player player, PlayerConditionRecord condition) { ContentTuningLevels? levels = Global.DB2Mgr.GetContentTuningData(condition.ContentTuningID, player.m_playerData.CtrOptions.GetValue().ContentTuningConditionMask); @@ -2957,7 +3008,8 @@ namespace Game "AreaTrigger Client Triggered", "Trainer Spell", "Object Visibility (by ID)", - "Spawn Group" + "Spawn Group", + "Player Condition" }; public ConditionTypeInfo[] StaticConditionTypeData = diff --git a/Source/Game/DataStorage/Structs/A_Records.cs b/Source/Game/DataStorage/Structs/A_Records.cs index 682179aa1..9d02fd072 100644 --- a/Source/Game/DataStorage/Structs/A_Records.cs +++ b/Source/Game/DataStorage/Structs/A_Records.cs @@ -26,6 +26,8 @@ namespace Game.DataStorage public uint CriteriaTree; public ushort SharesCriteria; public int CovenantID; + public int HiddenBeforeDisplaySeason; // hidden in UI before this DisplaySeason is active + public int LegacyAfterTimeEvent; // category changes clientside to Legacy after this TimeEvent is passed } public sealed class AchievementCategoryRecord @@ -54,8 +56,6 @@ namespace Game.DataStorage public ushort BattleMasterListID; public byte PriorityMin; public byte PriorityMax; - public int ItemID; - public uint ItemQuantity; public ushort CurrencyType; public uint CurrencyQuantity; public ushort UiMapID; diff --git a/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs b/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs index 68e8f947c..cca9d9f2f 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs @@ -285,7 +285,7 @@ namespace Game.Entities public class AreaTriggerSpawn : SpawnData { - public AreaTriggerId Id; + public new AreaTriggerId Id; public uint? SpellForVisuals; public AreaTriggerSpawn() : base(SpawnObjectType.AreaTrigger) { } diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 90ede8fa9..5099957eb 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -2588,11 +2588,15 @@ namespace Game.Entities // Send a message to LocalDefense channel for players opposition team in the zone public void SendZoneUnderAttackMessage(Player attacker) { - Team enemy_team = attacker.GetTeam(); - ZoneUnderAttack packet = new(); packet.AreaID = (int)GetAreaId(); - Global.WorldMgr.SendGlobalMessage(packet, null, (enemy_team == Team.Alliance ? Team.Horde : Team.Alliance)); + packet.Write(); + + Team enemyTeam = attacker.GetTeam(); + if (enemyTeam != Team.Alliance) + Global.WorldMgr.SendGlobalMessage(packet, null, Team.Alliance); + if (enemyTeam != Team.Horde) + Global.WorldMgr.SendGlobalMessage(packet, null, Team.Horde); } public void SetCanMelee(bool canMelee, bool fleeFromMelee = false) diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 46e95003d..f5ecf1cef 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -290,9 +290,10 @@ namespace Game.Entities m_goValue.FishingHole.MaxOpens = RandomHelper.URand(GetGoInfo().FishingHole.minRestock, GetGoInfo().FishingHole.maxRestock); break; case GameObjectTypes.DestructibleBuilding: - m_goValue.Building.Health = 20000;//goinfo.DestructibleBuilding.intactNumHits + goinfo.DestructibleBuilding.damagedNumHits; - m_goValue.Building.MaxHealth = m_goValue.Building.Health; + m_goValue.Building.DestructibleHitpoint = Global.ObjectMgr.GetDestructibleHitpoint(GetGoInfo().DestructibleBuilding.HealthRec); + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint != null ? m_goValue.Building.DestructibleHitpoint.GetMaxHealth() : 0; SetGoAnimProgress(255); + // yes, even after the updatefield rewrite this garbage hack is still in client SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.ParentRotation), new Quaternion(goInfo.DestructibleBuilding.DestructibleModelRec, 0f, 0f, 0f)); break; @@ -1366,13 +1367,24 @@ namespace Game.Entities } } + public bool CanActivateForPlayer(Player target) + { + if (!MeetsInteractCondition(target)) + return false; + + if (!ActivateToQuest(target)) + return false; + + return true; + } + public bool ActivateToQuest(Player target) { if (target.HasQuestForGO((int)GetEntry())) return true; if (!Global.ObjectMgr.IsGameObjectForQuests(GetEntry())) - return false; + return true; switch (GetGoType()) { @@ -1393,9 +1405,6 @@ namespace Game.Entities || LootStorage.Gameobject.HaveQuestLootForPlayer(GetGoInfo().Chest.chestPersonalLoot, target) || LootStorage.Gameobject.HaveQuestLootForPlayer(GetGoInfo().Chest.chestPushLoot, target)) { - Battleground bg = target.GetBattleground(); - if (bg != null) - return bg.CanActivateGO((int)GetEntry(), (uint)bg.GetPlayerTeam(target.GetGUID())); return true; } break; @@ -1406,6 +1415,12 @@ namespace Game.Entities return true; break; } + case GameObjectTypes.SpellFocus: + { + if (target.GetQuestStatus(GetGoInfo().SpellFocus.questID) == QuestStatus.Incomplete) + return true; + break; + } case GameObjectTypes.Goober: { if (target.GetQuestStatus(GetGoInfo().Goober.questID) == QuestStatus.Incomplete) @@ -1701,10 +1716,6 @@ namespace Game.Entities if (player == null) return; - Battleground bg = player.GetBattleground(); - if (bg != null && !bg.CanActivateGO((int)GetEntry(), (uint)bg.GetPlayerTeam(user.GetGUID()))) - return; - GameObjectTemplate info = GetGoInfo(); if (loot == null && info.GetLootId() != 0) { @@ -2250,7 +2261,6 @@ namespace Game.Entities break; } - case GameObjectTypes.FlagStand: // 24 { if (!user.IsTypeId(TypeId.Player)) @@ -2260,29 +2270,15 @@ namespace Game.Entities if (player.CanUseBattlegroundObject(this)) { - // in Battlegroundcheck - Battleground bg = player.GetBattleground(); - if (bg == null) - return; - if (player.GetVehicle() != null) return; player.RemoveAurasByType(AuraType.ModStealth); player.RemoveAurasByType(AuraType.ModInvisibility); - // BG flag click - // AB: - // 15001 - // 15002 - // 15003 - // 15004 - // 15005 - bg.EventPlayerClickedOnFlag(player, this); return; //we don;t need to delete flag ... it is despawned! } break; } - case GameObjectTypes.FishingHole: // 25 { if (!user.IsTypeId(TypeId.Player)) @@ -2290,7 +2286,7 @@ namespace Game.Entities Player player = user.ToPlayer(); - Loot loot = new Loot(GetMap(), GetGUID(), LootType.Fishinghole, null); + Loot loot = new(GetMap(), GetGUID(), LootType.Fishinghole, null); loot.FillLoot(GetGoInfo().GetLootId(), LootStorage.Gameobject, player, true, false, LootModes.Default, ItemBonusMgr.GetContextForPlayer(GetMap().GetMapDifficulty(), player)); m_personalLoot[player.GetGUID()] = loot; @@ -2298,7 +2294,6 @@ namespace Game.Entities player.UpdateCriteria(CriteriaType.CatchFishInFishingHole, GetGoInfo().entry); return; } - case GameObjectTypes.FlagDrop: // 26 { if (!user.IsTypeId(TypeId.Player)) @@ -2308,11 +2303,6 @@ namespace Game.Entities if (player.CanUseBattlegroundObject(this)) { - // in Battlegroundcheck - Battleground bg = player.GetBattleground(); - if (bg == null) - return; - if (player.GetVehicle() != null) return; @@ -2325,24 +2315,8 @@ namespace Game.Entities // EotS: // 184142 - Netherstorm Flag GameObjectTemplate info = GetGoInfo(); - if (info != null) - { - switch (info.entry) - { - case 179785: // Silverwing Flag - case 179786: // Warsong Flag - if (bg.GetTypeID() == BattlegroundTypeId.WS) - bg.EventPlayerClickedOnFlag(player, this); - break; - case 184142: // Netherstorm Flag - if (bg.GetTypeID() == BattlegroundTypeId.EY) - bg.EventPlayerClickedOnFlag(player, this); - break; - } - - if (info.FlagDrop.eventID != 0) - GameEvents.Trigger(info.FlagDrop.eventID, player, this); - } + if (info != null && info.FlagDrop.eventID != 0) + GameEvents.Trigger(info.FlagDrop.eventID, player, this); //this cause to call return, all flags must be deleted here!! spellId = 0; Delete(); @@ -2462,10 +2436,9 @@ namespace Game.Entities return; Player player = user.ToPlayer(); - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(info.ItemForge.conditionID1); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(player, playerCondition)) - return; + + if (!MeetsInteractCondition(player)) + return; switch (info.ItemForge.ForgeType) { @@ -2743,7 +2716,7 @@ namespace Game.Entities public void SetLocalRotation(float qx, float qy, float qz, float qw) { - Quaternion rotation = new Quaternion(qx, qy, qz, qw); + Quaternion rotation = new(qx, qy, qz, qw); rotation = Quaternion.Multiply(rotation, 1.0f / MathF.Sqrt(Quaternion.Dot(rotation, rotation))); m_localRotation.X = rotation.X; @@ -2880,7 +2853,7 @@ namespace Game.Entities public void ModifyHealth(int change, WorldObject attackerOrHealer = null, uint spellId = 0) { - if (m_goValue.Building.MaxHealth == 0 || change == 0) + if (m_goValue.Building.DestructibleHitpoint == null || change == 0) return; // prevent double destructions of the same object @@ -2889,13 +2862,13 @@ namespace Game.Entities if (m_goValue.Building.Health + change <= 0) m_goValue.Building.Health = 0; - else if (m_goValue.Building.Health + change >= m_goValue.Building.MaxHealth) - m_goValue.Building.Health = m_goValue.Building.MaxHealth; + else if (m_goValue.Building.Health + change >= m_goValue.Building.DestructibleHitpoint.GetMaxHealth()) + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.GetMaxHealth(); else m_goValue.Building.Health += (uint)change; // Set the health bar, value = 255 * healthPct; - SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.MaxHealth); + SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.DestructibleHitpoint.GetMaxHealth()); // dealing damage, send packet Player player = attackerOrHealer != null ? attackerOrHealer.GetCharmerOrOwnerPlayerOrPlayerItself() : null; @@ -2917,9 +2890,9 @@ namespace Game.Entities if (m_goValue.Building.Health == 0) newState = GameObjectDestructibleState.Destroyed; - else if (m_goValue.Building.Health < m_goValue.Building.MaxHealth / 2) + else if (m_goValue.Building.Health < m_goValue.Building.DestructibleHitpoint.DamagedNumHits) newState = GameObjectDestructibleState.Damaged; - else if (m_goValue.Building.Health == m_goValue.Building.MaxHealth) + else if (m_goValue.Building.Health == m_goValue.Building.DestructibleHitpoint.GetMaxHealth()) newState = GameObjectDestructibleState.Intact; if (newState == GetDestructibleState()) @@ -2938,9 +2911,9 @@ namespace Game.Entities case GameObjectDestructibleState.Intact: RemoveFlag(GameObjectFlags.Damaged | GameObjectFlags.Destroyed); SetDisplayId(m_goInfo.displayId); - if (setHealth) + if (setHealth && m_goValue.Building.DestructibleHitpoint != null) { - m_goValue.Building.Health = m_goValue.Building.MaxHealth; + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.GetMaxHealth(); SetGoAnimProgress(255); } EnableCollision(true); @@ -2959,12 +2932,13 @@ namespace Game.Entities if (modelData != null) if (modelData.State1Wmo != 0) modelId = modelData.State1Wmo; + SetDisplayId(modelId); - if (setHealth) + if (setHealth && m_goValue.Building.DestructibleHitpoint != null) { - m_goValue.Building.Health = 10000;//m_goInfo.DestructibleBuilding.damagedNumHits; - uint maxHealth = m_goValue.Building.MaxHealth; + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.DamagedNumHits; + uint maxHealth = m_goValue.Building.DestructibleHitpoint.GetMaxHealth(); // in this case current health is 0 anyway so just prevent crashing here if (maxHealth == 0) maxHealth = 1; @@ -2978,14 +2952,6 @@ namespace Game.Entities GameEvents.Trigger(GetGoInfo().DestructibleBuilding.DestroyedEvent, attackerOrHealer, this); GetAI().Destroyed(attackerOrHealer, m_goInfo.DestructibleBuilding.DestroyedEvent); - Player player = attackerOrHealer != null ? attackerOrHealer.GetCharmerOrOwnerPlayerOrPlayerItself() : null; - if (player != null) - { - Battleground bg = player.GetBattleground(); - if (bg != null) - bg.DestroyGate(player, this); - } - RemoveFlag(GameObjectFlags.Damaged); SetFlag(GameObjectFlags.Destroyed); @@ -2994,6 +2960,7 @@ namespace Game.Entities if (modelData != null) if (modelData.State2Wmo != 0) modelId = modelData.State2Wmo; + SetDisplayId(modelId); if (setHealth) @@ -3018,9 +2985,9 @@ namespace Game.Entities SetDisplayId(modelId); // restores to full health - if (setHealth) + if (setHealth & m_goValue.Building.DestructibleHitpoint != null) { - m_goValue.Building.Health = m_goValue.Building.MaxHealth; + m_goValue.Building.Health = m_goValue.Building.DestructibleHitpoint.GetMaxHealth(); SetGoAnimProgress(255); } EnableCollision(true); @@ -3318,8 +3285,7 @@ namespace Game.Entities public List GetPauseTimes() { - GameObjectType.Transport transport = m_goTypeImpl as GameObjectType.Transport; - if (transport != null) + if (m_goTypeImpl is GameObjectType.Transport transport) return transport.GetPauseTimes(); return null; @@ -3655,8 +3621,7 @@ namespace Game.Entities if (GetGoType() != GameObjectTypes.NewFlag) return 0; - GameObjectType.NewFlag newFlag = m_goTypeImpl as GameObjectType.NewFlag; - if (newFlag == null) + if (m_goTypeImpl is not GameObjectType.NewFlag newFlag) return 0; return newFlag.GetState(); @@ -3667,8 +3632,7 @@ namespace Game.Entities if (GetGoType() != GameObjectTypes.NewFlag) return ObjectGuid.Empty; - GameObjectType.NewFlag newFlag = m_goTypeImpl as GameObjectType.NewFlag; - if (newFlag == null) + if (m_goTypeImpl is not GameObjectType.NewFlag newFlag) return ObjectGuid.Empty; return newFlag.GetCarrierGUID(); @@ -3679,8 +3643,7 @@ namespace Game.Entities if (GetGoType() != GameObjectTypes.NewFlag) return 0; - GameObjectType.NewFlag newFlag = m_goTypeImpl as GameObjectType.NewFlag; - if (newFlag == null) + if (m_goTypeImpl is not GameObjectType.NewFlag newFlag) return 0; return newFlag.GetTakenFromBaseTime(); @@ -3688,8 +3651,7 @@ namespace Game.Entities public List GetInsidePlayers() { - ControlZone controlZone = m_goTypeImpl as ControlZone; - if (controlZone != null) + if (m_goTypeImpl is ControlZone controlZone) return controlZone.GetInsidePlayers(); return null; @@ -3697,15 +3659,7 @@ namespace Game.Entities public bool MeetsInteractCondition(Player user) { - if (m_goInfo.GetConditionID1() == 0) - return true; - - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(m_goInfo.GetConditionID1()); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(user, playerCondition)) - return false; - - return true; + return ConditionManager.IsPlayerMeetingCondition(user, m_goInfo.GetConditionID1()); } PerPlayerState GetOrCreatePerPlayerStates(ObjectGuid guid) @@ -3797,17 +3751,17 @@ namespace Game.Entities public GameObjectTypes GetGoType() { return (GameObjectTypes)(sbyte)m_gameObjectData.TypeID; } public void SetGoType(GameObjectTypes type) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.TypeID), (sbyte)type); } public GameObjectState GetGoState() { return (GameObjectState)(sbyte)m_gameObjectData.State; } - uint GetGoArtKit() { return m_gameObjectData.ArtKit; } - byte GetGoAnimProgress() { return m_gameObjectData.PercentHealth; } + public uint GetGoArtKit() { return m_gameObjectData.ArtKit; } + public byte GetGoAnimProgress() { return m_gameObjectData.PercentHealth; } public void SetGoAnimProgress(uint animprogress) { SetUpdateFieldValue(m_values.ModifyValue(m_gameObjectData).ModifyValue(m_gameObjectData.PercentHealth), (byte)animprogress); } public LootState GetLootState() { return m_lootState; } public LootModes GetLootMode() { return m_LootMode; } - bool HasLootMode(LootModes lootMode) { return Convert.ToBoolean(m_LootMode & lootMode); } - void SetLootMode(LootModes lootMode) { m_LootMode = lootMode; } - void AddLootMode(LootModes lootMode) { m_LootMode |= lootMode; } - void RemoveLootMode(LootModes lootMode) { m_LootMode &= ~lootMode; } - void ResetLootMode() { m_LootMode = LootModes.Default; } + public bool HasLootMode(LootModes lootMode) { return Convert.ToBoolean(m_LootMode & lootMode); } + public void SetLootMode(LootModes lootMode) { m_LootMode = lootMode; } + public void AddLootMode(LootModes lootMode) { m_LootMode |= lootMode; } + public void RemoveLootMode(LootModes lootMode) { m_LootMode &= ~lootMode; } + public void ResetLootMode() { m_LootMode = LootModes.Default; } public void AddToSkillupList(ObjectGuid PlayerGuid) { m_SkillupList.Add(PlayerGuid); } public bool IsInSkillupList(ObjectGuid PlayerGuid) @@ -3818,17 +3772,17 @@ namespace Game.Entities return false; } - void ClearSkillupList() { m_SkillupList.Clear(); } + public void ClearSkillupList() { m_SkillupList.Clear(); } public void AddUse() { ++m_usetimes; } public uint GetUseCount() { return m_usetimes; } - uint GetUniqueUseCount() { return (uint)m_unique_users.Count; } + public uint GetUniqueUseCount() { return (uint)m_unique_users.Count; } - List GetTapList() { return m_tapList; } - void SetTapList(List tapList) { m_tapList = tapList; } + public List GetTapList() { return m_tapList; } + public void SetTapList(List tapList) { m_tapList = tapList; } - bool HasLootRecipient() { return !m_tapList.Empty(); } + public bool HasLootRecipient() { return !m_tapList.Empty(); } public override uint GetLevelForTarget(WorldObject target) { @@ -4006,14 +3960,9 @@ namespace Game.Entities } // Base class for GameObject type specific implementations - public class GameObjectTypeBase + public class GameObjectTypeBase(GameObject owner) { - protected GameObject _owner; - - public GameObjectTypeBase(GameObject owner) - { - _owner = owner; - } + protected GameObject _owner = owner; public virtual void Update(uint diff) { } public virtual void OnStateChanged(GameObjectState oldState, GameObjectState newState) { } @@ -4057,7 +4006,7 @@ namespace Game.Entities public struct building { public uint Health; - public uint MaxHealth; + public DestructibleHitpoint DestructibleHitpoint; } //42 GAMEOBJECT_TYPE_CAPTURE_POINT public struct capturePoint @@ -4149,12 +4098,12 @@ namespace Game.Entities uint now = GameTime.GetGameTimeMS(); uint period = GetTransportPeriod(); - uint newProgress = 0; + uint newProgress; if (_stopFrames.Empty()) newProgress = now % period; else { - int stopTargetTime = 0; + int stopTargetTime; if (_owner.GetGoState() == GameObjectState.TransportActive) stopTargetTime = 0; else @@ -4179,7 +4128,7 @@ namespace Game.Entities progressPct = pathPctBetweenStops * timeSinceStopProgressPct + stopSourcePathPct; if (progressPct > 1.0f) - progressPct = progressPct - 1.0f; + progressPct = -1.0f; } else { @@ -4379,8 +4328,7 @@ namespace Game.Entities { foreach (WorldObject passenger in _passengers) { - float x, y, z, o; - passenger.m_movementInfo.transport.pos.GetPosition(out x, out y, out z, out o); + passenger.m_movementInfo.transport.pos.GetPosition(out float x, out float y, out float z, out float o); CalculatePassengerPosition(ref x, ref y, ref z, ref o); ITransport.UpdatePassengerPosition(this, _owner.GetMap(), passenger, x, y, z, o, true); } @@ -4529,7 +4477,7 @@ namespace Game.Entities public long GetTakenFromBaseTime() { return _takenFromBaseTime; } } - class SetNewFlagState : GameObjectTypeBase.CustomCommand + public class SetNewFlagState : GameObjectTypeBase.CustomCommand { FlagState _state; Player _player; @@ -4542,8 +4490,7 @@ namespace Game.Entities public override void Execute(GameObjectTypeBase type) { - NewFlag newFlag = type as NewFlag; - if (newFlag != null) + if (type is NewFlag newFlag) newFlag.SetState(_state, _player); } } @@ -4793,8 +4740,7 @@ namespace Game.Entities public override void Execute(GameObjectTypeBase type) { - ControlZone controlZone = type as ControlZone; - if (controlZone != null) + if (type is ControlZone controlZone) { uint value = controlZone.GetStartingValue(); if (_value.HasValue) diff --git a/Source/Game/Entities/GameObject/GameObjectData.cs b/Source/Game/Entities/GameObject/GameObjectData.cs index c2eed0929..62989d248 100644 --- a/Source/Game/Entities/GameObject/GameObjectData.cs +++ b/Source/Game/Entities/GameObject/GameObjectData.cs @@ -267,6 +267,15 @@ namespace Game.Entities } } + public uint GetQuestID() => type switch + { + GameObjectTypes.Chest => Chest.questID, + GameObjectTypes.Generic => Generic.questID, + GameObjectTypes.SpellFocus => SpellFocus.questID, + GameObjectTypes.Goober => Goober.questID, + _ => 0 + }; + public uint GetConditionID1() => type switch { GameObjectTypes.Door => Door.conditionID1, @@ -1648,4 +1657,13 @@ namespace Game.Entities public GameObjectData() : base(SpawnObjectType.GameObject) { } } + + public class DestructibleHitpoint + { + public uint Id; + public uint IntactNumHits; + public uint DamagedNumHits; + + public uint GetMaxHealth() { return IntactNumHits + DamagedNumHits; } + } } diff --git a/Source/Game/Entities/Item/AzeriteItem.cs b/Source/Game/Entities/Item/AzeriteItem.cs index b84df4be7..8327cf9cc 100644 --- a/Source/Game/Entities/Item/AzeriteItem.cs +++ b/Source/Game/Entities/Item/AzeriteItem.cs @@ -296,11 +296,7 @@ namespace Game.Entities public bool CanUseEssences() { - PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(PlayerConst.PlayerConditionIdUnlockedAzeriteEssences); - if (condition != null) - return ConditionManager.IsPlayerMeetingCondition(GetOwner(), condition); - - return false; + return ConditionManager.IsPlayerMeetingCondition(GetOwner(), PlayerConst.PlayerConditionIdUnlockedAzeriteEssences); } public bool HasUnlockedEssenceSlot(byte slot) diff --git a/Source/Game/Entities/Item/Item.cs b/Source/Game/Entities/Item/Item.cs index 94b56631c..909530f2d 100644 --- a/Source/Game/Entities/Item/Item.cs +++ b/Source/Game/Entities/Item/Item.cs @@ -72,10 +72,8 @@ namespace Game.Entities if (itemProto.GetArtifactID() != artifactAppearanceSet.ArtifactID) continue; - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactAppearance.UnlockPlayerConditionID); - if (playerCondition != null) - if (owner == null || !ConditionManager.IsPlayerMeetingCondition(owner, playerCondition)) - continue; + if (owner == null || !ConditionManager.IsPlayerMeetingCondition(owner, artifactAppearance.UnlockPlayerConditionID)) + continue; SetModifier(ItemModifier.ArtifactAppearanceId, artifactAppearance.Id); SetAppearanceModId(artifactAppearance.ItemAppearanceModifierID); @@ -591,13 +589,9 @@ namespace Game.Entities if (_bonusData.GemRelicType[e - EnchantmentSlot.Sock1] != -1) { ArtifactPowerPickerRecord artifactPowerPicker = CliDB.ArtifactPowerPickerStorage.LookupByKey(enchant.EffectArg[i]); - if (artifactPowerPicker != null) - { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactPowerPicker.PlayerConditionID); - if (playerCondition == null || (owner != null && ConditionManager.IsPlayerMeetingCondition(owner, playerCondition))) - if (artifactPower.Label == _bonusData.GemRelicType[e - EnchantmentSlot.Sock1]) - power.CurrentRankWithBonus += (byte)enchant.EffectPointsMin[i]; - } + if (artifactPowerPicker != null && owner != null && ConditionManager.IsPlayerMeetingCondition(owner, artifactPowerPicker.PlayerConditionID)) + if (artifactPower.Label == _bonusData.GemRelicType[e - EnchantmentSlot.Sock1]) + power.CurrentRankWithBonus += (byte)enchant.EffectPointsMin[i]; } break; default: @@ -793,7 +787,7 @@ namespace Game.Entities return !IsInBag() && (m_slot < EquipmentSlot.End || (m_slot >= ProfessionSlots.Start && m_slot < ProfessionSlots.End)); } - + public bool CanBeTraded(bool mail = false, bool trade = false) { if (m_lootGenerated) @@ -876,7 +870,7 @@ namespace Game.Entities return cost; } - + bool HasEnchantRequiredSkill(Player player) { // Check all enchants for required skill @@ -995,11 +989,11 @@ namespace Game.Entities { var oldEnchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(slot)); if (oldEnchant != null && !oldEnchant.HasFlag(SpellItemEnchantmentFlags.DoNotLog)) - owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), ObjectGuid.Empty, GetGUID(), GetEntry(), oldEnchant.Id, (uint)slot); + owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), ObjectGuid.Empty, GetGUID(), GetEntry(), oldEnchant.Id, (uint)slot); var newEnchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(id); if (newEnchant != null && !newEnchant.HasFlag(SpellItemEnchantmentFlags.DoNotLog)) - owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, (uint)slot); + owner.GetSession().SendEnchantmentLog(GetOwnerGUID(), caster, GetGUID(), GetEntry(), id, (uint)slot); } ApplyArtifactPowerEnchantmentBonuses(slot, GetEnchantmentId(slot), false, owner); @@ -2059,7 +2053,7 @@ namespace Game.Entities return itemModifiedAppearanceId; } - + public uint GetVisibleSecondaryModifiedAppearanceId(Player owner) { uint itemModifiedAppearanceId = GetModifier(ItemConst.SecondaryAppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()]); @@ -2068,7 +2062,7 @@ namespace Game.Entities return itemModifiedAppearanceId; } - + public uint GetVisibleEnchantmentId(Player owner) { uint enchantmentId = GetModifier(ItemConst.IllusionModifierSlotBySpec[owner.GetActiveTalentGroup()]); @@ -2290,8 +2284,7 @@ namespace Game.Entities ArtifactPowerPickerRecord artifactPowerPicker = CliDB.ArtifactPowerPickerStorage.LookupByKey(enchant.EffectArg[i]); if (artifactPowerPicker != null) { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactPowerPicker.PlayerConditionID); - if (playerCondition == null || ConditionManager.IsPlayerMeetingCondition(owner, playerCondition)) + if (ConditionManager.IsPlayerMeetingCondition(owner, artifactPowerPicker.PlayerConditionID)) { for (int artifactPowerIndex = 0; artifactPowerIndex < m_itemData.ArtifactPowers.Size(); ++artifactPowerIndex) { @@ -2413,7 +2406,7 @@ namespace Game.Entities { return $"{base.GetDebugInfo()}\nOwner: {GetOwnerGUID()} Count: {GetCount()} BagSlot: {GetBagSlot()} Slot: {GetSlot()} Equipped: {IsEquipped()}"; } - + public static Item NewItemOrBag(ItemTemplate proto) { if (proto.GetInventoryType() == InventoryType.Bag) @@ -2685,8 +2678,8 @@ namespace Game.Entities public void SetChildItem(ObjectGuid childItem) { m_childItem = childItem; } public ItemEffectRecord[] GetEffects() { return _bonusData.Effects[0.._bonusData.EffectCount]; } - - public override Loot GetLootForPlayer(Player player) { return loot; } + + public override Loot GetLootForPlayer(Player player) { return loot; } //Static public static bool ItemCanGoIntoBag(ItemTemplate pProto, ItemTemplate pBagProto) diff --git a/Source/Game/Entities/Item/ItemBonusManager.cs b/Source/Game/Entities/Item/ItemBonusManager.cs index e52bbd141..34de258ba 100644 --- a/Source/Game/Entities/Item/ItemBonusManager.cs +++ b/Source/Game/Entities/Item/ItemBonusManager.cs @@ -50,6 +50,9 @@ namespace Game.Entities public static ItemContext GetContextForPlayer(MapDifficultyRecord mapDifficulty, Player player) { + if (mapDifficulty == null) + return ItemContext.None; + ItemContext evalContext(ItemContext currentContext, ItemContext newContext) { if (newContext == ItemContext.None) @@ -81,11 +84,7 @@ namespace Game.Entities bool meetsPlayerCondition = false; if (player != null) - { - var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(itemContextPickerEntry.PlayerConditionID); - if (playerCondition != null) - meetsPlayerCondition = ConditionManager.IsPlayerMeetingCondition(player, playerCondition); - } + meetsPlayerCondition = ConditionManager.IsPlayerMeetingCondition(player, itemContextPickerEntry.PlayerConditionID); if ((itemContextPickerEntry.Flags & 0x1) != 0) meetsPlayerCondition = !meetsPlayerCondition; diff --git a/Source/Game/Entities/Object/Update/UpdateFields.cs b/Source/Game/Entities/Object/Update/UpdateFields.cs index 4898c35b2..787002124 100644 --- a/Source/Game/Entities/Object/Update/UpdateFields.cs +++ b/Source/Game/Entities/Object/Update/UpdateFields.cs @@ -112,29 +112,33 @@ namespace Game.Entities ushort pathProgress = 0xFFFF; switch (gameObject.GetGoType()) { + case GameObjectTypes.Button: + case GameObjectTypes.Goober: + if (gameObject.GetGoInfo().GetQuestID() != 0 || gameObject.GetGoInfo().GetConditionID1() != 0) + { + if (gameObject.CanActivateForPlayer(receiver)) + { + dynFlags |= GameObjectDynamicLowFlags.Highlight; + if (gameObject.GetGoStateFor(receiver.GetGUID()) != GameObjectState.Active) + dynFlags |= GameObjectDynamicLowFlags.Activate; + } + } + break; case GameObjectTypes.QuestGiver: - if (gameObject.ActivateToQuest(receiver)) + if (gameObject.CanActivateForPlayer(receiver)) dynFlags |= GameObjectDynamicLowFlags.Activate; break; case GameObjectTypes.Chest: - if (gameObject.ActivateToQuest(receiver)) + if (gameObject.CanActivateForPlayer(receiver)) dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight; else if (receiver.IsGameMaster()) - dynFlags |= GameObjectDynamicLowFlags.Activate; - break; - case GameObjectTypes.Goober: - if (gameObject.ActivateToQuest(receiver)) - { - dynFlags |= GameObjectDynamicLowFlags.Highlight; - if (gameObject.GetGoStateFor(receiver.GetGUID()) != GameObjectState.Active) - dynFlags |= GameObjectDynamicLowFlags.Activate; - } - else if (receiver.IsGameMaster()) - dynFlags |= GameObjectDynamicLowFlags.Activate; + dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle; break; case GameObjectTypes.Generic: - if (gameObject.ActivateToQuest(receiver)) - dynFlags |= GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight; + case GameObjectTypes.SpellFocus: + if (gameObject.GetGoInfo().GetQuestID() != 0 || gameObject.GetGoInfo().GetConditionID1() != 0) + if (gameObject.CanActivateForPlayer(receiver)) + dynFlags |= GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight; break; case GameObjectTypes.Transport: case GameObjectTypes.MapObjTransport: @@ -150,7 +154,7 @@ namespace Game.Entities dynFlags &= ~GameObjectDynamicLowFlags.NoInterract; break; case GameObjectTypes.GatheringNode: - if (gameObject.ActivateToQuest(receiver)) + if (gameObject.CanActivateForPlayer(receiver)) dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight; if (gameObject.GetGoStateFor(receiver.GetGUID()) == GameObjectState.Active) dynFlags |= GameObjectDynamicLowFlags.Depleted; @@ -159,7 +163,7 @@ namespace Game.Entities break; } - if (!gameObject.MeetsInteractCondition(receiver)) + if (!receiver.IsGameMaster() && !gameObject.MeetsInteractCondition(receiver)) dynFlags |= GameObjectDynamicLowFlags.NoInterract; unitDynFlags = ((uint)pathProgress << 16) | (uint)dynFlags; @@ -2789,22 +2793,25 @@ namespace Game.Entities public UpdateField HonorLevel = new(0, 30); public UpdateField LogoutTime = new(0, 31); public UpdateFieldString Name = new(32, 33); - public UpdateField Field_B0 = new(32, 34); - public UpdateField Field_B4 = new(32, 35); + public UpdateField Field_1AC = new(32, 34); + public UpdateField Field_1B0 = new(32, 35); public UpdateField CurrentBattlePetSpeciesID = new(32, 36); public UpdateField CtrOptions = new(32, 37); public UpdateField CovenantID = new(32, 38); public UpdateField SoulbindID = new(32, 39); public UpdateField DungeonScore = new(32, 40); - public OptionalUpdateField DeclinedNames = new(32, 41); - public UpdateField PersonalTabard = new(32, 42); - public UpdateFieldArray PartyType = new(2, 43, 44); - public UpdateFieldArray QuestLog = new(175, 46, 47); - public UpdateFieldArray VisibleItems = new(19, 222, 223); - public UpdateFieldArray AvgItemLevel = new(6, 242, 243); - public UpdateFieldArray Field_3120 = new(19, 249, 250); + public UpdateField SpectateTarget = new(32, 41); + public UpdateField Field_200 = new(32, 42); + public OptionalUpdateField DeclinedNames = new(32, 43); + public UpdateField PersonalTabard = new(32, 44); + public UpdateFieldArray PartyType = new(2, 45, 46); + public UpdateFieldArray QuestLog = new(175, 48, 49); + public UpdateFieldArray VisibleItems = new(19, 224, 225); + public UpdateFieldArray AvgItemLevel = new(6, 244, 245); + public UpdateFieldArray VisibleEquipableSpells = new(16, 251, 252); + public UpdateFieldArray Field_3120 = new(19, 268, 269); - public PlayerData() : base(0, TypeId.Player, 269) { } + public PlayerData() : base(0, TypeId.Player, 288) { } public void WriteCreate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Player owner, Player receiver) { @@ -2854,12 +2861,14 @@ namespace Game.Entities data.WriteUInt32(HonorLevel); data.WriteInt64(LogoutTime); data.WriteInt32(ArenaCooldowns.Size()); - data.WriteInt32(Field_B0); - data.WriteInt32(Field_B4); + data.WriteInt32(Field_1AC); + data.WriteInt32(Field_1B0); data.WriteInt32(CurrentBattlePetSpeciesID); ((CTROptions)CtrOptions).WriteCreate(data, owner, receiver); data.WriteInt32(CovenantID); data.WriteInt32(SoulbindID); + data.WritePackedGuid(SpectateTarget); + data.WriteInt32(Field_200); data.WriteInt32(VisualItemReplacements.Size()); for (int i = 0; i < 19; ++i) { @@ -2899,6 +2908,10 @@ namespace Game.Entities data.WriteBits(DeclinedNames.HasValue(), 1); DungeonScore._value.Write(data); data.WriteString(Name); + for (int i = 0; i < 16; ++i) + { + VisibleEquipableSpells[i].Write(data); + } if (DeclinedNames.HasValue()) { DeclinedNames.GetValue().WriteCreate(data, owner, receiver); @@ -2908,7 +2921,7 @@ namespace Game.Entities public void WriteUpdate(WorldPacket data, UpdateFieldFlag fieldVisibilityFlags, Player owner, Player receiver) { - UpdateMask allowedMaskForTarget = new(269, [0xFFFFFFDDu, 0x00003FFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xC0000000u, 0xFFFFFFFFu, 0x00001FFFu]); + UpdateMask allowedMaskForTarget = new(288, [0xFFFFFFDDu, 0x0000FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFFFu, 0xFFFFFFFFu]); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); WriteUpdate(data, _changesMask & allowedMaskForTarget, false, owner, receiver); } @@ -2916,12 +2929,12 @@ namespace Game.Entities public void AppendAllowedFieldsMaskForFlag(UpdateMask allowedMaskForTarget, UpdateFieldFlag fieldVisibilityFlags) { if (fieldVisibilityFlags.HasFlag(UpdateFieldFlag.PartyMember)) - allowedMaskForTarget.OR(new UpdateMask(269, new[] { 0x00000022u, 0xFFFFC000u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x3FFFFFFFu, 0x00000000u, 0x00000000u })); + allowedMaskForTarget.OR(new UpdateMask(288, [0x00000022u, 0xFFFF0000u, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0x00000000u, 0x00000000u])); } public void FilterDisallowedFieldsMaskForFlag(UpdateMask changesMask, UpdateFieldFlag fieldVisibilityFlags) { - UpdateMask allowedMaskForTarget = new(269, new[] { 0xFFFFFFDDu, 0x00003FFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xC0000000u, 0xFFFFFFFFu, 0x00001FFFu }); + UpdateMask allowedMaskForTarget = new(288, [0xFFFFFFDDu, 0x0000FFFFu, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 0xFFFFFFFFu, 0xFFFFFFFFu]); AppendAllowedFieldsMaskForFlag(allowedMaskForTarget, fieldVisibilityFlags); changesMask.AND(allowedMaskForTarget); } @@ -3137,11 +3150,11 @@ namespace Game.Entities { if (changesMask[34]) { - data.WriteInt32(Field_B0); + data.WriteInt32(Field_1AC); } if (changesMask[35]) { - data.WriteInt32(Field_B4); + data.WriteInt32(Field_1B0); } if (changesMask[36]) { @@ -3159,13 +3172,21 @@ namespace Game.Entities { data.WriteInt32(SoulbindID); } + if (changesMask[41]) + { + data.WritePackedGuid(SpectateTarget); + } if (changesMask[42]) + { + data.WriteInt32(Field_200); + } + if (changesMask[44]) { PersonalTabard.GetValue().WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } if (changesMask[33]) { - data.WriteBits(Name.GetValue().GetByteCount(), 32); + data.WriteBits(Name.GetValue().GetByteCount(), 6); } data.WriteBits(DeclinedNames.HasValue(), 1); data.FlushBits(); @@ -3177,7 +3198,7 @@ namespace Game.Entities { data.WriteString(Name); } - if (changesMask[41]) + if (changesMask[43]) { if (DeclinedNames.HasValue()) { @@ -3185,21 +3206,21 @@ namespace Game.Entities } } } - if (changesMask[43]) + if (changesMask[45]) { for (int i = 0; i < 2; ++i) { - if (changesMask[44 + i]) + if (changesMask[46 + i]) { data.WriteUInt8(PartyType[i]); } } } - if (changesMask[46]) + if (changesMask[48]) { for (int i = 0; i < 175; ++i) { - if (changesMask[47 + i]) + if (changesMask[49 + i]) { if (noQuestLogChangesMask) QuestLog[i].WriteCreate(data, owner, receiver); @@ -3208,36 +3229,46 @@ namespace Game.Entities } } } - if (changesMask[222]) + if (changesMask[224]) { for (int i = 0; i < 19; ++i) { - if (changesMask[223 + i]) + if (changesMask[225 + i]) { VisibleItems[i].WriteUpdate(data, ignoreNestedChangesMask, owner, receiver); } } } - if (changesMask[242]) + if (changesMask[244]) { for (int i = 0; i < 6; ++i) { - if (changesMask[243 + i]) + if (changesMask[245 + i]) { data.WriteFloat(AvgItemLevel[i]); } } } - if (changesMask[249]) + if (changesMask[268]) { for (int i = 0; i < 19; ++i) { - if (changesMask[250 + i]) + if (changesMask[269 + i]) { data.WriteUInt32(Field_3120[i]); } } } + if (changesMask[251]) + { + for (int i = 0; i < 16; ++i) + { + if (changesMask[252 + i]) + { + VisibleEquipableSpells[i].Write(data); + } + } + } data.FlushBits(); } @@ -3275,19 +3306,22 @@ namespace Game.Entities ClearChangesMask(HonorLevel); ClearChangesMask(LogoutTime); ClearChangesMask(Name); - ClearChangesMask(Field_B0); - ClearChangesMask(Field_B4); + ClearChangesMask(Field_1AC); + ClearChangesMask(Field_1B0); ClearChangesMask(CurrentBattlePetSpeciesID); ClearChangesMask(CtrOptions); ClearChangesMask(CovenantID); ClearChangesMask(SoulbindID); ClearChangesMask(DungeonScore); + ClearChangesMask(SpectateTarget); + ClearChangesMask(Field_200); ClearChangesMask(DeclinedNames); ClearChangesMask(PersonalTabard); ClearChangesMask(PartyType); ClearChangesMask(QuestLog); ClearChangesMask(VisibleItems); ClearChangesMask(AvgItemLevel); + ClearChangesMask(VisibleEquipableSpells); ClearChangesMask(Field_3120); _changesMask.ResetAll(); } diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 19e8081da..1b8b64900 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -451,13 +451,14 @@ namespace Game.Entities bool hasMoveCurveID = createProperties != null && createProperties.MoveCurveId != 0; bool hasAreaTriggerSphere = shape.IsSphere(); bool hasAreaTriggerBox = shape.IsBox(); - bool hasAreaTriggerPolygon = createProperties != null && shape.IsPolygon(); + bool hasAreaTriggerPolygon = shape.IsPolygon(); bool hasAreaTriggerCylinder = shape.IsCylinder(); bool hasDisk = shape.IsDisk(); bool hasBoundedPlane = shape.IsBoundedPlane(); bool hasAreaTriggerSpline = areaTrigger.HasSplines(); bool hasOrbit = areaTrigger.HasOrbit(); bool hasMovementScript = false; + bool hasPositionalSoundKitID = false; data.WriteBit(hasAbsoluteOrientation); data.WriteBit(hasDynamicShape); @@ -471,6 +472,7 @@ namespace Game.Entities data.WriteBit(hasMorphCurveID); data.WriteBit(hasFacingCurveID); data.WriteBit(hasMoveCurveID); + data.WriteBit(hasPositionalSoundKitID); data.WriteBit(hasAreaTriggerSphere); data.WriteBit(hasAreaTriggerBox); data.WriteBit(hasAreaTriggerPolygon); @@ -506,6 +508,9 @@ namespace Game.Entities if (hasMoveCurveID) data.WriteUInt32(createProperties.MoveCurveId); + if (hasPositionalSoundKitID) + data.WriteUInt32(0); + if (hasAreaTriggerSphere) { data.WriteFloat(shape.SphereDatas.Radius); @@ -1522,7 +1527,7 @@ namespace Game.Entities BattlegroundMap bgMap = map.ToBattlegroundMap(); if (bgMap != null) - return (ZoneScript)bgMap.GetBG(); + return (ZoneScript)bgMap.GetBattlegroundScript(); if (!map.IsBattlegroundOrArena()) { diff --git a/Source/Game/Entities/Player/CollectionManager.cs b/Source/Game/Entities/Player/CollectionManager.cs index 1257a71d7..ef38ddb29 100644 --- a/Source/Game/Entities/Player/CollectionManager.cs +++ b/Source/Game/Entities/Player/CollectionManager.cs @@ -233,7 +233,7 @@ namespace Game.Entities { return _heirlooms.ContainsKey(itemId); } - + public void UpgradeHeirloom(uint itemId, uint castItem) { Player player = _owner.GetPlayer(); @@ -386,12 +386,8 @@ namespace Game.Entities _mounts[spellId] = flags; // Mount condition only applies to using it, should still learn it. - if (mount.PlayerConditionID != 0) - { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mount.PlayerConditionID); - if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(player, playerCondition)) - return false; - } + if (!ConditionManager.IsPlayerMeetingCondition(player, mount.PlayerConditionID)) + return false; if (!learned) { @@ -859,7 +855,7 @@ namespace Game.Entities } while (knownTransmogIllusions.NextRow()); } - + _transmogIllusions = new(blocks); // Static illusions known by every player @@ -919,7 +915,7 @@ namespace Game.Entities { return transmogIllusionId < _transmogIllusions.Count && _transmogIllusions.Get((int)transmogIllusionId); } - + public bool HasToy(uint itemId) { return _toys.ContainsKey(itemId); } public Dictionary GetAccountToys() { return _toys; } public Dictionary GetAccountHeirlooms() { return _heirlooms; } diff --git a/Source/Game/Entities/Player/Player.Combat.cs b/Source/Game/Entities/Player/Player.Combat.cs index 8f4dbc32f..6140ee712 100644 --- a/Source/Game/Entities/Player/Player.Combat.cs +++ b/Source/Game/Entities/Player/Player.Combat.cs @@ -457,7 +457,7 @@ namespace Game.Entities case DuelCompleteType.Fled: // if initiator and opponent are on the same team // or initiator and opponent are not PvP enabled, forcibly stop attacking - if (GetTeam() == opponent.GetTeam()) + if (GetEffectiveTeam() == opponent.GetEffectiveTeam()) { AttackStop(); opponent.AttackStop(); diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index fcf818ee7..2fa399ddd 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -3612,10 +3612,8 @@ namespace Game.Entities if (GetSession().GetCollectionMgr().HasTransmogIllusion(transmogIllusion.Id)) continue; - var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(transmogIllusion.UnlockConditionID); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) - continue; + if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)transmogIllusion.UnlockConditionID)) + continue; GetSession().GetCollectionMgr().AddTransmogIllusion(transmogIllusion.Id); } diff --git a/Source/Game/Entities/Player/Player.Groups.cs b/Source/Game/Entities/Player/Player.Groups.cs index 19e671c71..4941b3046 100644 --- a/Source/Game/Entities/Player/Player.Groups.cs +++ b/Source/Game/Entities/Player/Player.Groups.cs @@ -252,7 +252,7 @@ namespace Game.Entities case 1: return IsInSameRaidWith(p); case 2: - return GetTeam() == p.GetTeam(); + return GetEffectiveTeam() == p.GetEffectiveTeam(); case 3: return false; } diff --git a/Source/Game/Entities/Player/Player.Items.cs b/Source/Game/Entities/Player/Player.Items.cs index 075198f2d..949f7050d 100644 --- a/Source/Game/Entities/Player/Player.Items.cs +++ b/Source/Game/Entities/Player/Player.Items.cs @@ -2865,8 +2865,7 @@ namespace Game.Entities var limitConditions = Global.DB2Mgr.GetItemLimitCategoryConditions(limitEntry.Id); foreach (ItemLimitCategoryConditionRecord limitCondition in limitConditions) { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(limitCondition.PlayerConditionID); - if (playerCondition == null || ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) + if (ConditionManager.IsPlayerMeetingCondition(this, limitCondition.PlayerConditionID)) limit += (byte)limitCondition.AddQuantity; } @@ -3273,14 +3272,10 @@ namespace Game.Entities return false; } - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(crItem.PlayerConditionId); - if (playerCondition != null) + if (!ConditionManager.IsPlayerMeetingCondition(this, crItem.PlayerConditionId)) { - if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) - { - SendEquipError(InventoryResult.ItemLocked); - return false; - } + SendEquipError(InventoryResult.ItemLocked); + return false; } // check current item amount if it limited @@ -6130,7 +6125,7 @@ namespace Game.Entities Guild guild = GetGuild(); if (guild != null) guild.AddGuildNews(GuildNews.ItemLooted, GetGUID(), 0, item.itemid); - } + } // if aeLooting then we must delay sending out item so that it appears properly stacked in chat if (aeResult == null || newitem == null) diff --git a/Source/Game/Entities/Player/Player.Map.cs b/Source/Game/Entities/Player/Player.Map.cs index e40bfc26a..09f61dadd 100644 --- a/Source/Game/Entities/Player/Player.Map.cs +++ b/Source/Game/Entities/Player/Player.Map.cs @@ -370,7 +370,7 @@ namespace Game.Entities var mapDifficultyConditions = Global.DB2Mgr.GetMapDifficultyConditions(mapDiff.Id); foreach (var pair in mapDifficultyConditions) { - if (!ConditionManager.IsPlayerMeetingCondition(this, pair.Item2)) + if (!ConditionManager.IsPlayerMeetingCondition(this, pair.Item2.Id)) { failedMapDifficultyXCondition = pair.Item1; break; diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 97bfde2e1..96ef9e14b 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -1174,10 +1174,8 @@ namespace Game.Entities { foreach (QuestRewardDisplaySpell displaySpell in quest.RewardDisplaySpell) { - var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(displaySpell.PlayerConditionId); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) - continue; + if (!ConditionManager.IsPlayerMeetingCondition(this, displaySpell.PlayerConditionId)) + continue; SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(displaySpell.SpellId, GetMap().GetDifficultyID()); Unit caster = this; @@ -1588,7 +1586,7 @@ namespace Game.Entities return true; } - public bool SatisfyQuestReputation(Quest qInfo, bool msg) + public bool SatisfyQuestMinReputation(Quest qInfo, bool msg) { uint fIdMin = qInfo.RequiredMinRepFaction; //Min required rep if (fIdMin != 0 && GetReputationMgr().GetReputation(fIdMin) < qInfo.RequiredMinRepValue) @@ -1601,6 +1599,11 @@ namespace Game.Entities return false; } + return true; + } + + public bool SatisfyQuestMaxReputation(Quest qInfo, bool msg) + { uint fIdMax = qInfo.RequiredMaxRepFaction; //Max required rep if (fIdMax != 0 && GetReputationMgr().GetReputation(fIdMax) >= qInfo.RequiredMaxRepValue) { @@ -1615,6 +1618,11 @@ namespace Game.Entities return true; } + bool SatisfyQuestReputation(Quest qInfo, bool msg) + { + return SatisfyQuestMinReputation(qInfo, msg) && SatisfyQuestMaxReputation(qInfo, msg); + } + public bool SatisfyQuestStatus(Quest qInfo, bool msg) { if (GetQuestStatus(qInfo.Id) == QuestStatus.Rewarded) @@ -3297,21 +3305,24 @@ namespace Game.Entities ObjectFieldData objMask = new(); GameObjectFieldData goMask = new(); - if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry()))) + if (m_questObjectiveStatus.ContainsKey((QuestObjectiveType.GameObject, (int)gameObject.GetEntry())) || gameObject.GetGoInfo().GetConditionID1() != 0) objMask.MarkChanged(gameObject.m_objectData.DynamicFlags); - - switch (gameObject.GetGoType()) + else { - case GameObjectTypes.QuestGiver: - case GameObjectTypes.Chest: - case GameObjectTypes.Goober: - case GameObjectTypes.Generic: - case GameObjectTypes.GatheringNode: - if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry())) - objMask.MarkChanged(gameObject.m_objectData.DynamicFlags); - break; - default: - break; + switch (gameObject.GetGoType()) + { + case GameObjectTypes.QuestGiver: + case GameObjectTypes.Chest: + case GameObjectTypes.Generic: + case GameObjectTypes.SpellFocus: + case GameObjectTypes.Goober: + case GameObjectTypes.GatheringNode: + if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry())) + objMask.MarkChanged(gameObject.m_objectData.DynamicFlags); + break; + default: + break; + } } if (objMask.GetUpdateMask().IsAnySet() || goMask.GetUpdateMask().IsAnySet()) diff --git a/Source/Game/Entities/Player/Player.Talents.cs b/Source/Game/Entities/Player/Player.Talents.cs index 3d2a447ec..6a9fbfd46 100644 --- a/Source/Game/Entities/Player/Player.Talents.cs +++ b/Source/Game/Entities/Player/Player.Talents.cs @@ -256,7 +256,7 @@ namespace Game.Entities { return CliDB.ChrSpecializationStorage.LookupByKey((uint)GetPrimarySpecialization()); } - + public byte GetActiveTalentGroup() { return _specializationInfo.ActiveGroup; } void SetActiveTalentGroup(byte group) { _specializationInfo.ActiveGroup = group; } @@ -742,10 +742,8 @@ namespace Game.Entities if (HasPvpTalent(talentID, GetActiveTalentGroup())) return TalentLearnResult.FailedUnknown; - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(talentInfo.PlayerConditionID); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) - return TalentLearnResult.FailedCantDoThatRightNow; + if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)talentInfo.PlayerConditionID)) + return TalentLearnResult.FailedCantDoThatRightNow; PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]); if (talent != null) diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 95cf97c9e..dc9728cd2 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -1327,11 +1327,8 @@ namespace Game.Entities // Check award condition if (currency.AwardConditionID != 0) - { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(currency.AwardConditionID); - if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) + if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)currency.AwardConditionID)) return; - } bool isGainOnRefund = false; @@ -2446,12 +2443,6 @@ namespace Game.Entities // stop taxi flight at summon FinishTaxiFlight(); - // drop flag at summon - // this code can be reached only when GM is summoning player who carries flag, because player should be immune to summoning spells when he carries flag - Battleground bg = GetBattleground(); - if (bg != null) - bg.EventPlayerDroppedFlag(this); - m_summon_expire = 0; UpdateCriteria(CriteriaType.AcceptSummon, 1); @@ -4250,13 +4241,6 @@ namespace Game.Entities UpdateZone(newzone, newarea); OutdoorPvPMgr.HandlePlayerResurrects(this, newzone); - if (InBattleground()) - { - Battleground bg = GetBattleground(); - if (bg != null) - bg.HandlePlayerResurrect(this); - } - // update visibility UpdateObjectVisibility(); @@ -4454,22 +4438,14 @@ namespace Game.Entities } WorldSafeLocsEntry closestGrave = null; - - // Special handle for Battlegroundmaps - Battleground bg = GetBattleground(); - if (bg != null) - closestGrave = bg.GetClosestGraveyard(this); + var bf = BattleFieldMgr.GetBattlefieldToZoneId(GetMap(), GetZoneId()); + if (bf != null) + closestGrave = bf.GetClosestGraveyard(this); else { - var bf = BattleFieldMgr.GetBattlefieldToZoneId(GetMap(), GetZoneId()); - if (bf != null) - closestGrave = bf.GetClosestGraveyard(this); - else - { - InstanceScript instance = GetInstanceScript(); - if (instance != null) - closestGrave = ObjectMgr.GetWorldSafeLoc(instance.GetEntranceLocation()); - } + InstanceScript instance = GetInstanceScript(); + if (instance != null) + closestGrave = ObjectMgr.GetWorldSafeLoc(instance.GetEntranceLocation()); } if (closestGrave == null) @@ -4985,12 +4961,7 @@ namespace Game.Entities public bool MeetPlayerCondition(uint conditionId) { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(conditionId); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) - return false; - - return true; + return ConditionManager.IsPlayerMeetingCondition(this, conditionId); } bool IsInFriendlyArea() @@ -5143,6 +5114,8 @@ namespace Game.Entities return Team.Alliance; case 1: return Team.Horde; + case 2: + return Team.PandariaNeutral; } return Team.Alliance; @@ -5157,10 +5130,10 @@ namespace Game.Entities return BattleGroundTeamId.Neutral; } public Team GetTeam() { return m_team; } - public int GetTeamId() { return m_team == Team.Alliance ? BattleGroundTeamId.Alliance : BattleGroundTeamId.Horde; } + public int GetTeamId() { return SharedConst.GetTeamIdForTeam(m_team); } - public Team GetEffectiveTeam() { return HasPlayerFlagEx(PlayerFlagsEx.MercenaryMode) ? (GetTeam() == Team.Alliance ? Team.Horde : Team.Alliance) : GetTeam(); } - public int GetEffectiveTeamId() { return GetEffectiveTeam() == Team.Alliance ? BattleGroundTeamId.Alliance : BattleGroundTeamId.Horde; } + public Team GetEffectiveTeam() { return HasPlayerFlagEx(PlayerFlagsEx.MercenaryMode) ? SharedConst.GetOtherTeam(GetTeam()) : GetTeam(); } + public int GetEffectiveTeamId() { return SharedConst.GetTeamIdForTeam(GetEffectiveTeam()); } //Money public ulong GetMoney() { return m_activePlayerData.Coinage; } @@ -6318,11 +6291,8 @@ namespace Game.Entities // Check award condition if (currencyRecord.AwardConditionID != 0) - { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(currencyRecord.AwardConditionID); - if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) + if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)currencyRecord.AwardConditionID)) continue; - } SetupCurrency.Record record = new(); record.Type = currencyRecord.Id; diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index 377abd75b..65b503cb9 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -363,7 +363,7 @@ namespace Game.Entities break; } } - + public virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, out float minDamage, out float maxDamage) { minDamage = 0f; @@ -802,7 +802,7 @@ namespace Game.Entities return damage; } - + // player or player's pet resilience (-1%) uint GetDamageReduction(uint damage) { return GetCombatRatingDamageReduction(CombatRating.ResiliencePlayerDamage, 1.0f, 100.0f, damage); } @@ -946,7 +946,7 @@ namespace Game.Entities float chance = GetUnitCriticalChanceDone(attackType); return victim.GetUnitCriticalChanceTaken(this, attackType, chance); } - + float GetUnitDodgeChance(WeaponAttackType attType, Unit victim) { int levelDiff = (int)(victim.GetLevelForTarget(this) - GetLevelForTarget(victim)); @@ -1085,7 +1085,7 @@ namespace Game.Entities } return Math.Max(resistMech, 0); } - + public void ApplyModManaCostMultiplier(float manaCostMultiplier, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ManaCostMultiplier), manaCostMultiplier, apply); } public void ApplyModManaCostModifier(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ManaCostModifier, (int)school), mod, apply); } @@ -1545,34 +1545,34 @@ namespace Game.Entities case CombatRating.HasteMelee: case CombatRating.HasteRanged: case CombatRating.HasteSpell: + { + // explicit affected values + float multiplier = GetRatingMultiplier(cr); + float oldVal = ApplyRatingDiminishing(cr, oldRating * multiplier); + float newVal = ApplyRatingDiminishing(cr, amount * multiplier); + switch (cr) { - // explicit affected values - float multiplier = GetRatingMultiplier(cr); - float oldVal = ApplyRatingDiminishing(cr, oldRating * multiplier); - float newVal = ApplyRatingDiminishing(cr, amount * multiplier); - switch (cr) - { - case CombatRating.HasteMelee: - ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, oldVal, false); - ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, oldVal, false); - ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, newVal, true); - ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, newVal, true); - if (GetClass() == Class.Deathknight) - UpdateAllRunesRegen(); - break; - case CombatRating.HasteRanged: - ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, oldVal, false); - ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, newVal, true); - break; - case CombatRating.HasteSpell: - ApplyCastTimePercentMod(oldVal, false); - ApplyCastTimePercentMod(newVal, true); - break; - default: - break; - } - break; + case CombatRating.HasteMelee: + ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, oldVal, false); + ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, oldVal, false); + ApplyAttackTimePercentMod(WeaponAttackType.BaseAttack, newVal, true); + ApplyAttackTimePercentMod(WeaponAttackType.OffAttack, newVal, true); + if (GetClass() == Class.Deathknight) + UpdateAllRunesRegen(); + break; + case CombatRating.HasteRanged: + ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, oldVal, false); + ApplyAttackTimePercentMod(WeaponAttackType.RangedAttack, newVal, true); + break; + case CombatRating.HasteSpell: + ApplyCastTimePercentMod(oldVal, false); + ApplyCastTimePercentMod(newVal, true); + break; + default: + break; } + break; + } case CombatRating.Expertise: if (affectStats) { @@ -1667,14 +1667,10 @@ namespace Game.Entities continue; } - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(corruptionEffect.PlayerConditionID); - if (playerCondition != null) + if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)corruptionEffect.PlayerConditionID)) { - if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition)) - { - RemoveAura(corruptionEffect.Aura); - continue; - } + RemoveAura(corruptionEffect.Aura); + continue; } CastSpell(this, corruptionEffect.Aura, true); @@ -1766,7 +1762,7 @@ namespace Game.Entities } SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ParryPercentage), value); } - + float[] dodge_cap = { 65.631440f, // Warrior @@ -1997,7 +1993,7 @@ namespace Game.Entities return Stats.Intellect; } - + public override void UpdateMaxHealth() { UnitMods unitMod = UnitMods.Health; @@ -2112,7 +2108,7 @@ namespace Game.Entities return base.GetCreatePowerValue(power); } - + public override bool UpdateStats(Stats stat) { return true; diff --git a/Source/Game/Entities/Taxi/TaxiPathGraph.cs b/Source/Game/Entities/Taxi/TaxiPathGraph.cs index 00c848b1d..8eea2deb1 100644 --- a/Source/Game/Entities/Taxi/TaxiPathGraph.cs +++ b/Source/Game/Entities/Taxi/TaxiPathGraph.cs @@ -154,14 +154,18 @@ namespace Game.Entities foreach (var edge in path) { var To = m_nodesByVertex[(int)edge.To]; - TaxiNodeFlags requireFlag = (player.GetTeam() == Team.Alliance) ? TaxiNodeFlags.ShowOnAllianceMap : TaxiNodeFlags.ShowOnHordeMap; - if (!To.HasFlag(requireFlag)) + bool isVisibleForFaction = player.GetTeam() switch + { + Team.Horde => To.HasFlag(TaxiNodeFlags.ShowOnHordeMap), + Team.Alliance => To.HasFlag(TaxiNodeFlags.ShowOnAllianceMap), + _ => false + }; + + if (!isVisibleForFaction) continue; - PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(To.ConditionID); - if (condition != null) - if (!ConditionManager.IsPlayerMeetingCondition(player, condition)) - continue; + if (!ConditionManager.IsPlayerMeetingCondition(player, To.ConditionID)) + continue; shortestPath.Add(GetNodeIDFromVertexID(edge.To)); } diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index d08bc3344..98c7676ae 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -868,13 +868,8 @@ namespace Game.Entities continue; Player thisPlayer = ToPlayer(); - if (thisPlayer != null) - { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountCapability.PlayerConditionID); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(thisPlayer, playerCondition)) - continue; - } + if (thisPlayer != null && !ConditionManager.IsPlayerMeetingCondition(thisPlayer, (uint)mountCapability.PlayerConditionID)) + continue; return mountCapability; } diff --git a/Source/Game/Entities/Unit/Vignette.cs b/Source/Game/Entities/Unit/Vignette.cs index 7bf0c576f..14be3a8d6 100644 --- a/Source/Game/Entities/Unit/Vignette.cs +++ b/Source/Game/Entities/Unit/Vignette.cs @@ -110,8 +110,7 @@ namespace Game.Entities if (player.IsQuestRewarded(vignette.Data.VisibleTrackingQuestID)) return false; - var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(vignette.Data.PlayerConditionID); - if (playerCondition != null && !ConditionManager.IsPlayerMeetingCondition(player, playerCondition)) + if (!ConditionManager.IsPlayerMeetingCondition(player, vignette.Data.PlayerConditionID)) return false; return true; diff --git a/Source/Game/Entities/Vehicle.cs b/Source/Game/Entities/Vehicle.cs index e7767bcf4..8d76da27c 100644 --- a/Source/Game/Entities/Vehicle.cs +++ b/Source/Game/Entities/Vehicle.cs @@ -672,11 +672,6 @@ namespace Game.Entities Player player = Passenger.ToPlayer(); if (player != null) { - // drop flag - Battleground bg = player.GetBattleground(); - if (bg != null) - bg.EventPlayerDroppedFlag(player); - player.StopCastingCharm(); player.StopCastingBindSight(); player.SendOnCancelExpectedVehicleRideAura(); diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 3dd609b84..3a58f9cc1 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -158,7 +158,7 @@ namespace Game { if (value == null) value = ""; - + data[(int)locale] = value; } public static void GetLocaleString(StringArray data, Locale locale, ref string value) @@ -4118,6 +4118,10 @@ namespace Game got.BarberChair.SitAnimKit = 0; } break; + case GameObjectTypes.DestructibleBuilding: + if (got.DestructibleBuilding.HealthRec != 0 && GetDestructibleHitpoint(got.DestructibleBuilding.HealthRec) == null) + Log.outError(LogFilter.Sql, $"GameObject (Entry: {entry}) Has non existing Destructible Hitpoint Record {got.DestructibleBuilding.HealthRec}."); + break; case GameObjectTypes.GarrisonBuilding: { int transportMap = got.GarrisonBuilding.SpawnMap; @@ -4647,6 +4651,12 @@ namespace Game continue; } + case GameObjectTypes.SpellFocus: + { + if (pair.Value.SpellFocus.questID > 0) //quests objects + break; + continue; + } case GameObjectTypes.Goober: { if (pair.Value.Goober.questID > 0) //quests objects @@ -4673,6 +4683,33 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, "Loaded {0} GameObjects for quests in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime)); } + public void LoadDestructibleHitpoints() + { + uint oldMSTime = Time.GetMSTime(); + + _destructibleHitpointStorage.Clear(); // need for reload case + + // 0 1 2 + SQLResult result = DB.World.Query("SELECT Id, IntactNumHits, DamagedNumHits FROM destructible_hitpoint"); + if (result.IsEmpty()) + return; + + do + { + uint id = result.Read(0); + + DestructibleHitpoint data = new(); + data.Id = id; + data.IntactNumHits = result.Read(1); + data.DamagedNumHits = result.Read(2); + + _destructibleHitpointStorage.Add(id, data); + + } while (result.NextRow()); + + Log.outInfo(LogFilter.ServerLoading, $"Loaded {_destructibleHitpointStorage.Count} destructible_hitpoint records in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); + } + public void AddGameObjectToGrid(GameObjectData data) { AddSpawnDataToGrid(data); @@ -4833,6 +4870,11 @@ namespace Game return difficulties; } + public DestructibleHitpoint GetDestructibleHitpoint(uint entry) + { + return _destructibleHitpointStorage.LookupByKey(entry); + } + //Items public void LoadItemTemplates() { @@ -5172,8 +5214,11 @@ namespace Game if (vItem.PlayerConditionId != 0 && !CliDB.PlayerConditionStorage.ContainsKey(vItem.PlayerConditionId)) { - Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` has Item (Entry: {0}) with invalid PlayerConditionId ({1}) for vendor ({2}), ignore", vItem.item, vItem.PlayerConditionId, vendorentry); - return false; + if (!Global.ConditionMgr.HasConditionsForNotGroupedEntry(ConditionSourceType.PlayerCondition, vItem.PlayerConditionId)) + { + Log.outError(LogFilter.Sql, "Table `(game_event_)npc_vendor` has Item (Entry: {0}) with serverside PlayerConditionId ({1}) for vendor ({2}) without conditions, ignore", vItem.item, vItem.PlayerConditionId, vendorentry); + return false; + } } if (vItem.ExtendedCost != 0 && !CliDB.ItemExtendedCostStorage.ContainsKey(vItem.ExtendedCost)) @@ -10426,10 +10471,19 @@ namespace Game float dist = 10000; uint id = 0; - TaxiNodeFlags requireFlag = (team == Team.Alliance) ? TaxiNodeFlags.ShowOnAllianceMap : TaxiNodeFlags.ShowOnHordeMap; + var isVisibleForFaction = (TaxiNodesRecord node) => + { + return team switch + { + Team.Horde => node.HasFlag(TaxiNodeFlags.ShowOnHordeMap), + Team.Alliance => node.HasFlag(TaxiNodeFlags.ShowOnAllianceMap), + _ => false + }; + }; + foreach (var node in CliDB.TaxiNodesStorage.Values) { - if (node.ContinentID != mapid || !node.HasFlag(requireFlag) || node.HasFlag(TaxiNodeFlags.IgnoreForFindNearest)) + if (node.ContinentID != mapid || !isVisibleForFaction(node) || node.HasFlag(TaxiNodeFlags.IgnoreForFindNearest)) continue; uint field = (node.Id - 1) / 8; @@ -10890,6 +10944,7 @@ namespace Game Dictionary _gameObjectAddonStorage = new(); MultiMap _gameObjectQuestItemStorage = new(); List _gameObjectForQuestStorage = new(); + Dictionary _destructibleHitpointStorage = new(); //Item Dictionary ItemTemplateStorage = new(); diff --git a/Source/Game/Guilds/Guild.cs b/Source/Game/Guilds/Guild.cs index 756c51960..e9d60ebc0 100644 --- a/Source/Game/Guilds/Guild.cs +++ b/Source/Game/Guilds/Guild.cs @@ -672,15 +672,13 @@ namespace Game.Guilds SendCommandResult(session, GuildCommandType.RemovePlayer, GuildCommandError.RankTooHigh_S, name); else { + DeleteMember(null, guid, false, true); _LogEvent(GuildEventLogTypes.UninvitePlayer, player.GetGUID().GetCounter(), guid.GetCounter()); Player pMember = Global.ObjAccessor.FindConnectedPlayer(guid); SendEventPlayerLeft(pMember, player, true); SendCommandResult(session, GuildCommandType.RemovePlayer, GuildCommandError.Success, name); - - // After call to DeleteMember pointer to member becomes invalid - DeleteMember(null, guid, false, true); } } } diff --git a/Source/Game/Handlers/ArtifactHandler.cs b/Source/Game/Handlers/ArtifactHandler.cs index 35dcb2d65..f8d16abb9 100644 --- a/Source/Game/Handlers/ArtifactHandler.cs +++ b/Source/Game/Handlers/ArtifactHandler.cs @@ -161,10 +161,8 @@ namespace Game if (artifactAppearanceSet == null || artifactAppearanceSet.ArtifactID != artifact.GetTemplate().GetArtifactID()) return; - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(artifactAppearance.UnlockPlayerConditionID); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(_player, playerCondition)) - return; + if (!ConditionManager.IsPlayerMeetingCondition(_player, artifactAppearance.UnlockPlayerConditionID)) + return; artifact.SetAppearanceModId(artifactAppearance.ItemAppearanceModifierID); artifact.SetModifier(ItemModifier.ArtifactAppearanceId, artifactAppearance.Id); diff --git a/Source/Game/Handlers/BattlenetHandler.cs b/Source/Game/Handlers/BattlenetHandler.cs index bc445d745..6e2e44e0f 100644 --- a/Source/Game/Handlers/BattlenetHandler.cs +++ b/Source/Game/Handlers/BattlenetHandler.cs @@ -36,7 +36,7 @@ namespace Game realmListTicket.Ticket.WriteCString("WorldserverRealmListTicket"); SendPacket(realmListTicket); - } + } public void SendBattlenetResponse(uint serviceHash, uint methodId, uint token, IMessage response) { @@ -52,7 +52,7 @@ namespace Game SendPacket(bnetResponse); } - public void SendBattlenetResponse(uint serviceHash, uint methodId, uint token, BattlenetRpcErrorCode status) + public void SendBattlenetResponse(uint serviceHash, uint methodId, uint token, BattlenetRpcErrorCode status) { Response bnetResponse = new(); bnetResponse.BnetStatus = status; @@ -63,16 +63,35 @@ namespace Game SendPacket(bnetResponse); } - public void SendBattlenetRequest(uint serviceHash, uint methodId, IMessage request, Action callback) + public void SendBattlenetRequest(OriginalHash serviceHash, uint methodId, IMessage request, bool client, bool server, Action callback) { _battlenetResponseCallbacks[_battlenetRequestToken] = callback; - SendBattlenetRequest(serviceHash, methodId, request); + SendBattlenetRequest(serviceHash, methodId, request, client, server); } - public void SendBattlenetRequest(uint serviceHash, uint methodId, IMessage request) + public void SendBattlenetRequest(NameHash serviceHash, uint methodId, IMessage request, bool client, bool server, Action callback) + { + _battlenetResponseCallbacks[_battlenetRequestToken] = callback; + SendBattlenetRequest(serviceHash, methodId, request, client, server); + } + + public void SendBattlenetRequest(OriginalHash serviceHash, uint methodId, IMessage request, bool client = true, bool server = true) { Notification notification = new(); - notification.Method.Type = MathFunctions.MakePair64(methodId, serviceHash); + notification.Method.Type = MathFunctions.MakePair64(methodId | (client ? 0x40000000 : 0u) | (server ? 0x80000000 : 0u), (uint)serviceHash); + notification.Method.ObjectId = 1; + notification.Method.Token = _battlenetRequestToken++; + + if (request.CalculateSize() != 0) + notification.Data.WriteBytes(request.ToByteArray()); + + SendPacket(notification); + } + + public void SendBattlenetRequest(NameHash serviceHash, uint methodId, IMessage request, bool client = true, bool server = true) + { + Notification notification = new(); + notification.Method.Type = MathFunctions.MakePair64(methodId | (client ? 0x40000000 : 0u) | (server ? 0x80000000 : 0u), (uint)serviceHash); notification.Method.ObjectId = 1; notification.Method.Token = _battlenetRequestToken++; diff --git a/Source/Game/Handlers/CharacterHandler.cs b/Source/Game/Handlers/CharacterHandler.cs index 3f7c7fd24..a5f963aa1 100644 --- a/Source/Game/Handlers/CharacterHandler.cs +++ b/Source/Game/Handlers/CharacterHandler.cs @@ -1394,10 +1394,8 @@ namespace Game if (!MeetsChrCustomizationReq(req, (Race)packet.CustomizedRace, _player.GetClass(), false, packet.Customizations)) return; - var condition = CliDB.PlayerConditionStorage.LookupByKey(conditionalChrModel.PlayerConditionID); - if (condition != null) - if (!ConditionManager.IsPlayerMeetingCondition(_player, condition)) - return; + if (!ConditionManager.IsPlayerMeetingCondition(_player, (uint)conditionalChrModel.PlayerConditionID)) + return; } if (!ValidateAppearance(_player.GetRace(), _player.GetClass(), (Gender)packet.NewSex, packet.Customizations)) @@ -1632,10 +1630,8 @@ namespace Game if (illusion.ItemVisual == 0 || !illusion.HasFlag(SpellItemEnchantmentFlags.AllowTransmog)) return false; - PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.TransmogUseConditionID); - if (condition != null) - if (!ConditionManager.IsPlayerMeetingCondition(_player, condition)) - return false; + if (!ConditionManager.IsPlayerMeetingCondition(_player, illusion.TransmogUseConditionID)) + return false; if (illusion.ScalingClassRestricted > 0 && illusion.ScalingClassRestricted != (byte)_player.GetClass()) return false; diff --git a/Source/Game/Handlers/MiscHandler.cs b/Source/Game/Handlers/MiscHandler.cs index 0c26da6de..9548208e6 100644 --- a/Source/Game/Handlers/MiscHandler.cs +++ b/Source/Game/Handlers/MiscHandler.cs @@ -251,9 +251,6 @@ namespace Game return; } - Battleground bg = player.GetBattleground(); - if (bg != null) - bg.HandleAreaTrigger(player, packet.AreaTriggerID, packet.Entered); OutdoorPvP pvp = player.GetOutdoorPvP(); if (pvp != null) @@ -452,10 +449,8 @@ namespace Game UISplashScreenRecord splashScreen = null; foreach (var itr in CliDB.UISplashScreenStorage.Values) { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(itr.CharLevelConditionID); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(_player, playerCondition)) - continue; + if (!ConditionManager.IsPlayerMeetingCondition(_player, (uint)itr.CharLevelConditionID)) + continue; splashScreen = itr; } diff --git a/Source/Game/Handlers/MovementHandler.cs b/Source/Game/Handlers/MovementHandler.cs index 32ce3ec23..f18d2b264 100644 --- a/Source/Game/Handlers/MovementHandler.cs +++ b/Source/Game/Handlers/MovementHandler.cs @@ -756,8 +756,7 @@ namespace Game // far teleport case if (GetPlayer().GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Flight) { - FlightPathMovementGenerator flight = GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() as FlightPathMovementGenerator; - if (flight != null) + if (GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() is FlightPathMovementGenerator flight) { bool shouldTeleport = curDestNode != null && curDestNode.ContinentID != GetPlayer().GetMapId(); if (!shouldTeleport) diff --git a/Source/Game/Handlers/NPCHandler.cs b/Source/Game/Handlers/NPCHandler.cs index e41872fcc..e20618b70 100644 --- a/Source/Game/Handlers/NPCHandler.cs +++ b/Source/Game/Handlers/NPCHandler.cs @@ -440,10 +440,8 @@ namespace Game VendorItemPkt item = new(); - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(vendorItem.PlayerConditionId); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(_player, playerCondition)) - item.PlayerConditionFailed = (int)playerCondition.Id; + if (!ConditionManager.IsPlayerMeetingCondition(_player, vendorItem.PlayerConditionId)) + item.PlayerConditionFailed = (int)vendorItem.PlayerConditionId; if (vendorItem.Type == ItemVendorType.Item) { diff --git a/Source/Game/Handlers/QuestHandler.cs b/Source/Game/Handlers/QuestHandler.cs index 169893aae..195b41e43 100644 --- a/Source/Game/Handlers/QuestHandler.cs +++ b/Source/Game/Handlers/QuestHandler.cs @@ -348,10 +348,6 @@ namespace Game { if (GetPlayer().CanRewardQuest(quest, packet.Choice.LootItemType, packet.Choice.Item.ItemID, true)) // Then check if player can receive the reward item (if inventory is not full, if player doesn't have too many unique items, and so on). If not, the client will close the gossip window { - Battleground bg = _player.GetBattleground(); - if (bg != null) - bg.HandleQuestComplete(packet.QuestID, _player); - GetPlayer().RewardQuest(quest, packet.Choice.LootItemType, packet.Choice.Item.ItemID, obj); } } @@ -650,13 +646,20 @@ namespace Game continue; } - if (!receiver.SatisfyQuestReputation(quest, false)) + if (!receiver.SatisfyQuestMinReputation(quest, false)) { sender.SendPushToPartyResponse(receiver, QuestPushReason.LowFaction); receiver.SendPushToPartyResponse(sender, QuestPushReason.LowFactionToRecipient, quest); continue; } + if (!receiver.SatisfyQuestMaxReputation(quest, false)) + { + sender.SendPushToPartyResponse(receiver, QuestPushReason.HighFaction); + receiver.SendPushToPartyResponse(sender, QuestPushReason.HighFactionToRecipient, quest); + continue; + } + if (!receiver.SatisfyQuestDependentQuests(quest, false)) { sender.SendPushToPartyResponse(receiver, QuestPushReason.Prerequisite); diff --git a/Source/Game/Handlers/TaxiHandler.cs b/Source/Game/Handlers/TaxiHandler.cs index 789a9247e..300675839 100644 --- a/Source/Game/Handlers/TaxiHandler.cs +++ b/Source/Game/Handlers/TaxiHandler.cs @@ -191,15 +191,7 @@ namespace Game var mountDisplays = Global.DB2Mgr.GetMountDisplays(mount.Id); if (mountDisplays != null) { - List usableDisplays = mountDisplays.Where(mountDisplay => - { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountDisplay.PlayerConditionID); - if (playerCondition != null) - return ConditionManager.IsPlayerMeetingCondition(GetPlayer(), playerCondition); - - return true; - }).ToList(); - + List usableDisplays = mountDisplays.Where(mountDisplay => ConditionManager.IsPlayerMeetingCondition(GetPlayer(), mountDisplay.PlayerConditionID)).ToList(); if (!usableDisplays.Empty()) preferredMountDisplay = usableDisplays.SelectRandom().CreatureDisplayInfoID; } @@ -221,8 +213,7 @@ namespace Game [WorldPacketHandler(ClientOpcodes.TaxiRequestEarlyLanding, Processing = PacketProcessing.ThreadSafe)] void HandleTaxiRequestEarlyLanding(TaxiRequestEarlyLanding taxiRequestEarlyLanding) { - FlightPathMovementGenerator flight = GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() as FlightPathMovementGenerator; - if (flight != null) + if (GetPlayer().GetMotionMaster().GetCurrentMovementGenerator() is FlightPathMovementGenerator flight) { if (GetPlayer().m_taxi.RequestEarlyLanding()) { diff --git a/Source/Game/Handlers/TransmogrificationHandler.cs b/Source/Game/Handlers/TransmogrificationHandler.cs index efe97c905..9f181f217 100644 --- a/Source/Game/Handlers/TransmogrificationHandler.cs +++ b/Source/Game/Handlers/TransmogrificationHandler.cs @@ -129,14 +129,10 @@ namespace Game return; } - var condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.UnlockConditionID); - if (condition != null) + if (!ConditionManager.IsPlayerMeetingCondition(player, (uint)illusion.UnlockConditionID)) { - if (!ConditionManager.IsPlayerMeetingCondition(player, condition)) - { - Log.outDebug(LogFilter.Network, "WORLD: HandleTransmogrifyItems - {0}, Name: {1} tried to transmogrify illusion using not allowed enchant ({2}).", player.GetGUID().ToString(), player.GetName(), transmogItem.SpellItemEnchantmentID); - return; - } + Log.outDebug(LogFilter.Network, "WORLD: HandleTransmogrifyItems - {0}, Name: {1} tried to transmogrify illusion using not allowed enchant ({2}).", player.GetGUID().ToString(), player.GetName(), transmogItem.SpellItemEnchantmentID); + return; } illusionItems[itemTransmogrified] = (uint)transmogItem.SpellItemEnchantmentID; diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index 371989b50..b653591f8 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -60,17 +60,10 @@ namespace Game.Maps m_terrain.LoadMMapInstance(GetId(), GetInstanceId()); _worldStateValues = Global.WorldStateMgr.GetInitialWorldStatesForMap(this); - - Global.OutdoorPvPMgr.CreateOutdoorPvPForMap(this); - Global.BattleFieldMgr.CreateBattlefieldsForMap(this); - - Global.ScriptMgr.OnCreateMap(this); } public void Dispose() { - Global.ScriptMgr.OnDestroyMap(this); - // Delete all waiting spawns // This doesn't delete from database. UnloadAllRespawnInfos(); @@ -86,9 +79,6 @@ namespace Game.Maps if (!m_scriptSchedule.Empty()) Global.MapMgr.DecreaseScheduledScriptCount((uint)m_scriptSchedule.Count); - Global.OutdoorPvPMgr.DestroyOutdoorPvPForMap(this); - Global.BattleFieldMgr.DestroyBattlefieldsForMap(this); - m_terrain.UnloadMMapInstance(GetId(), GetInstanceId()); } @@ -5273,6 +5263,10 @@ namespace Game.Maps public class BattlegroundMap : Map { + Battleground m_bg; + BattlegroundScript _battlegroundScript; + uint _scriptId; + public BattlegroundMap(uint id, uint expiry, uint InstanceId, Difficulty spawnMode) : base(id, expiry, InstanceId, spawnMode) { @@ -5285,6 +5279,37 @@ namespace Game.Maps m_VisibilityNotifyPeriod = IsBattleArena() ? Global.WorldMgr.GetVisibilityNotifyPeriodInArenas() : Global.WorldMgr.GetVisibilityNotifyPeriodInBG(); } + string GetScriptName() + { + return Global.ObjectMgr.GetScriptName(_scriptId); + } + + public void InitScriptData() + { + if (_battlegroundScript != null) + return; + + Cypher.Assert(GetBG() != null, "Battleground not set yet!"); + + BattlegroundScriptTemplate scriptTemplate = Global.BattlegroundMgr.FindBattlegroundScriptTemplate(GetId(), GetBG().GetTypeID()); + if (scriptTemplate != null) + { + _scriptId = scriptTemplate.ScriptId; + _battlegroundScript = Global.ScriptMgr.CreateBattlegroundData(this); + } + + // Make sure every battleground has a default script + if (_battlegroundScript == null) + { + if (IsBattleArena()) + _battlegroundScript = new ArenaScript(this); + else + _battlegroundScript = new BattlegroundScript(this); + } + + _battlegroundScript.OnInit(); + } + public override TransferAbortParams CannotEnter(Player player) { if (player.GetMap() == this) @@ -5327,10 +5352,18 @@ namespace Game.Maps player.TeleportTo(player.GetBattlegroundEntryPoint()); } + public override void Update(uint diff) + { + base.Update(diff); + _battlegroundScript.OnUpdate(diff); + } + public Battleground GetBG() { return m_bg; } public void SetBG(Battleground bg) { m_bg = bg; } - Battleground m_bg; + public uint GetScriptId() { return _scriptId; } + + public BattlegroundScript GetBattlegroundScript() { return _battlegroundScript; } } public class TransferAbortParams @@ -5396,7 +5429,7 @@ namespace Game.Maps public float FloorZ; public bool outdoors = true; public ZLiquidStatus LiquidStatus; - public WmoLocation? wmoLocation; + public WmoLocation wmoLocation; public LiquidData LiquidInfo; } diff --git a/Source/Game/Maps/MapManager.cs b/Source/Game/Maps/MapManager.cs index 63d66e90b..2191b10aa 100644 --- a/Source/Game/Maps/MapManager.cs +++ b/Source/Game/Maps/MapManager.cs @@ -99,6 +99,7 @@ namespace Game.Entities Cypher.Assert(map.IsBattlegroundOrArena()); map.SetBG(bg); bg.SetBgMap(map); + map.InitScriptData(); map.InitSpawnGroupState(); if (WorldConfig.GetBoolValue(WorldCfg.BattlegroundMapLoadGrids)) @@ -198,7 +199,7 @@ namespace Game.Entities if (map == null) { - map = CreateInstance(mapId, newInstanceId, instanceLock, difficulty, player.GetTeamId(), group); + map = CreateInstance(mapId, newInstanceId, instanceLock, difficulty, SharedConst.GetTeamIdForTeam(Global.CharacterCacheStorage.GetCharacterTeamByGuid(instanceOwnerGuid)), group); if (group != null) group.SetRecentInstance(mapId, instanceOwnerGuid, newInstanceId); else @@ -224,8 +225,14 @@ namespace Game.Entities } if (map != null) + { i_maps[(map.GetId(), map.GetInstanceId())] = map; + Global.ScriptMgr.OnCreateMap(map); + Global.OutdoorPvPMgr.CreateOutdoorPvPForMap(map); + Global.BattleFieldMgr.CreateBattlefieldsForMap(map); + } + return map; } } @@ -320,6 +327,10 @@ namespace Game.Entities map.UnloadAll(); + Global.OutdoorPvPMgr.DestroyOutdoorPvPForMap(map); + Global.BattleFieldMgr.DestroyBattlefieldsForMap(map); + Global.ScriptMgr.OnDestroyMap(map); + // Free up the instance id and allow it to be reused for normal dungeons, bgs and arenas if (map.IsBattlegroundOrArena() || (map.IsDungeon() && !map.GetMapDifficulty().HasResetSchedule())) FreeInstanceId(map.GetInstanceId()); @@ -337,11 +348,17 @@ namespace Game.Entities public void UnloadAll() { // first unload maps - foreach (var pair in i_maps) - pair.Value.UnloadAll(); + foreach (var (_, map) in i_maps) + { + map.UnloadAll(); - foreach (var pair in i_maps) - pair.Value.Dispose(); + Global.OutdoorPvPMgr.DestroyOutdoorPvPForMap(map); + Global.BattleFieldMgr.DestroyBattlefieldsForMap(map); + Global.ScriptMgr.OnDestroyMap(map); + } + + foreach (var (_, map) in i_maps) + map.Dispose(); i_maps.Clear(); diff --git a/Source/Game/Maps/ZoneScript.cs b/Source/Game/Maps/ZoneScript.cs index 75a84d7a8..1db873412 100644 --- a/Source/Game/Maps/ZoneScript.cs +++ b/Source/Game/Maps/ZoneScript.cs @@ -9,6 +9,9 @@ namespace Game.Maps { public class ZoneScript { + protected EventMap _events = new(); + protected TaskScheduler _scheduler = new(); + public virtual void TriggerGameEvent(uint gameEventId, WorldObject source = null, WorldObject target = null) { if (source != null) @@ -48,8 +51,6 @@ namespace Game.Maps public virtual bool CanCaptureFlag(AreaTrigger areaTrigger, Player player) { return false; } public virtual void OnCaptureFlag(AreaTrigger areaTrigger, Player player) { } - - protected EventMap _events = new(); } public class ControlZoneHandler diff --git a/Source/Game/Movement/Generators/ChaseMovementGenerator.cs b/Source/Game/Movement/Generators/ChaseMovementGenerator.cs index 2a23a641f..b8813571c 100644 --- a/Source/Game/Movement/Generators/ChaseMovementGenerator.cs +++ b/Source/Game/Movement/Generators/ChaseMovementGenerator.cs @@ -243,8 +243,7 @@ namespace Game.Movement if (target.GetMotionMaster().GetCurrentMovementGeneratorType() != MovementGeneratorType.Chase) return false; - ChaseMovementGenerator movement = target.GetMotionMaster().GetCurrentMovementGenerator() as ChaseMovementGenerator; - if (movement != null) + if (target.GetMotionMaster().GetCurrentMovementGenerator() is ChaseMovementGenerator movement) return movement.GetTarget() == owner; return false; diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 0f8f01228..cd4bd5813 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -148,8 +148,7 @@ namespace Game.Movement { case MovementGeneratorType.Chase: case MovementGeneratorType.Follow: - var followInformation = movement as FollowMovementGenerator; - if (followInformation != null) + if (movement is FollowMovementGenerator followInformation) { Unit target = followInformation.GetTarget(); if (target != null) diff --git a/Source/Game/Networking/Packets/AuctionHousePackets.cs b/Source/Game/Networking/Packets/AuctionHousePackets.cs index 1190e969d..8ab685def 100644 --- a/Source/Game/Networking/Packets/AuctionHousePackets.cs +++ b/Source/Game/Networking/Packets/AuctionHousePackets.cs @@ -19,6 +19,7 @@ namespace Game.Networking.Packets public AuctionHouseFilterMask Filters; public byte[] KnownPets; public sbyte MaxPetLevel; + public uint Unused1026; public AddOnInfo? TaintedBy; public string Name; public Array ItemClassFilters = new(7); @@ -37,6 +38,7 @@ namespace Game.Networking.Packets Filters = (AuctionHouseFilterMask)_worldPacket.ReadUInt32(); uint knownPetSize = _worldPacket.ReadUInt32(); MaxPetLevel = _worldPacket.ReadInt8(); + Unused1026 = _worldPacket.ReadUInt32(); uint sizeLimit = CliDB.BattlePetSpeciesStorage.GetNumRows() / 8 + 1; if (knownPetSize >= sizeLimit) diff --git a/Source/Game/Networking/Packets/CharacterPackets.cs b/Source/Game/Networking/Packets/CharacterPackets.cs index c0c9b9d78..6088dda0d 100644 --- a/Source/Game/Networking/Packets/CharacterPackets.cs +++ b/Source/Game/Networking/Packets/CharacterPackets.cs @@ -326,12 +326,6 @@ namespace Game.Networking.Packets public struct RaceLimitDisableInfo { - enum blah - { - Server, - Level - } - public int RaceID; public int BlockReason; @@ -386,6 +380,7 @@ namespace Game.Networking.Packets bool hasTemplateSet = _worldPacket.HasBit(); CreateInfo.IsTrialBoost = _worldPacket.HasBit(); CreateInfo.UseNPE = _worldPacket.HasBit(); + CreateInfo.Unused1026 = _worldPacket.HasBit(); CreateInfo.RaceId = (Race)_worldPacket.ReadUInt8(); CreateInfo.ClassId = (Class)_worldPacket.ReadUInt8(); @@ -1144,6 +1139,7 @@ namespace Game.Networking.Packets public uint? TemplateSet; public bool IsTrialBoost; public bool UseNPE; + public bool Unused1026; public string Name; // Server side data diff --git a/Source/Game/Networking/Packets/ClientConfigPackets.cs b/Source/Game/Networking/Packets/ClientConfigPackets.cs index b999112a4..4faf74f67 100644 --- a/Source/Game/Networking/Packets/ClientConfigPackets.cs +++ b/Source/Game/Networking/Packets/ClientConfigPackets.cs @@ -43,7 +43,7 @@ namespace Game.Networking.Packets public override void Read() { PlayerGuid = _worldPacket.ReadPackedGuid(); - DataType = (AccountDataTypes)_worldPacket.ReadBits(4); + DataType = (AccountDataTypes)_worldPacket.ReadInt32(); } public ObjectGuid PlayerGuid; @@ -56,10 +56,10 @@ namespace Game.Networking.Packets public override void Write() { - _worldPacket.WritePackedGuid(Player); _worldPacket.WriteInt64(Time); _worldPacket.WriteUInt32(Size); - _worldPacket.WriteBits(DataType, 4); + _worldPacket.WritePackedGuid(Player); + _worldPacket.WriteInt32((int)DataType); if (CompressedData == null) _worldPacket.WriteUInt32(0); @@ -84,10 +84,10 @@ namespace Game.Networking.Packets public override void Read() { - PlayerGuid = _worldPacket.ReadPackedGuid(); Time = _worldPacket.ReadInt64(); Size = _worldPacket.ReadUInt32(); - DataType = (AccountDataTypes)_worldPacket.ReadBits(4); + PlayerGuid = _worldPacket.ReadPackedGuid(); + DataType = (AccountDataTypes)_worldPacket.ReadInt32(); uint compressedSize = _worldPacket.ReadUInt32(); if (compressedSize != 0) diff --git a/Source/Game/Networking/Packets/ReputationPackets.cs b/Source/Game/Networking/Packets/ReputationPackets.cs index 5fb1a13df..bc66f163e 100644 --- a/Source/Game/Networking/Packets/ReputationPackets.cs +++ b/Source/Game/Networking/Packets/ReputationPackets.cs @@ -93,13 +93,22 @@ namespace Game.Networking.Packets Standing = standing; } + public FactionStandingData(int index, int standing, int factionId) + { + Index = index; + Standing = standing; + FactionID = factionId; + } + public void Write(WorldPacket data) { data.WriteInt32(Index); data.WriteInt32(Standing); + data.WriteInt32(FactionID); } int Index; int Standing; + int FactionID; } } diff --git a/Source/Game/Networking/Packets/ScenePackets.cs b/Source/Game/Networking/Packets/ScenePackets.cs index 223ac7f30..559535159 100644 --- a/Source/Game/Networking/Packets/ScenePackets.cs +++ b/Source/Game/Networking/Packets/ScenePackets.cs @@ -65,9 +65,11 @@ namespace Game.Networking.Packets public override void Read() { SceneInstanceID = _worldPacket.ReadUInt32(); + TimePassed = _worldPacket.ReadInt32(); } public uint SceneInstanceID; + public int TimePassed; } class ScenePlaybackCanceled : ClientPacket @@ -77,8 +79,10 @@ namespace Game.Networking.Packets public override void Read() { SceneInstanceID = _worldPacket.ReadUInt32(); + TimePassed = _worldPacket.ReadInt32(); } public uint SceneInstanceID; + public int TimePassed; } } diff --git a/Source/Game/Networking/Packets/SystemPackets.cs b/Source/Game/Networking/Packets/SystemPackets.cs index afc7f1041..bcc8d07a4 100644 --- a/Source/Game/Networking/Packets/SystemPackets.cs +++ b/Source/Game/Networking/Packets/SystemPackets.cs @@ -264,7 +264,7 @@ namespace Game.Networking.Packets _worldPacket.WriteBit(KioskModeEnabled); _worldPacket.WriteBit(CompetitiveModeEnabled); - _worldPacket.WriteBit(false); // unused, 10.0.2 + _worldPacket.WriteBit(IsBoostEnabled); _worldPacket.WriteBit(TrialBoostEnabled); _worldPacket.WriteBit(TokenBalanceEnabled); _worldPacket.WriteBit(LiveRegionCharacterListEnabled); @@ -275,7 +275,7 @@ namespace Game.Networking.Packets _worldPacket.WriteBit(Unknown901CheckoutRelated); _worldPacket.WriteBit(false); // unused, 10.0.2 _worldPacket.WriteBit(EuropaTicketSystemStatus.HasValue); - _worldPacket.WriteBit(false); // unused, 10.0.2 + _worldPacket.WriteBit(IsNameReservationEnabled); _worldPacket.WriteBit(LaunchETA.HasValue); _worldPacket.WriteBit(AddonsDisabled); _worldPacket.WriteBit(Unused1000); @@ -309,6 +309,7 @@ namespace Game.Networking.Packets _worldPacket.WriteUInt32((uint)PlayerNameQueryInterval.TotalSeconds); _worldPacket.WriteInt32(DebugTimeEvents.Count); _worldPacket.WriteInt32(Unused1007); + _worldPacket.WriteUInt32(EventRealmQueues); if (LaunchETA.HasValue) _worldPacket.WriteInt32(LaunchETA.Value); @@ -336,6 +337,7 @@ namespace Game.Networking.Packets public bool IsExpansionPreorderInStore; // NYI public bool KioskModeEnabled; // NYI public bool CompetitiveModeEnabled; // NYI + public bool IsBoostEnabled; // classic only public bool TrialBoostEnabled; // NYI public bool TokenBalanceEnabled; // NYI public bool LiveRegionCharacterListEnabled; // NYI @@ -343,6 +345,7 @@ namespace Game.Networking.Packets public bool LiveRegionAccountCopyEnabled; // NYI public bool LiveRegionKeyBindingsCopyEnabled; public bool Unknown901CheckoutRelated; // NYI + public bool IsNameReservationEnabled; // classic only public bool AddonsDisabled; public bool Unused1000; public bool AccountSaveDataExportEnabled; @@ -366,6 +369,7 @@ namespace Game.Networking.Packets public int? LaunchETA; public List DebugTimeEvents = new(); public int Unused1007; + public uint EventRealmQueues; public string RealmHiddenAlert; } diff --git a/Source/Game/Networking/WorldSocket.cs b/Source/Game/Networking/WorldSocket.cs index 28ad2c919..25e61a664 100644 --- a/Source/Game/Networking/WorldSocket.cs +++ b/Source/Game/Networking/WorldSocket.cs @@ -9,6 +9,7 @@ using Framework.Networking; using Game.Networking.Packets; using System; using System.Net.Sockets; +using System.Threading.Tasks; namespace Game.Networking { @@ -75,12 +76,12 @@ namespace Game.Networking PreparedStatement stmt = LoginDatabase.GetPreparedStatement(LoginStatements.SEL_IP_INFO); stmt.AddValue(0, ip_address); - stmt.AddValue(1, BitConverter.ToUInt32(GetRemoteIpAddress().Address.GetAddressBytes(), 0)); + stmt.AddValue(1, BitConverter.ToUInt32(GetRemoteIpAddress().GetAddressBytes(), 0)); _queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(CheckIpCallback)); } - void CheckIpCallback(SQLResult result) + async void CheckIpCallback(SQLResult result) { if (!result.IsEmpty()) { @@ -109,24 +110,18 @@ namespace Game.Networking ByteBuffer packet = new(); packet.WriteString(ServerConnectionInitialize); packet.WriteString("\n"); - AsyncWrite(packet.GetData()); + await AsyncWrite(packet.GetData()); } - void InitializeHandler(SocketAsyncEventArgs args) + async Task InitializeHandler(byte[] data, int receivedLength) { - if (args.SocketError != SocketError.Success) - { - CloseSocket(); - return; - } - - if (args.BytesTransferred > 0) + if (receivedLength > 0) { if (_packetBuffer.GetRemainingSpace() > 0) { // need to receive the header - int readHeaderSize = Math.Min(args.BytesTransferred, _packetBuffer.GetRemainingSpace()); - _packetBuffer.Write(args.Buffer, 0, readHeaderSize); + int readHeaderSize = Math.Min(receivedLength, _packetBuffer.GetRemainingSpace()); + _packetBuffer.Write(data, 0, readHeaderSize); if (_packetBuffer.GetRemainingSpace() > 0) { @@ -165,25 +160,25 @@ namespace Game.Networking _packetBuffer.Resize(0); _packetBuffer.Reset(); HandleSendAuthSession(); - AsyncRead(); + await AsyncRead(); return; } } } - public override void ReadHandler(SocketAsyncEventArgs args) + public async override void ReadHandler(byte[] data, int receivedLength) { if (!IsOpen()) return; int currentReadIndex = 0; - while (currentReadIndex < args.BytesTransferred) + while (currentReadIndex < receivedLength) { if (_headerBuffer.GetRemainingSpace() > 0) { // need to receive the header - int readHeaderSize = Math.Min(args.BytesTransferred - currentReadIndex, _headerBuffer.GetRemainingSpace()); - _headerBuffer.Write(args.Buffer, currentReadIndex, readHeaderSize); + int readHeaderSize = Math.Min(receivedLength - currentReadIndex, _headerBuffer.GetRemainingSpace()); + _headerBuffer.Write(data, currentReadIndex, readHeaderSize); currentReadIndex += readHeaderSize; if (_headerBuffer.GetRemainingSpace() > 0) @@ -201,8 +196,8 @@ namespace Game.Networking if (_packetBuffer.GetRemainingSpace() > 0) { // need more data in the payload - int readDataSize = Math.Min(args.BytesTransferred - currentReadIndex, _packetBuffer.GetRemainingSpace()); - _packetBuffer.Write(args.Buffer, currentReadIndex, readDataSize); + int readDataSize = Math.Min(receivedLength - currentReadIndex, _packetBuffer.GetRemainingSpace()); + _packetBuffer.Write(data, currentReadIndex, readDataSize); currentReadIndex += readDataSize; if (_packetBuffer.GetRemainingSpace() > 0) @@ -221,7 +216,7 @@ namespace Game.Networking } } - AsyncRead(); + await AsyncRead(); } bool ReadHeader() @@ -254,7 +249,7 @@ namespace Game.Networking return ReadDataHandlerResult.Error; } - PacketLog.Write(packet.GetData(), packet.GetOpcode(), GetRemoteIpAddress(), _connectType, true); + PacketLog.Write(packet.GetData(), packet.GetOpcode(), GetRemoteIpEndPoint(), _connectType, true); ClientOpcodes opcode = (ClientOpcodes)packet.GetOpcode(); @@ -346,7 +341,7 @@ namespace Game.Networking return ReadDataHandlerResult.Ok; } - public void SendPacket(ServerPacket packet) + public async void SendPacket(ServerPacket packet) { if (!IsOpen()) return; @@ -356,7 +351,7 @@ namespace Game.Networking var data = packet.GetData(); ServerOpcodes opcode = packet.GetOpcode(); - PacketLog.Write(data, (uint)opcode, GetRemoteIpAddress(), _connectType, false); + PacketLog.Write(data, (uint)opcode, GetRemoteIpEndPoint(), _connectType, false); ByteBuffer buffer = new(); @@ -368,7 +363,7 @@ namespace Game.Networking byte[] compressedData; uint compressedSize = CompressPacket(data, opcode, out compressedData); - buffer.WriteUInt32(ZLib.adler32(0x9827D8F1, compressedData, compressedSize)); + buffer.WriteUInt32(ZLib.adler32(0x9827D8F1, compressedData, compressedSize)); buffer.WriteBytes(compressedData, compressedSize); packetSize = (int)(compressedSize + 12); @@ -392,7 +387,7 @@ namespace Game.Networking header.Write(byteBuffer); byteBuffer.WriteBytes(data); - AsyncWrite(byteBuffer.GetData()); + await AsyncWrite(byteBuffer.GetData()); } public void SetWorldSession(WorldSession session) @@ -464,7 +459,7 @@ namespace Game.Networking _queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthSessionCallback, authSession)); } - void HandleAuthSessionCallback(AuthSession authSession, SQLResult result) + async void HandleAuthSessionCallback(AuthSession authSession, SQLResult result) { // Stop if the account is not found if (result.IsEmpty()) @@ -540,7 +535,7 @@ namespace Game.Networking { // As we don't know if attempted login process by ip works, we update last_attempt_ip right away stmt = LoginDatabase.GetPreparedStatement(LoginStatements.UPD_LAST_ATTEMPT_IP); - stmt.AddValue(0, address.Address.ToString()); + stmt.AddValue(0, address.ToString()); stmt.AddValue(1, authSession.RealmJoinTicket); DB.Login.Execute(stmt); // This also allows to check for possible "hack" attempts on account @@ -582,7 +577,7 @@ namespace Game.Networking //Re-check ip locking (same check as in auth). if (account.battleNet.IsLockedToIP) // if ip is locked { - if (account.battleNet.LastIP != address.Address.ToString()) + if (account.battleNet.LastIP != address.ToString()) { SendAuthResponseError(BattlenetRpcErrorCode.RiskAccountLocked); Log.outDebug(LogFilter.Network, "HandleAuthSession: Sent Auth Response (Account IP differs)."); @@ -643,7 +638,7 @@ namespace Game.Networking { // Update the last_ip in the database stmt = LoginDatabase.GetPreparedStatement(LoginStatements.UPD_LAST_IP); - stmt.AddValue(0, address.Address.ToString()); + stmt.AddValue(0, address.ToString()); stmt.AddValue(1, authSession.RealmJoinTicket); DB.Login.Execute(stmt); } @@ -659,7 +654,7 @@ namespace Game.Networking //_worldSession.InitWarden(_sessionKey); _queryProcessor.AddCallback(_worldSession.LoadPermissionsAsync().WithCallback(LoadSessionPermissionsCallback)); - AsyncRead(); + await AsyncRead(); } void LoadSessionPermissionsCallback(SQLResult result) @@ -690,7 +685,7 @@ namespace Game.Networking _queryProcessor.AddCallback(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthContinuedSessionCallback, authSession)); } - void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result) + async void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result) { if (result.IsEmpty()) { @@ -728,7 +723,7 @@ namespace Game.Networking Buffer.BlockCopy(encryptKeyGen.Digest, 0, _encryptKey, 0, 16); SendPacket(new EnterEncryptedMode(_encryptKey, true)); - AsyncRead(); + await AsyncRead(); } void HandleConnectToFailed(ConnectToFailed connectToFailed) @@ -752,11 +747,11 @@ namespace Game.Networking _worldSession.SendConnectToInstance(ConnectToSerial.WorldAttempt5); break; case ConnectToSerial.WorldAttempt5: - { - Log.outError(LogFilter.Network, "{0} failed to connect 5 times to world socket, aborting login", _worldSession.GetPlayerInfo()); - _worldSession.AbortLogin(LoginFailureReason.NoWorld); - break; - } + { + Log.outError(LogFilter.Network, "{0} failed to connect 5 times to world socket, aborting login", _worldSession.GetPlayerInfo()); + _worldSession.AbortLogin(LoginFailureReason.NoWorld); + break; + } default: return; } diff --git a/Source/Game/Quest/Quest.cs b/Source/Game/Quest/Quest.cs index e5bc17903..e70830342 100644 --- a/Source/Game/Quest/Quest.cs +++ b/Source/Game/Quest/Quest.cs @@ -133,8 +133,11 @@ namespace Game if (playerConditionId != 0 && !CliDB.PlayerConditionStorage.ContainsKey(playerConditionId)) { - Log.outError(LogFilter.Sql, $"Table `quest_reward_display_spell` has non-existing PlayerCondition ({playerConditionId}) set for quest {Id}. and spell {spellId} Set to 0."); - playerConditionId = 0; + if (!Global.ConditionMgr.HasConditionsForNotGroupedEntry(ConditionSourceType.PlayerCondition, playerConditionId)) + { + Log.outError(LogFilter.Sql, $"Table `quest_reward_display_spell` has serverside PlayerCondition ({playerConditionId}) set for quest {Id}. and spell {spellId} without conditions. Set to 0."); + playerConditionId = 0; + } } if (type >= QuestCompleteSpellType.Max) @@ -481,7 +484,7 @@ namespace Game return false; } - + public void BuildQuestRewards(QuestRewards rewards, Player player) { rewards.ChoiceItemCount = GetRewChoiceItemsCount(); @@ -495,10 +498,8 @@ namespace Game var displaySpellIndex = 0; foreach (QuestRewardDisplaySpell displaySpell in RewardDisplaySpell) { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(displaySpell.PlayerConditionId); - if (playerCondition != null) - if (!ConditionManager.IsPlayerMeetingCondition(player, playerCondition)) - continue; + if (!ConditionManager.IsPlayerMeetingCondition(player, displaySpell.PlayerConditionId)) + continue; rewards.SpellCompletionDisplayID[displaySpellIndex] = (int)displaySpell.SpellId; if (++displaySpellIndex >= rewards.SpellCompletionDisplayID.Length) @@ -811,7 +812,7 @@ namespace Game public bool IsDailyOrWeekly() { return Flags.HasAnyFlag(QuestFlags.Daily | QuestFlags.Weekly); } public bool IsDFQuest() { return SpecialFlags.HasAnyFlag(QuestSpecialFlags.DfQuest); } public bool IsPushedToPartyOnAccept() { return HasSpecialFlag(QuestSpecialFlags.AutoPushToParty); } - + public uint GetRewChoiceItemsCount() { return _rewChoiceItemsCount; } public uint GetRewItemsCount() { return _rewItemsCount; } public uint GetRewCurrencyCount() { return _rewCurrencyCount; } @@ -1013,7 +1014,7 @@ namespace Game } public struct QuestRewardDisplaySpell - { + { public uint SpellId; public uint PlayerConditionId; public QuestCompleteSpellType Type; @@ -1077,7 +1078,7 @@ namespace Game } return false; } - + public bool IsStoringFlag() { switch (Type) diff --git a/Source/Game/Scripting/CoreScripts.cs b/Source/Game/Scripting/CoreScripts.cs index d996474de..8b02410bb 100644 --- a/Source/Game/Scripting/CoreScripts.cs +++ b/Source/Game/Scripting/CoreScripts.cs @@ -242,6 +242,19 @@ namespace Game.Scripting Global.ScriptMgr.AddScript(this); } + + // Gets an BattlegroundScript object for this battleground. + public virtual BattlegroundScript GetBattlegroundScript(BattlegroundMap map) { return null; } + } + + class GenericBattlegroundMapScript