Core/Battlegrounds: Move to scripts And a lot of misc commits i couldn't recover.

Port From (https://github.com/TrinityCore/TrinityCore/commit/d0d5d309bb5877dc2fcb27f6cb123707a31ec1e8)
This commit is contained in:
Hondacrx
2024-08-04 15:18:22 -04:00
parent bca02a24b0
commit e9b21a91be
139 changed files with 8322 additions and 8700 deletions
@@ -64,6 +64,11 @@ namespace BNetServer
{
return certificate;
}
public bool UsesDevWildcardCertificate()
{
return certificate.Subject.Contains("*.*");
}
}
public class BnetServiceHandler
@@ -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;
+2 -2
View File
@@ -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<QueryCallback> queryProcessor;
Dictionary<uint, Action<CodedInputStream>> responseCallbacks;
public Session(Socket socket) : base(socket)
public Session(Socket socket) : base(socket, true)
{
clientSecret = new byte[32];
queryProcessor = new AsyncCallbackProcessor<QueryCallback>();
+5 -2
View File
@@ -16,11 +16,11 @@ namespace BNetServer.REST
public BnetSRP6Base Srp;
}
public class LoginHttpSession : SslSocket<LoginHttpSession>
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
}
}
if (!Global.LoginServiceMgr.UsesDevWildcardCertificate())
await AsyncHandshake(Global.LoginServiceMgr.GetCertificate());
else
await AsyncRead();
}
public override RequestHandlerResult RequestHandler(RequestContext context)
+1 -1
View File
@@ -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);
@@ -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,
@@ -103,6 +103,7 @@ namespace Framework.Constants
TrainerSpell = 31,
ObjectIdVisibility = 32,
SpawnGroup = 33,
PlayerCondition = 34,
MaxDbAllowed,
ReferenceCondition = MaxDbAllowed,
File diff suppressed because it is too large Load Diff
+13 -10
View File
@@ -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
File diff suppressed because it is too large Load Diff
@@ -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 = ?");
@@ -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();
+5
View File
@@ -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
+2 -3
View File
@@ -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))
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<MIN_MATCH) return Z_OK;
@@ -6,6 +6,7 @@ using Framework.Database;
using Framework.Web;
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Framework.Networking.Http
{
@@ -20,9 +21,21 @@ namespace Framework.Networking.Http
public Guid? GetSessionId();
}
public abstract class BaseSocket<Derived> : 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<QueryCallback> _queryProcessor = new();
protected SessionState _state;
protected ISocket socket;
}
}
@@ -1,39 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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<Derived> : BaseSocket<Derived>
{
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();
}
}
}
-126
View File
@@ -1,126 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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);
}
}
}
+81 -42
View File
@@ -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()
try
{
if (!IsOpen())
return;
receiveSocketAsyncEventArgs.SetBuffer(0, 0x4000);
if (!_socket.ReceiveAsync(receiveSocketAsyncEventArgs))
ProcessReadAsync(receiveSocketAsyncEventArgs);
}
void ProcessReadAsync(SocketAsyncEventArgs args)
{
if (args.SocketError != SocketError.Success)
var result = await _stream.ReadAsync(_receiveBuffer, 0, _receiveBuffer.Length);
if (result == 0)
{
CloseSocket();
return;
}
if (args.BytesTransferred == 0)
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(args);
ReadHandler(_receiveBuffer, result);
}
catch (Exception ex)
{
Log.outDebug(LogFilter.Network, ex.Message);
}
}
public abstract void ReadHandler(SocketAsyncEventArgs args);
public async Task AsyncHandshake(X509Certificate2 certificate)
{
try
{
await (_stream as SslStream).AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls12, false);
}
catch (Exception ex)
{
await HandshakeHandler(ex);
return;
}
public void AsyncWrite(byte[] data)
await HandshakeHandler();
}
public virtual Task HandshakeHandler(Exception exception = null) { return null; }
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()
+5
View File
@@ -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)
{
+16 -4
View File
@@ -506,13 +506,25 @@ 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);
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)
+2 -4
View File
@@ -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;
}
+7 -7
View File
@@ -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);
@@ -1,93 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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;
}
}
-239
View File
@@ -1,239 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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
}
}
-90
View File
@@ -1,90 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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;
}
}
-225
View File
@@ -1,225 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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
}
}
@@ -1,84 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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;
}
}
-9
View File
@@ -1,9 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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
{
}
}
@@ -1,9 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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
{
}
}
+1 -2
View File
@@ -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
+26 -338
View File
@@ -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<int, ObjectGuid>();
protected ObjectGuid[] BgCreatures;// = new Dictionary<int, ObjectGuid>();
public uint[] Buff_Entries = { BattlegroundConst.SpeedBuff, BattlegroundConst.RegenBuff, BattlegroundConst.BerserkerBuff };
// Battleground
@@ -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<uint>(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<uint>(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<string>(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<uint, BattlegroundTypeId> mBattleMastersMap = new();
Dictionary<BattlegroundTypeId, BattlegroundTemplate> _battlegroundTemplates = new();
Dictionary<uint, BattlegroundTemplate> _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;
}
}
@@ -0,0 +1,136 @@
// Copyright (c) CypherCore <http://github.com/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;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,658 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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<ObjectGuid> _gameobjectsToRemoveOnMatchStart = new();
List<ObjectGuid> _creaturesToRemoveOnMatchStart = new();
List<ObjectGuid> _doors = new();
List<ObjectGuid> _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
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,803 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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<uint, BgEyeOfStormControlZoneHandler> _controlZoneHandlers = new();
List<ObjectGuid> _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<Player> 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
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
@@ -1,10 +0,0 @@
// Copyright (c) CypherCore <http://github.com/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) { }
}
}
+9 -8
View File
@@ -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);
}
}
+1 -11
View File
@@ -682,11 +682,6 @@ namespace Game.Chat
WorldSafeLocsEntry nearestLoc = null;
if (linked == "linked")
{
Battleground bg = player.GetBattleground();
if (bg != null)
nearestLoc = bg.GetClosestGraveyard(player);
else
{
BattleField bf = Global.BattleFieldMgr.GetBattlefieldToZoneId(player.GetMap(), player.GetZoneId());
if (bf != null)
@@ -694,7 +689,6 @@ namespace Game.Chat
else
nearestLoc = Global.ObjectMgr.GetClosestGraveyard(player, player.GetTeam(), player);
}
}
else
{
float x = player.GetPositionX();
@@ -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");
+1 -1
View File
@@ -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());
+1 -2
View File
@@ -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;
});
+3 -29
View File
@@ -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())
+70 -107
View File
@@ -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)
{
if (IsEmpty())
public bool TryConsumeTo(out dynamic val, Type type)
{
val = default;
return _allowEmptyTokens;
}
if (IsEmpty())
return _allowEmptyTokens;
switch (Type.GetTypeCode(type))
{
case TypeCode.SByte:
val = _arg.NextByte(":");
return true;
}
public bool TryConsumeTo(out ushort val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
case TypeCode.Int16:
val = _arg.NextUInt16(":");
return true;
}
public bool TryConsumeTo(out uint val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
case TypeCode.Int32:
val = _arg.NextUInt32(":");
return true;
}
public bool TryConsumeTo(out ulong val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
case TypeCode.Int64:
val = _arg.NextUInt64(":");
return true;
}
public bool TryConsumeTo(out sbyte val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextSByte(":");
case TypeCode.Byte:
val = _arg.NextByte(":");
return true;
}
public bool TryConsumeTo(out short val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextInt16(":");
case TypeCode.UInt16:
val = _arg.NextUInt16(":");
return true;
}
public bool TryConsumeTo(out int val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextInt32(":");
case TypeCode.UInt32:
val = _arg.NextUInt32(":");
return true;
}
public bool TryConsumeTo(out long val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = _arg.NextInt64(":");
case TypeCode.UInt64:
val = _arg.NextUInt64(":");
return true;
}
public bool TryConsumeTo(out float val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
case TypeCode.Single:
val = _arg.NextSingle(":");
return true;
}
public bool TryConsumeTo(out ObjectGuid val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
val = ObjectGuid.FromString(_arg.NextString(":"));
case TypeCode.Double:
val = _arg.NextDouble(":");
return true;
}
public bool TryConsumeTo(out string val)
{
if (IsEmpty())
{
val = default;
return _allowEmptyTokens;
}
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;
}
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(); }
@@ -19,7 +19,7 @@ namespace Game.Collision
void InitEmpty()
{
tree= new uint[3];
tree = new uint[3];
objects = Array.Empty<uint>();
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)
{
+21 -16
View File
@@ -40,34 +40,41 @@ namespace Game.Collision
public class WModelAreaCallback : WorkerCallback
{
public WModelAreaCallback(List<GroupModel> vals, Vector3 down)
List<GroupModel> prims;
public GroupModel[] hit = new GroupModel[3];
public WModelAreaCallback(List<GroupModel> vals)
{
prims = vals;
hit = null;
zDist = float.PositiveInfinity;
zVec = down;
}
List<GroupModel> 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<GroupModel> models;
public bool hit;
public WModelRayCallBack(List<GroupModel> mod)
{
models = mod;
@@ -79,8 +86,6 @@ namespace Game.Collision
if (result) hit = true;
return hit;
}
List<GroupModel> models;
public bool hit;
}
public class GModelRayCallback : WorkerCallback
+64 -14
View File
@@ -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;
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;
Ray ray = new(rPos, down);
bool hit = IntersectRay(ray, ref dist, false);
if (hit)
if (IntersectRay(ray, ref dist, false))
{
z_dist = dist - 0.1f;
return hit;
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;
+2 -6
View File
@@ -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:
+57 -5
View File
@@ -505,6 +505,41 @@ namespace Game
foreach (var (id, conditions) in ConditionStorage[ConditionSourceType.Graveyard])
AddToGraveyardData(id, conditions);
bool isPlayerConditionIdUsedByCondition(int playerConditionId, List<Condition> conditions, Dictionary<ConditionSourceType, Dictionary<ConditionId, List<Condition>>> 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 =
+2 -2
View File
@@ -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;
@@ -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) { }
+7 -3
View File
@@ -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)
+69 -123
View File
@@ -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)
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,9 +2436,8 @@ namespace Game.Entities
return;
Player player = user.ToPlayer();
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(info.ItemForge.conditionID1);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(player, playerCondition))
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<uint> 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<ObjectGuid> 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<ObjectGuid> GetTapList() { return m_tapList; }
void SetTapList(List<ObjectGuid> tapList) { m_tapList = tapList; }
public List<ObjectGuid> GetTapList() { return m_tapList; }
public void SetTapList(List<ObjectGuid> 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)
@@ -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; }
}
}
+1 -5
View File
@@ -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)
+3 -10
View File
@@ -72,9 +72,7 @@ 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))
if (owner == null || !ConditionManager.IsPlayerMeetingCondition(owner, artifactAppearance.UnlockPlayerConditionID))
continue;
SetModifier(ItemModifier.ArtifactAppearanceId, artifactAppearance.Id);
@@ -591,14 +589,10 @@ 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 (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:
break;
@@ -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)
{
@@ -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;
@@ -112,28 +112,32 @@ namespace Game.Entities
ushort pathProgress = 0xFFFF;
switch (gameObject.GetGoType())
{
case GameObjectTypes.QuestGiver:
if (gameObject.ActivateToQuest(receiver))
dynFlags |= GameObjectDynamicLowFlags.Activate;
break;
case GameObjectTypes.Chest:
if (gameObject.ActivateToQuest(receiver))
dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
else if (receiver.IsGameMaster())
dynFlags |= GameObjectDynamicLowFlags.Activate;
break;
case GameObjectTypes.Button:
case GameObjectTypes.Goober:
if (gameObject.ActivateToQuest(receiver))
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;
}
else if (receiver.IsGameMaster())
}
break;
case GameObjectTypes.QuestGiver:
if (gameObject.CanActivateForPlayer(receiver))
dynFlags |= GameObjectDynamicLowFlags.Activate;
break;
case GameObjectTypes.Chest:
if (gameObject.CanActivateForPlayer(receiver))
dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle | GameObjectDynamicLowFlags.Highlight;
else if (receiver.IsGameMaster())
dynFlags |= GameObjectDynamicLowFlags.Activate | GameObjectDynamicLowFlags.Sparkle;
break;
case GameObjectTypes.Generic:
if (gameObject.ActivateToQuest(receiver))
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:
@@ -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<uint> HonorLevel = new(0, 30);
public UpdateField<long> LogoutTime = new(0, 31);
public UpdateFieldString Name = new(32, 33);
public UpdateField<int> Field_B0 = new(32, 34);
public UpdateField<int> Field_B4 = new(32, 35);
public UpdateField<int> Field_1AC = new(32, 34);
public UpdateField<int> Field_1B0 = new(32, 35);
public UpdateField<int> CurrentBattlePetSpeciesID = new(32, 36);
public UpdateField<CTROptions> CtrOptions = new(32, 37);
public UpdateField<int> CovenantID = new(32, 38);
public UpdateField<int> SoulbindID = new(32, 39);
public UpdateField<DungeonScoreSummary> DungeonScore = new(32, 40);
public OptionalUpdateField<DeclinedNames> DeclinedNames = new(32, 41);
public UpdateField<CustomTabardInfo> PersonalTabard = new(32, 42);
public UpdateFieldArray<byte> PartyType = new(2, 43, 44);
public UpdateFieldArray<QuestLog> QuestLog = new(175, 46, 47);
public UpdateFieldArray<VisibleItem> VisibleItems = new(19, 222, 223);
public UpdateFieldArray<float> AvgItemLevel = new(6, 242, 243);
public UpdateFieldArray<uint> Field_3120 = new(19, 249, 250);
public UpdateField<ObjectGuid> SpectateTarget = new(32, 41);
public UpdateField<int> Field_200 = new(32, 42);
public OptionalUpdateField<DeclinedNames> DeclinedNames = new(32, 43);
public UpdateField<CustomTabardInfo> PersonalTabard = new(32, 44);
public UpdateFieldArray<byte> PartyType = new(2, 45, 46);
public UpdateFieldArray<QuestLog> QuestLog = new(175, 48, 49);
public UpdateFieldArray<VisibleItem> VisibleItems = new(19, 224, 225);
public UpdateFieldArray<float> AvgItemLevel = new(6, 244, 245);
public UpdateFieldArray<ItemInstance> VisibleEquipableSpells = new(16, 251, 252);
public UpdateFieldArray<uint> 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();
}
+7 -2
View File
@@ -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())
{
@@ -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))
if (!ConditionManager.IsPlayerMeetingCondition(player, mount.PlayerConditionID))
return false;
}
if (!learned)
{
+1 -1
View File
@@ -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();
+1 -3
View File
@@ -3612,9 +3612,7 @@ 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))
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)transmogIllusion.UnlockConditionID))
continue;
GetSession().GetCollectionMgr().AddTransmogIllusion(transmogIllusion.Id);
+1 -1
View File
@@ -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;
}
+2 -7
View File
@@ -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,15 +3272,11 @@ namespace Game.Entities
return false;
}
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(crItem.PlayerConditionId);
if (playerCondition != null)
{
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(this, crItem.PlayerConditionId))
{
SendEquipError(InventoryResult.ItemLocked);
return false;
}
}
// check current item amount if it limited
if (crItem.maxcount != 0)
+1 -1
View File
@@ -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;
+18 -7
View File
@@ -1174,9 +1174,7 @@ namespace Game.Entities
{
foreach (QuestRewardDisplaySpell displaySpell in quest.RewardDisplaySpell)
{
var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(displaySpell.PlayerConditionId);
if (playerCondition != null)
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(this, displaySpell.PlayerConditionId))
continue;
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(displaySpell.SpellId, GetMap().GetDifficultyID());
@@ -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,15 +3305,17 @@ 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);
else
{
switch (gameObject.GetGoType())
{
case GameObjectTypes.QuestGiver:
case GameObjectTypes.Chest:
case GameObjectTypes.Goober:
case GameObjectTypes.Generic:
case GameObjectTypes.SpellFocus:
case GameObjectTypes.Goober:
case GameObjectTypes.GatheringNode:
if (Global.ObjectMgr.IsGameObjectForQuests(gameObject.GetEntry()))
objMask.MarkChanged(gameObject.m_objectData.DynamicFlags);
@@ -3313,6 +3323,7 @@ namespace Game.Entities
default:
break;
}
}
if (objMask.GetUpdateMask().IsAnySet() || goMask.GetUpdateMask().IsAnySet())
gameObject.BuildValuesUpdateForPlayerWithMask(udata, objMask.GetUpdateMask(), goMask.GetUpdateMask(), this);
@@ -742,9 +742,7 @@ 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))
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)talentInfo.PlayerConditionID))
return TalentLearnResult.FailedCantDoThatRightNow;
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
+8 -38
View File
@@ -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,13 +4438,6 @@ namespace Game.Entities
}
WorldSafeLocsEntry closestGrave = null;
// Special handle for Battlegroundmaps
Battleground bg = GetBattleground();
if (bg != null)
closestGrave = bg.GetClosestGraveyard(this);
else
{
var bf = BattleFieldMgr.GetBattlefieldToZoneId(GetMap(), GetZoneId());
if (bf != null)
closestGrave = bf.GetClosestGraveyard(this);
@@ -4470,7 +4447,6 @@ namespace Game.Entities
if (instance != null)
closestGrave = ObjectMgr.GetWorldSafeLoc(instance.GetEntranceLocation());
}
}
if (closestGrave == null)
closestGrave = ObjectMgr.GetClosestGraveyard(this, GetTeam(), this);
@@ -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;
+1 -5
View File
@@ -1667,15 +1667,11 @@ namespace Game.Entities
continue;
}
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(corruptionEffect.PlayerConditionID);
if (playerCondition != null)
{
if (!ConditionManager.IsPlayerMeetingCondition(this, playerCondition))
if (!ConditionManager.IsPlayerMeetingCondition(this, (uint)corruptionEffect.PlayerConditionID))
{
RemoveAura(corruptionEffect.Aura);
continue;
}
}
CastSpell(this, corruptionEffect.Aura, true);
}
+9 -5
View File
@@ -154,13 +154,17 @@ 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))
if (!ConditionManager.IsPlayerMeetingCondition(player, To.ConditionID))
continue;
shortestPath.Add(GetNodeIDFromVertexID(edge.To));
+1 -6
View File
@@ -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))
if (thisPlayer != null && !ConditionManager.IsPlayerMeetingCondition(thisPlayer, (uint)mountCapability.PlayerConditionID))
continue;
}
return mountCapability;
}
+1 -2
View File
@@ -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;
-5
View File
@@ -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();
+58 -3
View File
@@ -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<uint>(0);
DestructibleHitpoint data = new();
data.Id = id;
data.IntactNumHits = result.Read<uint>(1);
data.DamagedNumHits = result.Read<uint>(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,9 +5214,12 @@ 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);
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<ulong, GameObjectAddon> _gameObjectAddonStorage = new();
MultiMap<uint, uint> _gameObjectQuestItemStorage = new();
List<uint> _gameObjectForQuestStorage = new();
Dictionary<uint, DestructibleHitpoint> _destructibleHitpointStorage = new();
//Item
Dictionary<uint, ItemTemplate> ItemTemplateStorage = new();
+1 -3
View File
@@ -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);
}
}
}
+1 -3
View File
@@ -161,9 +161,7 @@ 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))
if (!ConditionManager.IsPlayerMeetingCondition(_player, artifactAppearance.UnlockPlayerConditionID))
return;
artifact.SetAppearanceModId(artifactAppearance.ItemAppearanceModifierID);
+23 -4
View File
@@ -63,16 +63,35 @@ namespace Game
SendPacket(bnetResponse);
}
public void SendBattlenetRequest(uint serviceHash, uint methodId, IMessage request, Action<CodedInputStream> callback)
public void SendBattlenetRequest(OriginalHash serviceHash, uint methodId, IMessage request, bool client, bool server, Action<CodedInputStream> 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<CodedInputStream> 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++;
+2 -6
View File
@@ -1394,9 +1394,7 @@ 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))
if (!ConditionManager.IsPlayerMeetingCondition(_player, (uint)conditionalChrModel.PlayerConditionID))
return;
}
@@ -1632,9 +1630,7 @@ 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))
if (!ConditionManager.IsPlayerMeetingCondition(_player, illusion.TransmogUseConditionID))
return false;
if (illusion.ScalingClassRestricted > 0 && illusion.ScalingClassRestricted != (byte)_player.GetClass())
+1 -6
View File
@@ -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,9 +449,7 @@ 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))
if (!ConditionManager.IsPlayerMeetingCondition(_player, (uint)itr.CharLevelConditionID))
continue;
splashScreen = itr;
+1 -2
View File
@@ -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)
+2 -4
View File
@@ -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)
{
+8 -5
View File
@@ -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);
+2 -11
View File
@@ -191,15 +191,7 @@ namespace Game
var mountDisplays = Global.DB2Mgr.GetMountDisplays(mount.Id);
if (mountDisplays != null)
{
List<MountXDisplayRecord> usableDisplays = mountDisplays.Where(mountDisplay =>
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountDisplay.PlayerConditionID);
if (playerCondition != null)
return ConditionManager.IsPlayerMeetingCondition(GetPlayer(), playerCondition);
return true;
}).ToList();
List<MountXDisplayRecord> 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())
{
@@ -129,15 +129,11 @@ namespace Game
return;
}
var condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.UnlockConditionID);
if (condition != null)
{
if (!ConditionManager.IsPlayerMeetingCondition(player, condition))
if (!ConditionManager.IsPlayerMeetingCondition(player, (uint)illusion.UnlockConditionID))
{
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;
cost += illusion.TransmogCost;
+45 -12
View File
@@ -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;
}
+22 -5
View File
@@ -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();
+3 -2
View File
@@ -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
@@ -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;
+1 -2
View File
@@ -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)
@@ -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<AuctionListFilterClass> 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)
@@ -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
@@ -43,7 +43,7 @@ namespace Game.Networking.Packets
public override void Read()
{
PlayerGuid = _worldPacket.ReadPackedGuid();
DataType = (AccountDataTypes)_worldPacket.ReadBits<uint>(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<uint>(4);
PlayerGuid = _worldPacket.ReadPackedGuid();
DataType = (AccountDataTypes)_worldPacket.ReadInt32();
uint compressedSize = _worldPacket.ReadUInt32();
if (compressedSize != 0)

Some files were not shown because too many files have changed in this diff Show More