diff options
422 files changed, 23797 insertions, 9898 deletions
diff --git a/dep/PackageList.txt b/dep/PackageList.txt index 5d3d4bdcc4d..28099265772 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -38,4 +38,4 @@ gSOAP (a portable development toolkit for C and C++ XML Web services and XML dat StormLib (a pack of modules, written in C++, which are able to read and also to write files from/to the MPQ archives) http://www.zezula.net/en/mpq/stormlib.html - Version: 8.04
\ No newline at end of file + Version: 8.04 diff --git a/dep/StormLib/CMakeLists.txt b/dep/StormLib/CMakeLists.txt index bc6f947af13..a6735e0a6a0 100644 --- a/dep/StormLib/CMakeLists.txt +++ b/dep/StormLib/CMakeLists.txt @@ -236,21 +236,22 @@ set(TEST_SRC_FILES add_definitions(-D_7ZIP_ST -DBZ_STRICT_ANSI) -if( WIN32 ) - if( MSVC ) +if(WIN32) + if(MSVC) add_definitions(-D_7ZIP_ST -DWIN32) endif() set(SRC_ADDITIONAL_FILES ${ZLIB_BZIP2_FILES} ${TOMCRYPT_FILES} ${TOMMATH_FILES}) + set(LINK_LIBS wininet) endif() -if( APPLE ) +if(APPLE) set(LINK_LIBS z bz2) set(SRC_ADDITIONAL_FILES ${TOMCRYPT_FILES} ${TOMMATH_FILES}) endif() -if( ${CMAKE_SYSTEM_NAME} STREQUAL Linux ) +if (${CMAKE_SYSTEM_NAME} STREQUAL Linux) option(WITH_LIBTOMCRYPT "Use system LibTomCrypt library" OFF) - if( WITH_LIBTOMCRYPT ) + if(WITH_LIBTOMCRYPT) set(LINK_LIBS z bz2 tomcrypt) else() set(LINK_LIBS z bz2) @@ -261,17 +262,17 @@ endif() add_library(storm STATIC ${SRC_FILES} ${SRC_ADDITIONAL_FILES}) target_link_libraries(storm ${LINK_LIBS}) -if( APPLE ) +if(APPLE) set_target_properties(storm PROPERTIES FRAMEWORK true) set_target_properties(storm PROPERTIES PUBLIC_HEADER "src/StormLib.h src/StormPort.h") set_target_properties(storm PROPERTIES LINK_FLAGS "-framework Carbon") endif() -if( UNIX ) +if(UNIX) set_target_properties(storm PROPERTIES SOVERSION 0) endif() # On Win32, build StormLib.dll since we don't want to clash with Storm.dll -if( WIN32 ) +if(WIN32) set_target_properties(storm PROPERTIES OUTPUT_NAME StormLib) endif() diff --git a/dep/StormLib/doc/d3-authenticationcode-deDE.txt b/dep/StormLib/doc/d3-authenticationcode-deDE.txt new file mode 100644 index 00000000000..cac66712af0 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-deDE.txt @@ -0,0 +1 @@ +UCMXF6EJY352EFH4XFRXCFH2XC9MQRZK
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-enGB.txt b/dep/StormLib/doc/d3-authenticationcode-enGB.txt new file mode 100644 index 00000000000..2bc9c83859d --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-enGB.txt @@ -0,0 +1 @@ +MMKVHY48RP7WXP4GHYBQ7SL9J9UNPHBP
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-enSG.txt b/dep/StormLib/doc/d3-authenticationcode-enSG.txt new file mode 100644 index 00000000000..e6f1ec29609 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-enSG.txt @@ -0,0 +1 @@ +8MXLWHQ7VGGLTZ9MQZQSFDCLJYET3CPP
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-enUS.txt b/dep/StormLib/doc/d3-authenticationcode-enUS.txt new file mode 100644 index 00000000000..8d73e61def9 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-enUS.txt @@ -0,0 +1 @@ +EJ2R5TM6XFE2GUNG5QDGHKQ9UAKPWZSZ
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-esES.txt b/dep/StormLib/doc/d3-authenticationcode-esES.txt new file mode 100644 index 00000000000..6b1b0a1b811 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-esES.txt @@ -0,0 +1 @@ +PBGFBE42Z6LNK65UGJQ3WZVMCLP4HQQT
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-esMX.txt b/dep/StormLib/doc/d3-authenticationcode-esMX.txt new file mode 100644 index 00000000000..504759e8d55 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-esMX.txt @@ -0,0 +1 @@ +X7SEJJS9TSGCW5P28EBSC47AJPEY8VU2
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-frFR.txt b/dep/StormLib/doc/d3-authenticationcode-frFR.txt new file mode 100644 index 00000000000..bb35a2bfdc6 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-frFR.txt @@ -0,0 +1 @@ +5KVBQA8VYE6XRY3DLGC5ZDE4XS4P7YA2
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-itIT.txt b/dep/StormLib/doc/d3-authenticationcode-itIT.txt new file mode 100644 index 00000000000..a62031d3883 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-itIT.txt @@ -0,0 +1 @@ +478JD2K56EVNVVY4XX8TDWYT5B8KB254
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-koKR.txt b/dep/StormLib/doc/d3-authenticationcode-koKR.txt new file mode 100644 index 00000000000..296ffcc9450 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-koKR.txt @@ -0,0 +1 @@ +8TS4VNFQRZTN6YWHE9CHVDH9NVWD474A
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-plPL.txt b/dep/StormLib/doc/d3-authenticationcode-plPL.txt new file mode 100644 index 00000000000..a92563c1815 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-plPL.txt @@ -0,0 +1 @@ +LJ52Z32DF4LZ4ZJJXVKK3AZQA6GABLJB
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-ptBR.txt b/dep/StormLib/doc/d3-authenticationcode-ptBR.txt new file mode 100644 index 00000000000..e6e5c3568d9 --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-ptBR.txt @@ -0,0 +1 @@ +K6BDHY2ECUE2545YKNLBJPVYWHE7XYAG
\ No newline at end of file diff --git a/dep/StormLib/doc/d3-authenticationcode-zhTW.txt b/dep/StormLib/doc/d3-authenticationcode-zhTW.txt new file mode 100644 index 00000000000..138a5449c7a --- /dev/null +++ b/dep/StormLib/doc/d3-authenticationcode-zhTW.txt @@ -0,0 +1 @@ +6VWCQTN8V3ZZMRUCZXV8A8CGUX2TAA8H
\ No newline at end of file diff --git a/dep/StormLib/doc/diablo3_ruru_disk_encrypted_win.blob b/dep/StormLib/doc/diablo3_ruru_disk_encrypted_win.blob new file mode 100644 index 00000000000..7972b2d7636 --- /dev/null +++ b/dep/StormLib/doc/diablo3_ruru_disk_encrypted_win.blob @@ -0,0 +1,49 @@ +{ +"config":{ + "product": "D3", + "install_progress_percent": 70.0, + "install_progress_info": [8000000000.0, 0.0, 0.0], + "download_progress_info": [10000000.0, 500000000.0, 500000000.0], + "install_progress_speed": 5000000.0, + "tome_download_progress_percent": 0.0, + "updater_product": "d3_patch", + "expansion_level": 0, + "ptr": false, + "beta": false, + "update_method": "patch on demand", + "supports_multibox": false, + "data_dir": "Data_D3/PC/MPQs/", + "patch_url": "http://ruRU.patch.battle.net:1119/patch", + "update_regex": "(?P<prefix>d3-update-(?P<dataset>\\w+))-(?P<build>\\d+)\\.mpq$", + "update_identifier": "d3-update-", + "torrent_file_path": "Diablo III.tfil", + "manifest_file_path": "Diablo III.mfil", + "priority_file_path": "Diablo III.pfil", + "priority_file_layout": "Retail", + "binary_version_path": "Diablo III.exe", + "binary_launch_path": "Diablo III.exe", + "display_locales":["ruRU"], + "supported_locales" : ["enUS", "esMX", "ptBR", "enGB", "deDE", "esES", "frFR", "itIT", "plPL", "enSG", "ptPT", "ruRU", "koKR", "zhTW", "zhCN"], + "launch_arguments":["-launch","-uid","diablo3_ruru"], + "form": { + "eula": { + "eula":false + }, + "game_dir": { + "default": "Program Files", + "dirname": "Diablo III", + "required_space": 15032385536 + }, + "language": { + "default":["ruRU"], + "list":["ruRU"] + }, + "authentication_key": { + "url": [ + "http://ruru.nydus.battle.net/D3/ruRU/setup/mediakey", + "http://dist.blizzard.com/mediakey/d3-authenticationcode-ruRU.txt" + ] + } + } + } +}
\ No newline at end of file diff --git a/dep/StormLib/doc/diablo3_urls.txt b/dep/StormLib/doc/diablo3_urls.txt new file mode 100644 index 00000000000..d89f4899528 --- /dev/null +++ b/dep/StormLib/doc/diablo3_urls.txt @@ -0,0 +1,14 @@ +http://dist.blizzard.com/mediakey/d3-authenticationcode-deDE.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-enGB.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-enSG.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-enUS.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-esES.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-esMX.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-frFR.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-itIT.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-koKR.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-plPL.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-ptBR.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-ruRU.txt <==== +http://dist.blizzard.com/mediakey/d3-authenticationcode-zhTW.txt +http://dist.blizzard.com/mediakey/d3-authenticationcode-zhCN.txt <==== diff --git a/dep/StormLib/searchFix.patch b/dep/StormLib/searchFix.patch deleted file mode 100644 index d4ba11d8645..00000000000 --- a/dep/StormLib/searchFix.patch +++ /dev/null @@ -1,49 +0,0 @@ -diff --git a/dep/StormLib/src/SFileFindFile.cpp b/dep/StormLib/src/SFileFindFile.cpp -index aa065d2..542637b 100644 ---- a/dep/StormLib/src/SFileFindFile.cpp -+++ b/dep/StormLib/src/SFileFindFile.cpp -@@ -31,7 +31,7 @@ struct TMPQSearch - DWORD dwSearchTableItems; // Number of items in the search table - DWORD dwNextIndex; // Next file index to be checked - DWORD dwFlagMask; // For checking flag mask -- char szSearchMask[1]; // Search mask (variable length) -+ char * szSearchMask; // Search mask (variable length) - }; - - //----------------------------------------------------------------------------- -@@ -69,7 +69,7 @@ bool CheckWildCard(const char * szString, const char * szWildCard) - szString++; - } - -- // If there is '*', means zero or more chars. We have to -+ // If there is '*', means zero or more chars. We have to - // find the sequence after '*' - if(*szWildCard == '*') - { -@@ -337,6 +337,8 @@ static void FreeMPQSearch(TMPQSearch *& hs) - { - if(hs->pSearchTable != NULL) - STORM_FREE(hs->pSearchTable); -+ if(hs->szSearchMask != NULL) -+ free(hs->szSearchMask); // allocated with strdup - STORM_FREE(hs); - hs = NULL; - } -@@ -376,7 +378,7 @@ HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DA - if(nError == ERROR_SUCCESS) - { - memset(hs, 0, sizeof(TMPQSearch)); -- strcpy(hs->szSearchMask, szMask); -+ hs->szSearchMask = strdup(szMask); - hs->dwFlagMask = MPQ_FILE_EXISTS; - hs->ha = ha; - -@@ -406,7 +408,7 @@ HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DA - FreeMPQSearch(hs); - SetLastError(nError); - } -- -+ - // Return the result value - return (HANDLE)hs; - } diff --git a/dep/StormLib/src/FileStream.cpp b/dep/StormLib/src/FileStream.cpp index b8de102cd2e..413f2acb3a2 100644 --- a/dep/StormLib/src/FileStream.cpp +++ b/dep/StormLib/src/FileStream.cpp @@ -16,6 +16,11 @@ #define __STORMLIB_SELF__ #include "StormLib.h" #include "StormCommon.h" +#include "FileStream.h" + +#ifdef _MSC_VER +#pragma comment(lib, "wininet.lib") +#endif //----------------------------------------------------------------------------- // Local defines @@ -25,77 +30,11 @@ #endif #ifdef _MSC_VER -#pragma warning(disable: 4800) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) +#pragma warning(disable: 4800) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) #endif //----------------------------------------------------------------------------- -// Local structures - -// Structure describing the PART file header -typedef struct _PART_FILE_HEADER -{ - DWORD PartialVersion; // Always set to 2 - char GameBuildNumber[8]; // Minimum build number of the game that can use this MPQ - DWORD Unknown0C; - DWORD Unknown10; - DWORD Unknown14; // Often contains 0x1C (size of the rest of the header ?) - DWORD Unknown18; - DWORD ZeroValue1C; // Seems to always be zero - DWORD ZeroValue20; // Seems to always be zero - DWORD ZeroValue24; // Seems to always be zero - DWORD FileSizeLo; // Low 32 bits of the file size - DWORD FileSizeHi; // High 32 bits of the file size - DWORD BlockSize; // Size of one file block, in bytes - -} PART_FILE_HEADER, *PPART_FILE_HEADER; - -// Structure describing the block-to-file map entry -typedef struct _PART_FILE_MAP_ENTRY -{ - DWORD Flags; // 3 = the block is present in the file - DWORD BlockOffsLo; // Low 32 bits of the block position in the file - DWORD BlockOffsHi; // High 32 bits of the block position in the file - DWORD Unknown0C; - DWORD Unknown10; - -} PART_FILE_MAP_ENTRY, *PPART_FILE_MAP_ENTRY; - -struct TPartFileStream : public TFileStream -{ - ULONGLONG VirtualSize; // Virtual size of the file - ULONGLONG VirtualPos; // Virtual position in the file - DWORD BlockCount; // Number of file blocks. Used by partial file stream - DWORD BlockSize; // Size of one block. Used by partial file stream - - PART_FILE_MAP_ENTRY PartMap[1]; // File map, variable length -}; - -#define MPQE_CHUNK_SIZE 0x40 // Size of one chunk to be decrypted - -struct TEncryptedStream : public TFileStream -{ - BYTE Key[MPQE_CHUNK_SIZE]; // File key -}; - -static bool IsPartHeader(PPART_FILE_HEADER pPartHdr) -{ - // Version number must be 2 - if(pPartHdr->PartialVersion == 2) - { - // GameBuildNumber must be anm ASCII number - if(isdigit(pPartHdr->GameBuildNumber[0]) && isdigit(pPartHdr->GameBuildNumber[1]) && isdigit(pPartHdr->GameBuildNumber[2])) - { - // Block size must be power of 2 - if((pPartHdr->BlockSize & (pPartHdr->BlockSize - 1)) == 0) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Non-Windows support for LastError +// Local functions - platform-specific functions #ifndef PLATFORM_WINDOWS static int nLastError = ERROR_SUCCESS; @@ -111,639 +50,1087 @@ void SetLastError(int nError) } #endif -//----------------------------------------------------------------------------- -// Local functions - platform-specific functions - #ifndef PLATFORM_LITTLE_ENDIAN void ConvertPartHeader(void * partHeader) { PPART_FILE_HEADER theHeader = (PPART_FILE_HEADER)partHeader; theHeader->PartialVersion = SwapUInt32(theHeader->PartialVersion); - theHeader->Unknown0C = SwapUInt32(theHeader->Unknown0C); - theHeader->Unknown10 = SwapUInt32(theHeader->Unknown10); - theHeader->Unknown14 = SwapUInt32(theHeader->Unknown14); - theHeader->Unknown18 = SwapUInt32(theHeader->Unknown18); - theHeader->Unknown1C = SwapUInt32(theHeader->Unknown1C); - theHeader->Unknown20 = SwapUInt32(theHeader->Unknown20); - theHeader->ZeroValue = SwapUInt32(theHeader->ZeroValue); + theHeader->Flags = SwapUInt32(theHeader->Flags); theHeader->FileSizeLo = SwapUInt32(theHeader->FileSizeLo); theHeader->FileSizeHi = SwapUInt32(theHeader->FileSizeHi); theHeader->BlockSize = SwapUInt32(theHeader->BlockSize); } #endif -#ifdef PLATFORM_MAC -static void ConvertUTCDateTimeToFileTime(const UTCDateTimePtr inTime, ULONGLONG * pFT) -{ - UInt64 intTime = ((UInt64)inTime->highSeconds << 32) + inTime->lowSeconds; - intTime *= 10000000; - intTime += 0x0153b281e0fb4000ull; +//----------------------------------------------------------------------------- +// Preparing file bitmap for a complete file of a given size - *pFT = intTime; -} +#define DEFAULT_BLOCK_SIZE 0x4000 -static OSErr FSOpenDFCompat(FSRef *ref, char permission, short *refNum) +static bool Dummy_GetBitmap( + TFileStream * pStream, + TFileBitmap * pBitmap, + DWORD Length, + LPDWORD LengthNeeded) { - HFSUniStr255 forkName; - OSErr theErr; - Boolean isFolder, wasChanged; - - theErr = FSResolveAliasFile(ref, true, &isFolder, &wasChanged); - if (theErr != noErr) + ULONGLONG FileSize = 0; + DWORD TotalLength; + DWORD BlockCount; + DWORD BitmapSize; + DWORD LastByte; + bool bResult = false; + + // Get file size and calculate bitmap length + FileStream_GetSize(pStream, FileSize); + BlockCount = (DWORD)(((FileSize - 1) / DEFAULT_BLOCK_SIZE) + 1); + BitmapSize = (DWORD)(((BlockCount - 1) / 8) + 1); + + // Calculate and give the total length + TotalLength = sizeof(TFileBitmap) + BitmapSize; + if(LengthNeeded != NULL) + *LengthNeeded = TotalLength; + + // Has the caller given enough space for storing the structure? + if(Length >= sizeof(TFileBitmap)) { - return theErr; + memset(pBitmap, 0, sizeof(TFileBitmap)); + pBitmap->EndOffset = FileSize; + pBitmap->IsComplete = 1; + pBitmap->BitmapSize = BitmapSize; + pBitmap->BlockSize = DEFAULT_BLOCK_SIZE; + bResult = true; } - - FSGetDataForkName(&forkName); -#ifdef PLATFORM_64BIT - theErr = FSOpenFork(ref, forkName.length, forkName.unicode, permission, (FSIORefNum *)refNum); -#else - theErr = FSOpenFork(ref, forkName.length, forkName.unicode, permission, refNum); -#endif - return theErr; -} -#endif -#ifdef PLATFORM_LINUX -// time_t is number of seconds since 1.1.1970, UTC. -// 1 second = 10000000 (decimal) in FILETIME -static void ConvertTimeTToFileTime(ULONGLONG * pFileTime, time_t crt_time) -{ - // Set the start to 1.1.1970 00:00:00 - *pFileTime = 0x019DB1DED53E8000ULL + (10000000 * crt_time); + // Do we have enough space to fill the bitmap as well? + if(Length >= TotalLength) + { + LPBYTE pbBitmap = (LPBYTE)(pBitmap + 1); + + // Fill the full blocks + memset(pbBitmap, 0xFF, (BlockCount / 8)); + pbBitmap += (BlockCount / 8); + bResult = true; + + // Supply the last block + if(BlockCount & 7) + { + LastByte = (1 << (BlockCount & 7)) - 1; + pbBitmap[0] = (BYTE)LastByte; + } + } + + return bResult; } -#endif -static HANDLE CreateNewFile( - const TCHAR * szFileName) // Name of the file to open +//----------------------------------------------------------------------------- +// Local functions - base file support + +static bool BaseFile_Read( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position + void * pvBuffer, // Pointer to data to be read + DWORD dwBytesToRead) // Number of bytes to read from the file { - HANDLE hFile = INVALID_HANDLE_VALUE; // Pre-set the file handle to INVALID_HANDLE_VALUE + ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos; + DWORD dwBytesRead = 0; // Must be set by platform-specific code #ifdef PLATFORM_WINDOWS { - DWORD dwShareMode = FILE_SHARE_READ; - - if(dwGlobalFlags & SFILE_FLAG_ALLOW_WRITE_SHARE) - dwShareMode |= FILE_SHARE_WRITE; - - hFile = CreateFile(szFileName, - GENERIC_READ | GENERIC_WRITE, - dwShareMode, - NULL, - CREATE_ALWAYS, - 0, - NULL); - } -#endif + // Note: StormLib no longer supports Windows 9x. + // Thus, we can use the OVERLAPPED structure to specify + // file offset to read from file. This allows us to skip + // one system call to SetFilePointer -#ifdef PLATFORM_MAC - { - FSRef theParentRef; - FSRef theFileRef; - OSErr theErr; - short fileRef; - - theErr = FSPathMakeRef((const UInt8 *)szFileName, &theFileRef, NULL); - - if (theErr == noErr) - FSDeleteObject(&theFileRef); - - // Create the FSRef for the parent directory. - UInt8 folderName[MAX_PATH]; - memset(&theFileRef, 0, sizeof(FSRef)); - CFStringRef filePathCFString = CFStringCreateWithCString(NULL, szFileName, kCFStringEncodingUTF8); - CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, filePathCFString, kCFURLPOSIXPathStyle, false); - CFURLRef folderURL = CFURLCreateCopyDeletingLastPathComponent(NULL, fileURL); - CFURLGetFileSystemRepresentation(folderURL, true, folderName, MAX_PATH); - theErr = FSPathMakeRef(folderName, &theParentRef, NULL); - CFRelease(fileURL); - CFRelease(folderURL); - - if (theErr != noErr) + // Update the byte offset + pStream->Base.File.FilePos = ByteOffset; + + // Read the data + if(dwBytesToRead != 0) { - nLastError = theErr; - return INVALID_HANDLE_VALUE; + OVERLAPPED Overlapped; + + Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32); + Overlapped.Offset = (DWORD)ByteOffset; + Overlapped.hEvent = NULL; + if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped)) + return false; } - - // Create the file - UniChar unicodeFileName[256]; - fileURL = CFURLCreateWithFileSystemPath(NULL, filePathCFString, kCFURLPOSIXPathStyle, false); - CFStringRef fileNameCFString = CFURLCopyLastPathComponent(fileURL); - CFStringGetCharacters(fileNameCFString, CFRangeMake(0, CFStringGetLength(fileNameCFString)), - unicodeFileName); - theErr = FSCreateFileUnicode(&theParentRef, CFStringGetLength(fileNameCFString), unicodeFileName, - kFSCatInfoNone, NULL, &theFileRef, NULL); - CFRelease(fileNameCFString); - CFRelease(filePathCFString); - CFRelease(fileURL); - if (theErr != noErr) +/* + // If the byte offset is different from the current file position, + // we have to update the file position + if(ByteOffset != pStream->Base.File.FilePos) { - nLastError = theErr; - return INVALID_HANDLE_VALUE; + LONG ByteOffsetHi = (LONG)(ByteOffset >> 32); + + SetFilePointer(pStream->Base.File.hFile, (LONG)ByteOffset, &ByteOffsetHi, FILE_BEGIN); + pStream->Base.File.FilePos = ByteOffset; } - theErr = FSOpenDFCompat(&theFileRef, fsRdWrPerm, &fileRef); - if(theErr != noErr) + // Read the data + if(dwBytesToRead != 0) { - nLastError = theErr; - return INVALID_HANDLE_VALUE; + if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, NULL)) + return false; } - - hFile = (HANDLE)(int)fileRef; +*/ } #endif -#ifdef PLATFORM_LINUX +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) { - intptr_t handle; + ssize_t bytes_read; - handle = open(szFileName, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if(handle == -1) + // If the byte offset is different from the current file position, + // we have to update the file position + if(ByteOffset != pStream->Base.File.FilePos) { - nLastError = errno; - return INVALID_HANDLE_VALUE; + lseek((intptr_t)pStream->Base.File.hFile, (off_t)(ByteOffset), SEEK_SET); + pStream->Base.File.FilePos = ByteOffset; } - hFile = (HANDLE)handle; + // Perform the read operation + if(dwBytesToRead != 0) + { + bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead); + if(bytes_read == -1) + { + nLastError = errno; + return false; + } + + dwBytesRead = (DWORD)(size_t)bytes_read; + } } #endif - // Return the file handle - return hFile; + // Increment the current file position by number of bytes read + // If the number of bytes read doesn't match to required amount, return false + pStream->Base.File.FilePos = ByteOffset + dwBytesRead; + if(dwBytesRead != dwBytesToRead) + SetLastError(ERROR_HANDLE_EOF); + return (dwBytesRead == dwBytesToRead); } -static HANDLE OpenExistingFile( - const TCHAR * szFileName, // Name of the file to open - bool bWriteAccess) // false = read-only, true = read/write +/** + * \a pStream Pointer to an open stream + * \a pByteOffset Pointer to file byte offset. If NULL, writes to current position + * \a pvBuffer Pointer to data to be written + * \a dwBytesToWrite Number of bytes to write to the file + */ + +static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite) { - HANDLE hFile = INVALID_HANDLE_VALUE; // Pre-set the file handle to INVALID_HANDLE_VALUE + ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos; + DWORD dwBytesWritten = 0; // Must be set by platform-specific code #ifdef PLATFORM_WINDOWS { - DWORD dwShareMode = FILE_SHARE_READ; - - if(dwGlobalFlags & SFILE_FLAG_ALLOW_WRITE_SHARE) - dwShareMode |= FILE_SHARE_WRITE; - - hFile = CreateFile(szFileName, - bWriteAccess ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, - dwShareMode, - NULL, - OPEN_EXISTING, - 0, - NULL); - } -#endif + // Note: StormLib no longer supports Windows 9x. + // Thus, we can use the OVERLAPPED structure to specify + // file offset to read from file. This allows us to skip + // one system call to SetFilePointer -#ifdef PLATFORM_MAC - { - FSRef theFileRef; - OSErr theErr; - short fileRef; - char permission = bWriteAccess ? fsRdWrPerm : fsRdPerm; + // Update the byte offset + pStream->Base.File.FilePos = ByteOffset; - theErr = FSPathMakeRef((const UInt8 *)szFileName, &theFileRef, NULL); - if(theErr != noErr) + // Read the data + if(dwBytesToWrite != 0) { - nLastError = theErr; - return INVALID_HANDLE_VALUE; - } + OVERLAPPED Overlapped; - theErr = FSOpenDFCompat(&theFileRef, permission, &fileRef); - if (theErr != noErr) + Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32); + Overlapped.Offset = (DWORD)ByteOffset; + Overlapped.hEvent = NULL; + if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped)) + return false; + } +/* + // If the byte offset is different from the current file position, + // we have to update the file position + if(ByteOffset != pStream->Base.File.FilePos) { - nLastError = theErr; - return INVALID_HANDLE_VALUE; + LONG ByteOffsetHi = (LONG)(ByteOffset >> 32); + + SetFilePointer(pStream->Base.File.hFile, (LONG)ByteOffset, &ByteOffsetHi, FILE_BEGIN); + pStream->Base.File.FilePos = ByteOffset; } - hFile = (HANDLE)(int)fileRef; + // Read the data + if(dwBytesToWrite != 0) + { + if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, NULL)) + return false; + } +*/ } #endif -#ifdef PLATFORM_LINUX +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) { - int oflag = bWriteAccess ? O_RDWR : O_RDONLY; - intptr_t handle; + ssize_t bytes_written; - handle = open(szFileName, oflag | O_LARGEFILE); - if(handle == -1) + // If the byte offset is different from the current file position, + // we have to update the file position + if(ByteOffset != pStream->Base.File.FilePos) { - nLastError = errno; - return INVALID_HANDLE_VALUE; + lseek((intptr_t)pStream->Base.File.hFile, (off_t)(ByteOffset), SEEK_SET); + pStream->Base.File.FilePos = ByteOffset; } - hFile = (HANDLE)handle; + // Perform the read operation + bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite); + if(bytes_written == -1) + { + nLastError = errno; + return false; + } + + dwBytesWritten = (DWORD)(size_t)bytes_written; } #endif - // Return the file handle - return hFile; + // Increment the current file position by number of bytes read + pStream->Base.File.FilePos = ByteOffset + dwBytesWritten; + + // Also modify the file size, if needed + if(pStream->Base.File.FilePos > pStream->Base.File.FileSize) + pStream->Base.File.FileSize = pStream->Base.File.FilePos; + + if(dwBytesWritten != dwBytesToWrite) + SetLastError(ERROR_DISK_FULL); + return (dwBytesWritten == dwBytesToWrite); } -static void CloseTheFile(HANDLE hFile) +static bool BaseFile_GetPos( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG & ByteOffset) // Pointer to file byte offset { -#ifdef PLATFORM_WINDOWS - CloseHandle(hFile); -#endif - -#ifdef PLATFORM_MAC - FSCloseFork((short)(long)hFile); -#endif + ByteOffset = pStream->Base.File.FilePos; + return true; +} -#ifdef PLATFORM_LINUX - close((intptr_t)hFile); -#endif +static bool BaseFile_GetSize( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG & FileSize) // Pointer where to store file size +{ + FileSize = pStream->Base.File.FileSize; + return true; } /** - * Renames a file to another name. - * Note that the "szNewFile" file usually exists when this function is called, - * so the function must deal with it properly + * \a pStream Pointer to an open stream + * \a NewFileSize New size of the file */ -static bool RenameFile(const TCHAR * szExistingFile, const TCHAR * szNewFile) +static bool BaseFile_SetSize(TFileStream * pStream, ULONGLONG NewFileSize) { #ifdef PLATFORM_WINDOWS - // Delete the original stream file. Don't check the result value, - // because if the file doesn't exist, it would fail - DeleteFile(szNewFile); + { + LONG FileSizeHi = (LONG)(NewFileSize >> 32); + LONG FileSizeLo; + DWORD dwNewPos; + bool bResult; - // Rename the new file to the old stream's file - return (bool)MoveFile(szExistingFile, szNewFile); -#endif + // Set the position at the new file size + dwNewPos = SetFilePointer(pStream->Base.File.hFile, (LONG)NewFileSize, &FileSizeHi, FILE_BEGIN); + if(dwNewPos == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS) + return false; -#ifdef PLATFORM_MAC - OSErr theErr; - FSRef fromFileRef; - FSRef toFileRef; - - if (FSPathMakeRef((const UInt8 *)szNewFile, &toFileRef, NULL) == noErr) - FSDeleteObject(&toFileRef); - - // Get the path to the old file - theErr = FSPathMakeRef((const UInt8 *)szExistingFile, &fromFileRef, NULL); - if (theErr != noErr) - { - nLastError = theErr; - return false; + // Set the current file pointer as the end of the file + bResult = (bool)SetEndOfFile(pStream->Base.File.hFile); + + // Restore the file position + FileSizeHi = (LONG)(pStream->Base.File.FilePos >> 32); + FileSizeLo = (LONG)(pStream->Base.File.FilePos); + SetFilePointer(pStream->Base.File.hFile, FileSizeLo, &FileSizeHi, FILE_BEGIN); + return bResult; } +#endif - // Get a CFString for the new file name - CFStringRef newFileNameCFString = CFStringCreateWithCString(NULL, szNewFile, kCFStringEncodingUTF8); - CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, newFileNameCFString, kCFURLPOSIXPathStyle, false); - CFRelease(newFileNameCFString); - newFileNameCFString = CFURLCopyLastPathComponent(fileURL); - CFRelease(fileURL); - - // Convert CFString to Unicode and rename the file - UniChar unicodeFileName[256]; - CFStringGetCharacters(newFileNameCFString, CFRangeMake(0, CFStringGetLength(newFileNameCFString)), - unicodeFileName); - theErr = FSRenameUnicode(&fromFileRef, CFStringGetLength(newFileNameCFString), unicodeFileName, - kTextEncodingUnknown, NULL); - if (theErr != noErr) +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) { - CFRelease(newFileNameCFString); - nLastError = theErr; - return false; + if(ftruncate((intptr_t)pStream->Base.File.hFile, (off_t)NewFileSize) == -1) + { + nLastError = errno; + return false; + } + + return true; } - - CFRelease(newFileNameCFString); - +#endif +} + +static bool BaseFile_GetTime(TFileStream * pStream, ULONGLONG * pFileTime) +{ + *pFileTime = pStream->Base.File.FileTime; return true; +} + +// Renames the file pointed by pStream so that it contains data from pNewStream +static bool BaseFile_Switch(TFileStream * pStream, TFileStream * pNewStream) +{ +#ifdef PLATFORM_WINDOWS + // Delete the original stream file. Don't check the result value, + // because if the file doesn't exist, it would fail + DeleteFile(pStream->szFileName); + + // Rename the new file to the old stream's file + return (bool)MoveFile(pNewStream->szFileName, pStream->szFileName); #endif -#ifdef PLATFORM_LINUX +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) // "rename" on Linux also works if the target file exists - if(rename(szExistingFile, szNewFile) == -1) + if(rename(pNewStream->szFileName, pStream->szFileName) == -1) { nLastError = errno; return false; } - + return true; #endif } -//----------------------------------------------------------------------------- -// Stream functions - normal file stream - -static bool File_GetPos( - TFileStream * pStream, // Pointer to an open stream - ULONGLONG & ByteOffset) // Pointer to file byte offset +static void BaseFile_Close(TFileStream * pStream) { - ByteOffset = pStream->RawFilePos; - return true; + if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE) + { +#ifdef PLATFORM_WINDOWS + CloseHandle(pStream->Base.File.hFile); +#endif + +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + close((intptr_t)pStream->Base.File.hFile); +#endif + } + + // Also invalidate the handle + pStream->Base.File.hFile = INVALID_HANDLE_VALUE; } -static bool File_Read( - TFileStream * pStream, // Pointer to an open stream - ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position - void * pvBuffer, // Pointer to data to be read - DWORD dwBytesToRead) // Number of bytes to read from the file +static bool BaseFile_Create( + TFileStream * pStream, + const TCHAR * szFileName, + DWORD dwStreamFlags) { - DWORD dwBytesRead = 0; // Must be set by platform-specific code +#ifdef PLATFORM_WINDOWS + { + DWORD dwWriteShare = (dwStreamFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0; + + pStream->Base.File.hFile = CreateFile(szFileName, + GENERIC_READ | GENERIC_WRITE, + dwWriteShare | FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + 0, + NULL); + if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE) + return false; + } +#endif - // If the byte offset is not entered, use the current position - if(pByteOffset == NULL) - pByteOffset = &pStream->RawFilePos; +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + { + intptr_t handle; + + handle = open(szFileName, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if(handle == -1) + { + nLastError = errno; + return false; + } + + pStream->Base.File.hFile = (HANDLE)handle; + } +#endif + + // Fill-in the entry points + pStream->BaseRead = BaseFile_Read; + pStream->BaseWrite = BaseFile_Write; + pStream->BaseGetPos = BaseFile_GetPos; + pStream->BaseGetSize = BaseFile_GetSize; + pStream->BaseSetSize = BaseFile_SetSize; + pStream->BaseSetSize = BaseFile_SetSize; + pStream->BaseGetTime = BaseFile_GetTime; + pStream->BaseClose = BaseFile_Close; + + // Reset the file position + pStream->Base.File.FileSize = 0; + pStream->Base.File.FilePos = 0; + pStream->dwFlags = dwStreamFlags; + return true; +} +static bool BaseFile_Open( + TFileStream * pStream, + const TCHAR * szFileName, + DWORD dwStreamFlags) +{ #ifdef PLATFORM_WINDOWS { - // If the byte offset is different from the current file position, - // we have to update the file position - if(*pByteOffset != pStream->RawFilePos) - { - LONG ByteOffsetHi = (LONG)(*pByteOffset >> 32); - LONG ByteOffsetLo = (LONG)(*pByteOffset); + ULARGE_INTEGER FileSize; + DWORD dwDesiredAccess = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? GENERIC_READ : GENERIC_ALL; + DWORD dwWriteShare = (dwStreamFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0; + + // Open the file + pStream->Base.File.hFile = CreateFile(szFileName, + dwDesiredAccess, + dwWriteShare | FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL); + if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE) + return false; - SetFilePointer(pStream->hFile, ByteOffsetLo, &ByteOffsetHi, FILE_BEGIN); - pStream->RawFilePos = *pByteOffset; - } + // Query the file size + FileSize.LowPart = GetFileSize(pStream->Base.File.hFile, &FileSize.HighPart); + pStream->Base.File.FileSize = FileSize.QuadPart; - // Read the data - if(dwBytesToRead != 0) - { - if(!ReadFile(pStream->hFile, pvBuffer, dwBytesToRead, &dwBytesRead, NULL)) - return false; - } + // Query last write time + GetFileTime(pStream->Base.File.hFile, NULL, NULL, (LPFILETIME)&pStream->Base.File.FileTime); } #endif -#ifdef PLATFORM_MAC +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) { - ByteCount nBytesToRead = (ByteCount)dwBytesToRead; - ByteCount nBytesRead = 0; - OSErr theErr; + struct stat fileinfo; + int oflag = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? O_RDONLY : O_RDWR; + intptr_t handle; - // If the byte offset is different from the current file position, - // we have to update the file position - if(*pByteOffset != pStream->RawFilePos) + // Open the file + handle = open(szFileName, oflag); + if(handle == -1) { - FSSetForkPosition((short)(long)pStream->hFile, fsFromStart, (SInt64)(*pByteOffset)); - pStream->RawFilePos = *pByteOffset; + nLastError = errno; + return false; } - // Read the data - if(nBytesToRead != 0) + // Get the file size + if(fstat(handle, &fileinfo) == -1) { - theErr = FSReadFork((short)(long)pStream->hFile, fsAtMark, 0, nBytesToRead, pvBuffer, &nBytesRead); - if (theErr != noErr && theErr != eofErr) - { - nLastError = theErr; - return false; - } - dwBytesRead = (DWORD)nBytesRead; + nLastError = errno; + return false; } + + // time_t is number of seconds since 1.1.1970, UTC. + // 1 second = 10000000 (decimal) in FILETIME + // Set the start to 1.1.1970 00:00:00 + pStream->Base.File.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime); + pStream->Base.File.FileSize = (ULONGLONG)fileinfo.st_size; + pStream->Base.File.hFile = (HANDLE)handle; } #endif -#ifdef PLATFORM_LINUX - { - ssize_t bytes_read; + // Fill-in the entry points + pStream->BaseRead = BaseFile_Read; + pStream->BaseWrite = BaseFile_Write; + pStream->BaseGetPos = BaseFile_GetPos; + pStream->BaseGetSize = BaseFile_GetSize; + pStream->BaseSetSize = BaseFile_SetSize; + pStream->BaseGetTime = BaseFile_GetTime; + pStream->BaseClose = BaseFile_Close; + + // Reset the file position + pStream->Base.File.FilePos = 0; + pStream->dwFlags = dwStreamFlags; + return true; +} - // If the byte offset is different from the current file position, - // we have to update the file position - if(*pByteOffset != pStream->RawFilePos) - { - lseek64((intptr_t)pStream->hFile, (off64_t)(*pByteOffset), SEEK_SET); - pStream->RawFilePos = *pByteOffset; - } +//----------------------------------------------------------------------------- +// Local functions - base memory-mapped file support - // Perform the read operation - if(dwBytesToRead != 0) - { - bytes_read = read((intptr_t)pStream->hFile, pvBuffer, (size_t)dwBytesToRead); - if(bytes_read == -1) - { - nLastError = errno; - return false; - } +static bool BaseMap_Read( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position + void * pvBuffer, // Pointer to data to be read + DWORD dwBytesToRead) // Number of bytes to read from the file +{ + ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Map.FilePos; - dwBytesRead = (DWORD)(size_t)bytes_read; - } + // Do we have to read anything at all? + if(dwBytesToRead != 0) + { + // Don't allow reading past file size + if((ByteOffset + dwBytesToRead) > pStream->Base.Map.FileSize) + return false; + + // Copy the required data + memcpy(pvBuffer, pStream->Base.Map.pbFile + (size_t)ByteOffset, dwBytesToRead); } -#endif - // Increment the current file position by number of bytes read - // If the number of bytes read doesn't match to required amount, return false - pStream->RawFilePos = *pByteOffset + dwBytesRead; - if(dwBytesRead != dwBytesToRead) - SetLastError(ERROR_HANDLE_EOF); - return (dwBytesRead == dwBytesToRead); + // Move the current file position + pStream->Base.Map.FilePos += dwBytesToRead; + return true; } -/** - * \a pStream Pointer to an open stream - * \a pByteOffset Pointer to file byte offset. If NULL, writes to current position - * \a pvBuffer Pointer to data to be written - * \a dwBytesToWrite Number of bytes to write to the file - */ +static bool BaseMap_GetPos( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG & ByteOffset) // Pointer to file byte offset +{ + ByteOffset = pStream->Base.Map.FilePos; + return true; +} -static bool File_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite) +static bool BaseMap_GetSize( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG & FileSize) // Pointer where to store file size { - DWORD dwBytesWritten = 0; // Must be set by platform-specific code + FileSize = pStream->Base.Map.FileSize; + return true; +} - // If the byte offset is not entered, use the current position - if(pByteOffset == NULL) - pByteOffset = &pStream->RawFilePos; +static bool BaseMap_GetTime(TFileStream * pStream, ULONGLONG * pFileTime) +{ + *pFileTime = pStream->Base.Map.FileTime; + return true; +} +static void BaseMap_Close(TFileStream * pStream) +{ +#ifdef PLATFORM_WINDOWS + if(pStream->Base.Map.pbFile != NULL) + UnmapViewOfFile(pStream->Base.Map.pbFile); +#endif + +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + if(pStream->Base.Map.pbFile != NULL) + munmap(pStream->Base.Map.pbFile, (size_t )pStream->Base.Map.FileSize); +#endif + + pStream->Base.Map.pbFile = NULL; +} + +static bool BaseMap_Open( + TFileStream * pStream, + const TCHAR * szFileName, + DWORD dwStreamFlags) +{ #ifdef PLATFORM_WINDOWS + + ULARGE_INTEGER FileSize; + HANDLE hFile; + HANDLE hMap; + bool bResult = false; + + // Open the file for read access + hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if(hFile != NULL) { - // If the byte offset is different from the current file position, - // we have to update the file position - if(*pByteOffset != pStream->RawFilePos) + // Retrieve file size. Don't allow mapping file of a zero size. + FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); + if(FileSize.QuadPart != 0) { - LONG ByteOffsetHi = (LONG)(*pByteOffset >> 32); - LONG ByteOffsetLo = (LONG)(*pByteOffset); + // Retrieve file time + GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime); + + // Now create mapping object + hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + if(hMap != NULL) + { + // Map the entire view into memory + // Note that this operation will fail if the file can't fit + // into usermode address space + pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); + if(pStream->Base.Map.pbFile != NULL) + { + pStream->Base.Map.FileSize = FileSize.QuadPart; + pStream->Base.Map.FilePos = 0; + bResult = true; + } - SetFilePointer(pStream->hFile, ByteOffsetLo, &ByteOffsetHi, FILE_BEGIN); - pStream->RawFilePos = *pByteOffset; + // Close the map handle + CloseHandle(hMap); + } } - // Read the data - if(!WriteFile(pStream->hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, NULL)) - return false; + // Close the file handle + CloseHandle(hFile); } + + // If the file is not there and is not available for random access, + // report error + if(bResult == false) + return false; #endif -#ifdef PLATFORM_MAC - { - ByteCount nBytesToWrite = (ByteCount)dwBytesToWrite; - ByteCount nBytesWritten = 0; - OSErr theErr; +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) + struct stat fileinfo; + intptr_t handle; + bool bResult = false; - // If the byte offset is different from the current file position, - // we have to update the file position - if(*pByteOffset != pStream->RawFilePos) + // Open the file + handle = open(szFileName, O_RDONLY); + if(handle != -1) + { + // Get the file size + if(fstat(handle, &fileinfo) != -1) { - FSSetForkPosition((short)(long)pStream->hFile, fsFromStart, (SInt64)(*pByteOffset)); - pStream->RawFilePos = *pByteOffset; + pStream->Base.Map.pbFile = (LPBYTE)mmap(NULL, (size_t)fileinfo.st_size, PROT_READ, MAP_PRIVATE, handle, 0); + if(pStream->Base.Map.pbFile != NULL) + { + // time_t is number of seconds since 1.1.1970, UTC. + // 1 second = 10000000 (decimal) in FILETIME + // Set the start to 1.1.1970 00:00:00 + pStream->Base.Map.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime); + pStream->Base.Map.FileSize = (ULONGLONG)fileinfo.st_size; + pStream->Base.Map.FilePos = 0; + bResult = true; + } } + close(handle); + } - theErr = FSWriteFork((short)(long)pStream->hFile, fsAtMark, 0, nBytesToWrite, pvBuffer, &nBytesWritten); - if (theErr != noErr) - { - nLastError = theErr; - return false; - } - dwBytesWritten = (DWORD)nBytesWritten; + // Did the mapping fail? + if(bResult == false) + { + nLastError = errno; + return false; } #endif -#ifdef PLATFORM_LINUX + // Fill-in entry points + pStream->BaseRead = BaseMap_Read; + pStream->BaseGetPos = BaseMap_GetPos; + pStream->BaseGetSize = BaseMap_GetSize; + pStream->BaseGetTime = BaseMap_GetTime; + pStream->BaseClose = BaseMap_Close; + pStream->dwFlags = dwStreamFlags; + return true; +} + +//----------------------------------------------------------------------------- +// Local functions - base HTTP file support + +static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR * szServerName) +{ + // Check for HTTP + if(!_tcsnicmp(szFileName, _T("http://"), 7)) + szFileName += 7; + + // Cut off the server name + if(szServerName != NULL) { - ssize_t bytes_written; + while(szFileName[0] != 0 && szFileName[0] != _T('/')) + *szServerName++ = *szFileName++; + *szServerName = 0; + } + else + { + while(szFileName[0] != 0 && szFileName[0] != _T('/')) + *szFileName++; + } - // If the byte offset is different from the current file position, - // we have to update the file position - if(*pByteOffset != pStream->RawFilePos) - { - lseek64((intptr_t)pStream->hFile, (off64_t)(*pByteOffset), SEEK_SET); - pStream->RawFilePos = *pByteOffset; - } + // Return the remainder + return szFileName; +} - // Perform the read operation - bytes_written = write((intptr_t)pStream->hFile, pvBuffer, (size_t)dwBytesToWrite); - if(bytes_written == -1) +static bool BaseHttp_Read( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position + void * pvBuffer, // Pointer to data to be read + DWORD dwBytesToRead) // Number of bytes to read from the file +{ +#ifdef PLATFORM_WINDOWS + ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Http.FilePos; + DWORD dwTotalBytesRead = 0; + + // Do we have to read anything at all? + if(dwBytesToRead != 0) + { + HINTERNET hRequest; + LPCTSTR szFileName; + LPBYTE pbBuffer = (LPBYTE)pvBuffer; + TCHAR szRangeRequest[0x80]; + DWORD dwStartOffset = (DWORD)ByteOffset; + DWORD dwEndOffset = dwStartOffset + dwBytesToRead; + BYTE Buffer[0x200]; + + // Open HTTP request to the file + szFileName = BaseHttp_ExtractServerName(pStream->szFileName, NULL); + hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0); + if(hRequest != NULL) { - nLastError = errno; - return false; - } + // Add range request to the HTTP headers + // http://www.clevercomponents.com/articles/article015/resuming.asp + _stprintf(szRangeRequest, _T("Range: bytes=%d-%d"), dwStartOffset, dwEndOffset); + HttpAddRequestHeaders(hRequest, szRangeRequest, 0xFFFFFFFF, HTTP_ADDREQ_FLAG_ADD_IF_NEW); - dwBytesWritten = (DWORD)(size_t)bytes_written; + // Send the request to the server + if(HttpSendRequest(hRequest, NULL, 0, NULL, 0)) + { + while(dwTotalBytesRead < dwBytesToRead) + { + DWORD dwBlockBytesToRead = dwBytesToRead - dwTotalBytesRead; + DWORD dwBlockBytesRead = 0; + + // Read the block from the file + if(dwBlockBytesToRead > sizeof(Buffer)) + dwBlockBytesToRead = sizeof(Buffer); + InternetReadFile(hRequest, pbBuffer, dwBlockBytesToRead, &dwBlockBytesRead); + + // Check for end + if(dwBlockBytesRead == 0) + break; + + // Move buffers + dwTotalBytesRead += dwBlockBytesRead; + pbBuffer += dwBlockBytesRead; + } + } + InternetCloseHandle(hRequest); + } } -#endif // Increment the current file position by number of bytes read - pStream->RawFilePos = *pByteOffset + dwBytesWritten; - if(dwBytesWritten != dwBytesToWrite) - SetLastError(ERROR_DISK_FULL); - return (dwBytesWritten == dwBytesToWrite); + pStream->Base.Http.FilePos = ByteOffset + dwTotalBytesRead; + + // If the number of bytes read doesn't match the required amount, return false + if(dwTotalBytesRead != dwBytesToRead) + SetLastError(ERROR_HANDLE_EOF); + return (dwTotalBytesRead == dwBytesToRead); + +#else + + // Not supported + pStream = pStream; + pByteOffset = pByteOffset; + pvBuffer = pvBuffer; + dwBytesToRead = dwBytesToRead; + SetLastError(ERROR_NOT_SUPPORTED); + return false; + +#endif +} + +static bool BaseHttp_GetPos( + TFileStream * pStream, // Pointer to an open stream + ULONGLONG & ByteOffset) // Pointer to file byte offset +{ + ByteOffset = pStream->Base.Http.FilePos; + return true; } -static bool File_GetSize( +static bool BaseHttp_GetSize( TFileStream * pStream, // Pointer to an open stream ULONGLONG & FileSize) // Pointer where to store file size { -#ifdef PLATFORM_WINDOWS - DWORD FileSizeHi = 0; - DWORD FileSizeLo; - - FileSizeLo = GetFileSize(pStream->hFile, &FileSizeHi); - if(FileSizeLo == INVALID_FILE_SIZE && GetLastError() != ERROR_SUCCESS) - return false; + FileSize = pStream->Base.Http.FileSize; + return true; +} - FileSize = MAKE_OFFSET64(FileSizeHi, FileSizeLo); +static bool BaseHttp_GetTime(TFileStream * pStream, ULONGLONG * pFileTime) +{ + *pFileTime = pStream->Base.Http.FileTime; return true; +} + +static void BaseHttp_Close(TFileStream * pStream) +{ +#ifdef PLATFORM_WINDOWS + if(pStream->Base.Http.hConnect != NULL) + InternetCloseHandle(pStream->Base.Http.hConnect); + pStream->Base.Http.hConnect = NULL; + + if(pStream->Base.Http.hInternet != NULL) + InternetCloseHandle(pStream->Base.Http.hInternet); + pStream->Base.Http.hInternet = NULL; +#else + pStream = pStream; #endif +} + +static bool BaseHttp_Open( + TFileStream * pStream, + const TCHAR * szFileName, + DWORD dwStreamFlags) +{ +#ifdef PLATFORM_WINDOWS + + HINTERNET hRequest; + DWORD dwTemp = 0; + bool bFileAvailable = false; + int nError = ERROR_SUCCESS; -#ifdef PLATFORM_MAC - SInt64 fileLength = 0; - OSErr theErr; + // Don't connect to the internet + if(!InternetGetConnectedState(&dwTemp, 0)) + nError = GetLastError(); - theErr = FSGetForkSize((short)(long)pStream->hFile, &fileLength); - if(theErr != noErr) + // Initiate the connection to the internet + if(nError == ERROR_SUCCESS) { - nLastError = theErr; - return false; + pStream->Base.Http.hInternet = InternetOpen(_T("StormLib HTTP MPQ reader"), + INTERNET_OPEN_TYPE_PRECONFIG, + NULL, + NULL, + 0); + if(pStream->Base.Http.hInternet == NULL) + nError = GetLastError(); } - FileSize = (ULONGLONG)fileLength; - return true; -#endif + // Connect to the server + if(nError == ERROR_SUCCESS) + { + TCHAR szServerName[MAX_PATH]; + DWORD dwFlags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE; + + // Initiate connection with the server + szFileName = BaseHttp_ExtractServerName(szFileName, szServerName); + pStream->Base.Http.hConnect = InternetConnect(pStream->Base.Http.hInternet, + szServerName, + INTERNET_DEFAULT_HTTP_PORT, + NULL, + NULL, + INTERNET_SERVICE_HTTP, + dwFlags, + 0); + if(pStream->Base.Http.hConnect == NULL) + nError = GetLastError(); + } -#ifdef PLATFORM_LINUX - struct stat64 fileinfo; + // Now try to query the file size + if(nError == ERROR_SUCCESS) + { + // Open HTTP request to the file + hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0); + if(hRequest != NULL) + { + if(HttpSendRequest(hRequest, NULL, 0, NULL, 0)) + { + ULONGLONG FileTime = 0; + DWORD dwFileSize = 0; + DWORD dwDataSize; + DWORD dwIndex = 0; + + // Check if the MPQ has Last Modified field + dwDataSize = sizeof(ULONGLONG); + if(HttpQueryInfo(hRequest, HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &FileTime, &dwDataSize, &dwIndex)) + pStream->Base.Http.FileTime = FileTime; + + // Verify if the server supports random access + dwDataSize = sizeof(DWORD); + if(HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwFileSize, &dwDataSize, &dwIndex)) + { + if(dwFileSize != 0) + { + pStream->Base.Http.FileSize = dwFileSize; + pStream->Base.Http.FilePos = 0; + bFileAvailable = true; + } + } + } + InternetCloseHandle(hRequest); + } + } - if(fstat64((intptr_t)pStream->hFile, &fileinfo) == -1) + // If the file is not there and is not available for random access, + // report error + if(bFileAvailable == false) { - nLastError = errno; + BaseHttp_Close(pStream); return false; } - FileSize = (ULONGLONG)fileinfo.st_size; + // Fill-in entry points + pStream->BaseRead = BaseHttp_Read; + pStream->BaseGetPos = BaseHttp_GetPos; + pStream->BaseGetSize = BaseHttp_GetSize; + pStream->BaseGetTime = BaseHttp_GetTime; + pStream->BaseClose = BaseHttp_Close; + pStream->dwFlags = dwStreamFlags; return true; + +#else + + // Not supported + pStream = pStream; + szFileName = szFileName; + SetLastError(ERROR_NOT_SUPPORTED); + return false; + #endif } -/** - * \a pStream Pointer to an open stream - * \a NewFileSize New size of the file - */ -static bool File_SetSize(TFileStream * pStream, ULONGLONG NewFileSize) +//----------------------------------------------------------------------------- +// Local functions - linear stream support + +static bool LinearStream_Read( + TLinearStream * pStream, // Pointer to an open stream + ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position + void * pvBuffer, // Pointer to data to be read + DWORD dwBytesToRead) // Number of bytes to read from the file { -#ifdef PLATFORM_WINDOWS + ULONGLONG ByteOffset; + ULONGLONG EndOffset; + LPBYTE pbBitmap; + DWORD BlockIndex; + DWORD ByteIndex; + DWORD BitMask; + + // At this point, we must have a bitmap set + assert(pStream->pBitmap != NULL); + + // If we have data map, we must check if the data block is present in the MPQ + if(dwBytesToRead != 0) { - LONG FileSizeHi = (LONG)(NewFileSize >> 32); - LONG FileSizeLo = (LONG)(NewFileSize); - DWORD dwNewPos; - bool bResult; + DWORD BlockSize = pStream->pBitmap->BlockSize; - // Set the position at the new file size - dwNewPos = SetFilePointer(pStream->hFile, FileSizeLo, &FileSizeHi, FILE_BEGIN); - if(dwNewPos == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS) - return false; + // Get the offset where we read it from + if(pByteOffset == NULL) + pStream->BaseGetPos(pStream, ByteOffset); + else + ByteOffset = *pByteOffset; + EndOffset = ByteOffset + dwBytesToRead; - // Set the current file pointer as the end of the file - bResult = (bool)SetEndOfFile(pStream->hFile); + // If the start of the area is within the region + // protected by data map, check each block + if(ByteOffset < pStream->pBitmap->EndOffset) + { + // Cut the end of the stream protected by the data map + EndOffset = STORMLIB_MIN(EndOffset, pStream->pBitmap->EndOffset); - // Restore the file position - FileSizeHi = (LONG)(pStream->RawFilePos >> 32); - FileSizeLo = (LONG)(pStream->RawFilePos); - SetFilePointer(pStream->hFile, FileSizeLo, &FileSizeHi, FILE_BEGIN); - return bResult; - } -#endif - -#ifdef PLATFORM_MAC - { - OSErr theErr; + // Calculate the initial block index + BlockIndex = (DWORD)(ByteOffset / BlockSize); + pbBitmap = (LPBYTE)(pStream->pBitmap + 1); - theErr = FSSetForkSize((short)(long)pStream->hFile, fsFromStart, (SInt64)NewFileSize); - if(theErr != noErr) - { - nLastError = theErr; - return false; + // Parse each block + while(ByteOffset < EndOffset) + { + // Prepare byte index and bit mask + ByteIndex = BlockIndex / 8; + BitMask = 1 << (BlockIndex & 0x07); + + // If that bit is not set, it means that the block is not present + if((pbBitmap[ByteIndex] & BitMask) == 0) + { + SetLastError(ERROR_FILE_CORRUPT); + return false; + } + + // Move to tne next block + ByteOffset += BlockSize; + BlockIndex++; + } } - - return true; } -#endif -#ifdef PLATFORM_LINUX + // Now if all tests passed, we can call the base read function + return pStream->BaseRead(pStream, pByteOffset, pvBuffer, dwBytesToRead); +} + +static bool LinearStream_Switch(TLinearStream * pStream, TLinearStream * pNewStream) +{ + // Sanity checks + assert((pNewStream->dwFlags & STREAM_PROVIDER_MASK) == STREAM_PROVIDER_LINEAR); + assert((pNewStream->dwFlags & BASE_PROVIDER_MASK) == BASE_PROVIDER_FILE); + assert((pStream->dwFlags & STREAM_PROVIDER_MASK) == STREAM_PROVIDER_LINEAR); + assert((pStream->dwFlags & BASE_PROVIDER_MASK) == BASE_PROVIDER_FILE); + + // Close the new stream + pNewStream->BaseClose(pNewStream); + + // Close the source stream + pStream->BaseClose(pStream); + + // Rename the new data source file to the existing file + if(!BaseFile_Switch(pStream, pNewStream)) + return false; + + // Now we have to open the "pStream" again + if(!BaseFile_Open(pStream, pStream->szFileName, pNewStream->dwFlags)) + return false; + + // We need to cleanup the new data stream + FileStream_Close(pNewStream); + return true; +} + +static bool LinearStream_GetBitmap( + TLinearStream * pStream, + TFileBitmap * pBitmap, + DWORD Length, + LPDWORD LengthNeeded) +{ + DWORD TotalLength; + bool bResult = false; + + // Assumed that we have bitmap now + assert(pStream->pBitmap != NULL); + + // Give the bitmap length + TotalLength = sizeof(TFileBitmap) + pStream->pBitmap->BitmapSize; + if(LengthNeeded != NULL) + *LengthNeeded = TotalLength; + + // Do we have enough space to fill at least the bitmap structure? + if(Length >= sizeof(TFileBitmap)) { - if(ftruncate((intptr_t)pStream->hFile, (off_t)NewFileSize) == -1) + // Enough space for complete bitmap? + if(Length >= TotalLength) { - nLastError = errno; - return false; + memcpy(pBitmap, pStream->pBitmap, TotalLength); + bResult = true; + } + else + { + memcpy(pBitmap, pStream->pBitmap, sizeof(TFileBitmap)); + bResult = true; } - - return true; } -#endif + + return bResult; } -//----------------------------------------------------------------------------- -// Stream functions - partial normal file stream +static void LinearStream_Close(TLinearStream * pStream) +{ + // Free the data map, if any + if(pStream->pBitmap != NULL) + STORM_FREE(pStream->pBitmap); + pStream->pBitmap = NULL; + + // Call the base class for closing the stream + return pStream->BaseClose(pStream); +} -/** - * \a pStream Pointer to an open stream - * \a ByteOffset File byte offset - */ -static bool PartFile_GetPos(TPartFileStream * pStream, ULONGLONG & ByteOffset) +static bool LinearStream_Open(TLinearStream * pStream) { - ByteOffset = pStream->VirtualPos; + // No extra work here really; just set entry points + pStream->StreamRead = pStream->BaseRead; + pStream->StreamWrite = pStream->BaseWrite; + pStream->StreamGetPos = pStream->BaseGetPos; + pStream->StreamGetSize = pStream->BaseGetSize; + pStream->StreamSetSize = pStream->BaseSetSize; + pStream->StreamGetTime = pStream->BaseGetTime; + pStream->StreamGetBmp = (STREAM_GETBMP)Dummy_GetBitmap; + pStream->StreamSwitch = (STREAM_SWITCH)LinearStream_Switch; + pStream->StreamClose = (STREAM_CLOSE)LinearStream_Close; return true; } -/** - * \a pStream Pointer to an open stream - * \a pByteOffset Pointer to file byte offset. If NULL, reads from the current position - * \a pvBuffer Pointer to data to be read - * \a dwBytesToRead Number of bytes to read from the file - */ -static bool PartFile_Read(TPartFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead) +//----------------------------------------------------------------------------- +// Local functions - partial stream support + +static bool IsPartHeader(PPART_FILE_HEADER pPartHdr) +{ + // Version number must be 2 + if(pPartHdr->PartialVersion == 2) + { + // GameBuildNumber must be an ASCII number + if(isdigit(pPartHdr->GameBuildNumber[0]) && isdigit(pPartHdr->GameBuildNumber[1]) && isdigit(pPartHdr->GameBuildNumber[2])) + { + // Block size must be power of 2 + if((pPartHdr->BlockSize & (pPartHdr->BlockSize - 1)) == 0) + return true; + } + } + + return false; +} + +static bool PartialStream_Read( + TPartialStream * pStream, + ULONGLONG * pByteOffset, + void * pvBuffer, + DWORD dwBytesToRead) { ULONGLONG RawByteOffset; LPBYTE pbBuffer = (LPBYTE)pvBuffer; @@ -789,7 +1176,7 @@ static bool PartFile_Read(TPartFileStream * pStream, ULONGLONG * pByteOffset, vo // If the part is not present in the file, we fail the read if((PartMap->Flags & 3) == 0) { - nFailReason = ERROR_CAN_NOT_COMPLETE; + nFailReason = ERROR_FILE_CORRUPT; bResult = false; break; } @@ -805,7 +1192,7 @@ static bool PartFile_Read(TPartFileStream * pStream, ULONGLONG * pByteOffset, vo RawByteOffset = MAKE_OFFSET64(PartMap->BlockOffsHi, PartMap->BlockOffsLo); if(RawByteOffset == 0) { - nFailReason = ERROR_CAN_NOT_COMPLETE; + nFailReason = ERROR_FILE_CORRUPT; bResult = false; break; } @@ -816,9 +1203,9 @@ static bool PartFile_Read(TPartFileStream * pStream, ULONGLONG * pByteOffset, vo // Append the offset within the part RawByteOffset += dwPartOffset; - if(!File_Read(pStream, &RawByteOffset, pbBuffer, dwBytesInPart)) + if(!pStream->BaseRead(pStream, &RawByteOffset, pbBuffer, dwBytesInPart)) { - nFailReason = ERROR_CAN_NOT_COMPLETE; + nFailReason = ERROR_FILE_CORRUPT; bResult = false; break; } @@ -840,69 +1227,237 @@ static bool PartFile_Read(TPartFileStream * pStream, ULONGLONG * pByteOffset, vo return (dwBytesRead == dwBytesToRead); } -static bool PartFile_Write( - TPartFileStream * pStream, // Pointer to an open stream - ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position - const void * pvBuffer, // Pointer to data to be read - DWORD dwBytesToRead) // Number of bytes to read from the file +static bool PartialStream_GetPos( + TPartialStream * pStream, + ULONGLONG & ByteOffset) { - // Keep compiler happy - dwBytesToRead = dwBytesToRead; - pByteOffset = pByteOffset; - pvBuffer = pvBuffer; - pStream = pStream; - - // Not allowed - return false; + ByteOffset = pStream->VirtualPos; + return true; } -static bool PartFile_GetSize( - TPartFileStream * pStream, // Pointer to an open stream +static bool PartialStream_GetSize( + TPartialStream * pStream, // Pointer to an open stream ULONGLONG & FileSize) // Pointer where to store file size { FileSize = pStream->VirtualSize; return true; } -static bool PartFile_SetSize( - TPartFileStream * pStream, // Pointer to an open stream - ULONGLONG NewSize) // new size of the file +static bool PartialStream_GetBitmap( + TPartialStream * pStream, + TFileBitmap * pBitmap, + DWORD Length, + LPDWORD LengthNeeded) { - // Keep compiler happy - pStream = pStream; - NewSize = NewSize; + LPBYTE pbBitmap; + DWORD TotalLength; + DWORD BitmapSize = 0; + DWORD ByteOffset; + DWORD BitMask; + bool bResult = false; - // Not allowed - return false; + // Do we have stream bitmap? + BitmapSize = ((pStream->BlockCount - 1) / 8) + 1; + + // Give the bitmap length + TotalLength = sizeof(TFileBitmap) + BitmapSize; + if(LengthNeeded != NULL) + *LengthNeeded = TotalLength; + + // Do we have enough to fill at least the header? + if(Length >= sizeof(TFileBitmap)) + { + // Fill the bitmap header + pBitmap->StartOffset = 0; + pBitmap->EndOffset = pStream->VirtualSize; + pBitmap->IsComplete = 1; + pBitmap->BitmapSize = BitmapSize; + pBitmap->BlockSize = pStream->BlockSize; + pBitmap->Reserved = 0; + + // Is there at least one incomplete block? + for(DWORD i = 0; i < pStream->BlockCount; i++) + { + if(pStream->PartMap[i].Flags != 3) + { + pBitmap->IsComplete = 0; + break; + } + } + + bResult = true; + } + + // Do we have enough space for supplying the bitmap? + if(Length >= TotalLength) + { + // Fill the file bitmap + pbBitmap = (LPBYTE)(pBitmap + 1); + for(DWORD i = 0; i < pStream->BlockCount; i++) + { + // Is the block there? + if(pStream->PartMap[i].Flags == 3) + { + ByteOffset = i / 8; + BitMask = 1 << (i & 7); + pbBitmap[ByteOffset] |= BitMask; + } + } + bResult = true; + } + + return bResult; } -/* - * Stream functions - encrypted stream - * - * Note: In original Starcraft II Installer.exe: Suffix derived from battle.net auth. code - * Address of decryption routine: 0053A3D0 http://us.battle.net/static/mediakey/sc2-authenticationcode-enUS.txt - * Pointer to decryptor object: ECX Numbers mean offset of 4-char group of auth code - * Pointer to key: ECX+0x5C -0C- -1C--08- -18--04- -14--00- -10- - */ -static const char * MpqeKey_Starcraft2_Install_enUS = "expand 32-byte kTFD80000ETR5VM5G0000K859RE5N0000WT6F3DH500005LXG"; -static const char * MpqeKey_Starcraft2_Install_enGB = "expand 32-byte kANGY000029ZH6NA20000HRGF8UDG0000NY82G8MN00006A3D"; -static const char * MpqeKey_Starcraft2_Install_deDE = "expand 32-byte kSSXH00004XFXK4KX00008EKJD3CA0000Y64ZY45M0000YD9V"; -static const char * MpqeKey_Starcraft2_Install_esES = "expand 32-byte kQU4Y0000XKTQ94PF0000N4R4UAXE0000AZ248WLK0000249P"; -static const char * MpqeKey_Starcraft2_Install_frFR = "expand 32-byte kFWPQ00006EAJ8HJE0000PFER9K9300008MA2ZG7J0000UA76"; -static const char * MpqeKey_Starcraft2_Install_itIT = "expand 32-byte kXV7E00008BL2TVAP0000GVMWUNNN0000SVBWNE7C00003G2B"; -static const char * MpqeKey_Starcraft2_Install_plPL = "expand 32-byte k83U6000048L6LULJ00004MQDB8ME0000UP6K2NSF0000YHA3"; -static const char * MpqeKey_Starcraft2_Install_ruRU = "expand 32-byte k9SH70000YEGT4BAT0000QDK978W60000V9NLVHB30000D68V"; +static void PartialStream_Close(TPartialStream * pStream) +{ + // Free the part map + if(pStream->PartMap != NULL) + STORM_FREE(pStream->PartMap); + pStream->PartMap = NULL; + + // Clear variables + pStream->VirtualSize = 0; + pStream->VirtualPos = 0; + + // Close the base stream + assert(pStream->BaseClose != NULL); + pStream->BaseClose(pStream); +} + +static bool PartialStream_Open(TPartialStream * pStream) +{ + PART_FILE_HEADER PartHdr; + ULONGLONG VirtualSize; // Size of the file stored in part file + ULONGLONG ByteOffset = {0}; + DWORD BlockCount; + + // Sanity check + assert(pStream->BaseRead != NULL); + // Attempt to read PART file header + if(pStream->BaseRead(pStream, &ByteOffset, &PartHdr, sizeof(PART_FILE_HEADER))) + { + // We need to swap PART file header on big-endian platforms + BSWAP_PART_HEADER(&PartHdr); + + // Verify the PART file header + if(IsPartHeader(&PartHdr)) + { + // Calculate the number of parts in the file + VirtualSize = MAKE_OFFSET64(PartHdr.FileSizeHi, PartHdr.FileSizeLo); + assert(VirtualSize != 0); + BlockCount = (DWORD)((VirtualSize + PartHdr.BlockSize - 1) / PartHdr.BlockSize); + + // Allocate the map entry array + pStream->PartMap = STORM_ALLOC(PART_FILE_MAP_ENTRY, BlockCount); + if(pStream->PartMap != NULL) + { + // Load the block map + if(pStream->BaseRead(pStream, NULL, pStream->PartMap, BlockCount * sizeof(PART_FILE_MAP_ENTRY))) + { + // Swap the array of file map entries + BSWAP_ARRAY32_UNSIGNED(pStream->PartMap, BlockCount * sizeof(PART_FILE_MAP_ENTRY)); + + // Fill the members of PART file stream + pStream->VirtualSize = ((ULONGLONG)PartHdr.FileSizeHi) + PartHdr.FileSizeLo; + pStream->VirtualPos = 0; + pStream->BlockCount = BlockCount; + pStream->BlockSize = PartHdr.BlockSize; + + // Set new function pointers + pStream->StreamRead = (STREAM_READ)PartialStream_Read; + pStream->StreamGetPos = (STREAM_GETPOS)PartialStream_GetPos; + pStream->StreamGetSize = (STREAM_GETSIZE)PartialStream_GetSize; + pStream->StreamGetTime = pStream->BaseGetTime; + pStream->StreamGetTime = pStream->BaseGetTime; + pStream->StreamGetBmp = (STREAM_GETBMP)PartialStream_GetBitmap; + pStream->StreamClose = (STREAM_CLOSE)PartialStream_Close; + return true; + } + + // Free the part map + STORM_FREE(pStream->PartMap); + pStream->PartMap = NULL; + } + } + } + + SetLastError(ERROR_BAD_FORMAT); + return false; +} + +//----------------------------------------------------------------------------- +// Local functions - encrypted stream support + +// Note: Starcraft II - Installer.exe (4.1.1.4219): Suffix derived from battle.net auth. code +// Address of decryption routine: 0053A3D0 http://us.battle.net/static/mediakey/sc2-authenticationcode-enUS.txt +// Pointer to decryptor object: ECX Numbers mean offset of 4-char group of auth code (follows in comment) +// Pointer to key: ECX+0x5C -0C- -1C--08- -18--04- -14--00- -10- +static const char * MpqeKey_Starcraft2_Install_deDE = "expand 32-byte kSSXH00004XFXK4KX00008EKJD3CA0000Y64ZY45M0000YD9V"; // Y45MD3CAK4KXSSXHYD9VY64Z8EKJ4XFX +static const char * MpqeKey_Starcraft2_Install_enGB = "expand 32-byte kANGY000029ZH6NA20000HRGF8UDG0000NY82G8MN00006A3D"; // G8MN8UDG6NA2ANGY6A3DNY82HRGF29ZH +static const char * MpqeKey_Starcraft2_Install_enSG = "expand 32-byte kWW5B0000F7HWFDU90000FWZSHLB20000BLRSW9RR00003ECE"; // W9RRHLB2FDU9WW5B3ECEBLRSFWZSF7HW +static const char * MpqeKey_Starcraft2_Install_enUS = "expand 32-byte kTFD80000ETR5VM5G0000K859RE5N0000WT6F3DH500005LXG"; // 3DH5RE5NVM5GTFD85LXGWT6FK859ETR5 +static const char * MpqeKey_Starcraft2_Install_esES = "expand 32-byte kQU4Y0000XKTQ94PF0000N4R4UAXE0000AZ248WLK0000249P"; // 8WLKUAXE94PFQU4Y249PAZ24N4R4XKTQ +static const char * MpqeKey_Starcraft2_Install_esMX = "expand 32-byte kSQBR00004G54HGGX0000MF9GXX3V0000FFDXA34D0000FE5U"; // A34DXX3VHGGXSQBRFE5UFFDXMF9G4G54 +static const char * MpqeKey_Starcraft2_Install_frFR = "expand 32-byte kFWPQ00006EAJ8HJE0000PFER9K9300008MA2ZG7J0000UA76"; // ZG7J9K938HJEFWPQUA768MA2PFER6EAJ +static const char * MpqeKey_Starcraft2_Install_itIT = "expand 32-byte kXV7E00008BL2TVAP0000GVMWUNNN0000SVBWNE7C00003G2B"; // NE7CUNNNTVAPXV7E3G2BSVBWGVMW8BL2 +static const char * MpqeKey_Starcraft2_Install_koKR = "expand 32-byte kQWK70000838FBM9Q0000WQDB2FTM0000MWAZ3V9E0000U6MA"; // 3V9E2FTMBM9QQWK7U6MAMWAZWQDB838F +static const char * MpqeKey_Starcraft2_Install_plPL = "expand 32-byte k83U6000048L6LULJ00004MQDB8ME0000UP6K2NSF0000YHA3"; // 2NSFB8MELULJ83U6YHA3UP6K4MQD48L6 +static const char * MpqeKey_Starcraft2_Install_ptBR = "expand 32-byte kU8BM0000SW4EZ4CU00005F9CZ9EW0000CTY6QA2T0000B5WX"; // QA2TZ9EWZ4CUU8BMB5WXCTY65F9CSW4E +static const char * MpqeKey_Starcraft2_Install_ruRU = "expand 32-byte k9SH70000YEGT4BAT0000QDK978W60000V9NLVHB30000D68V"; // VHB378W64BAT9SH7D68VV9NLQDK9YEGT +static const char * MpqeKey_Starcraft2_Install_zhTW = "expand 32-byte k7KBN0000D9NEM6GC0000N3PLQJV400003BRDU3NF00009XQJ"; // U3NFQJV4M6GC7KBN9XQJ3BRDN3PLD9NE + +// Note: Diablo III: Agent.exe (1.0.0.954): Suffix derived from battle.net auth. code +// Address of decryption routine: 00502b00 http://dist.blizzard.com/mediakey/d3-authenticationcode-enGB.txt +// Pointer to decryptor object: ECX Numbers mean offset of 4-char group of auth code (follows in comment) +// Pointer to key: ECX+0x5C -0C- -1C--08- -18--04- -14--00- -10- +static const char * MpqeKey_Diablo3_Install_deDE = "expand 32-byte kEFH40000QRZKY3520000XC9MF6EJ0000CFH2UCMX0000XFRX"; // UCMXF6EJY352EFH4XFRXCFH2XC9MQRZK +static const char * MpqeKey_Diablo3_Install_enGB = "expand 32-byte kXP4G0000PHBPRP7W0000J9UNHY4800007SL9MMKV0000HYBQ"; // MMKVHY48RP7WXP4GHYBQ7SL9J9UNPHBP +static const char * MpqeKey_Diablo3_Install_enSG = "expand 32-byte kTZ9M00003CPPVGGL0000JYETWHQ70000FDCL8MXL0000QZQS"; // 8MXLWHQ7VGGLTZ9MQZQSFDCLJYET3CPP +static const char * MpqeKey_Diablo3_Install_enUS = "expand 32-byte kGUNG0000WZSZXFE20000UAKP5TM60000HKQ9EJ2R00005QDG"; // EJ2R5TM6XFE2GUNG5QDGHKQ9UAKPWZSZ +static const char * MpqeKey_Diablo3_Install_esES = "expand 32-byte kK65U0000HQQTZ6LN0000CLP4BE420000WZVMPBGF0000GJQ3"; // PBGFBE42Z6LNK65UGJQ3WZVMCLP4HQQT +static const char * MpqeKey_Diablo3_Install_esMX = "expand 32-byte kW5P200008VU2TSGC0000JPEYJJS90000C47AX7SE00008EBS"; // X7SEJJS9TSGCW5P28EBSC47AJPEY8VU2 +static const char * MpqeKey_Diablo3_Install_frFR = "expand 32-byte kRY3D00007YA2YE6X0000XS4PQA8V0000ZDE45KVB0000LGC5"; // 5KVBQA8VYE6XRY3DLGC5ZDE4XS4P7YA2 +static const char * MpqeKey_Diablo3_Install_itIT = "expand 32-byte kVVY40000B2546EVN00005B8KD2K50000DWYT478J0000XX8T"; // 478JD2K56EVNVVY4XX8TDWYT5B8KB254 +static const char * MpqeKey_Diablo3_Install_koKR = "expand 32-byte k6YWH0000474ARZTN0000NVWDVNFQ0000VDH98TS40000E9CH"; // 8TS4VNFQRZTN6YWHE9CHVDH9NVWD474A +static const char * MpqeKey_Diablo3_Install_plPL = "expand 32-byte k4ZJJ0000BLJBF4LZ0000A6GAZ32D00003AZQLJ520000XVKK"; // LJ52Z32DF4LZ4ZJJXVKK3AZQA6GABLJB +static const char * MpqeKey_Diablo3_Install_ptBR = "expand 32-byte k545Y0000XYAGCUE20000WHE7HY2E0000JPVYK6BD0000KNLB"; // K6BDHY2ECUE2545YKNLBJPVYWHE7XYAG +static const char * MpqeKey_Diablo3_Install_ruRU = "expand 32-byte kXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // +static const char * MpqeKey_Diablo3_Install_zhTW = "expand 32-byte kMRUC0000AA8HV3ZZ0000UX2TQTN80000A8CG6VWC0000ZXV8"; // 6VWCQTN8V3ZZMRUCZXV8A8CGUX2TAA8H +static const char * MpqeKey_Diablo3_Install_zhCN = "expand 32-byte kXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // + static const char * MpqKeyArray[] = { - MpqeKey_Starcraft2_Install_enUS, - MpqeKey_Starcraft2_Install_enGB, MpqeKey_Starcraft2_Install_deDE, + MpqeKey_Starcraft2_Install_enGB, + MpqeKey_Starcraft2_Install_enSG, + MpqeKey_Starcraft2_Install_enUS, MpqeKey_Starcraft2_Install_esES, + MpqeKey_Starcraft2_Install_esMX, MpqeKey_Starcraft2_Install_frFR, MpqeKey_Starcraft2_Install_itIT, + MpqeKey_Starcraft2_Install_koKR, MpqeKey_Starcraft2_Install_plPL, + MpqeKey_Starcraft2_Install_ptBR, MpqeKey_Starcraft2_Install_ruRU, + MpqeKey_Starcraft2_Install_zhTW, + + MpqeKey_Diablo3_Install_deDE, + MpqeKey_Diablo3_Install_enGB, + MpqeKey_Diablo3_Install_enSG, + MpqeKey_Diablo3_Install_enUS, + MpqeKey_Diablo3_Install_esES, + MpqeKey_Diablo3_Install_esMX, + MpqeKey_Diablo3_Install_frFR, + MpqeKey_Diablo3_Install_itIT, + MpqeKey_Diablo3_Install_koKR, + MpqeKey_Diablo3_Install_plPL, + MpqeKey_Diablo3_Install_ptBR, +// MpqeKey_Diablo3_Install_ruRU, + MpqeKey_Diablo3_Install_zhTW, +// MpqeKey_Diablo3_Install_zhCN, + NULL }; @@ -1026,40 +1581,35 @@ static void DecryptFileChunk( } } - -static bool DetectFileKey(TEncryptedStream * pStream) +static const char * DetectFileKey(LPBYTE pbEncryptedHeader) { ULONGLONG ByteOffset = 0; - BYTE EncryptedHeader[MPQE_CHUNK_SIZE]; BYTE FileHeader[MPQE_CHUNK_SIZE]; - - // Load the chunk from the file - if(!FileStream_Read(pStream, &ByteOffset, EncryptedHeader, sizeof(EncryptedHeader))) - return false; + BYTE Key[MPQE_CHUNK_SIZE]; // We just try all known keys one by one for(int i = 0; MpqKeyArray[i] != NULL; i++) { // Copy the key there - memcpy(pStream->Key, MpqKeyArray[i], MPQE_CHUNK_SIZE); - BSWAP_ARRAY32_UNSIGNED(pStream->Key, MPQE_CHUNK_SIZE); + memcpy(Key, MpqKeyArray[i], MPQE_CHUNK_SIZE); + BSWAP_ARRAY32_UNSIGNED(Key, MPQE_CHUNK_SIZE); // Try to decrypt with the given key - memcpy(FileHeader, EncryptedHeader, MPQE_CHUNK_SIZE); - DecryptFileChunk((LPDWORD)FileHeader, pStream->Key, ByteOffset, MPQE_CHUNK_SIZE); + memcpy(FileHeader, pbEncryptedHeader, MPQE_CHUNK_SIZE); + DecryptFileChunk((LPDWORD)FileHeader, Key, ByteOffset, MPQE_CHUNK_SIZE); - // We check the decrypoted data + // We check the decrypted data // All known encrypted MPQs have header at the begin of the file, // so we check for MPQ signature there. if(FileHeader[0] == 'M' && FileHeader[1] == 'P' && FileHeader[2] == 'Q') - return true; + return MpqKeyArray[i]; } // Key not found, sorry - return false; + return NULL; } -static bool EncryptedFile_Read( +static bool EncryptedStream_Read( TEncryptedStream * pStream, // Pointer to an open stream ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position void * pvBuffer, // Pointer to data to be read @@ -1075,10 +1625,10 @@ static bool EncryptedFile_Read( bool bResult = false; // Get the byte offset - if(pByteOffset != NULL) - ByteOffset = *pByteOffset; + if(pByteOffset == NULL) + pStream->BaseGetPos(pStream, ByteOffset); else - ByteOffset = pStream->RawFilePos; + ByteOffset = *pByteOffset; // Cut it down to MPQE chunk size StartOffset = ByteOffset; @@ -1097,7 +1647,7 @@ static bool EncryptedFile_Read( dwOffsetInCache = (DWORD)(ByteOffset - StartOffset); // Read the file from the stream as-is - if(File_Read(pStream, &StartOffset, pbMpqData, dwBytesToDecrypt)) + if(pStream->BaseRead(pStream, &StartOffset, pbMpqData, dwBytesToDecrypt)) { // Decrypt the data DecryptFileChunk((LPDWORD)pbMpqData, pStream->Key, StartOffset, dwBytesToAllocate); @@ -1119,31 +1669,42 @@ static bool EncryptedFile_Read( return bResult; } -static bool EncryptedFile_Write( - TEncryptedStream * pStream, // Pointer to an open stream - ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position - const void * pvBuffer, // Pointer to data to be read - DWORD dwBytesToRead) // Number of bytes to read from the file +static bool EncryptedStream_Open(TEncryptedStream * pStream) { - // Keep compiler happy - dwBytesToRead = dwBytesToRead; - pByteOffset = pByteOffset; - pvBuffer = pvBuffer; - pStream = pStream; + ULONGLONG ByteOffset = 0; + BYTE EncryptedHeader[MPQE_CHUNK_SIZE]; + const char * szKey; - // Not allowed - return false; -} + // Sanity check + assert(pStream->BaseRead != NULL); -static bool EncryptedFile_SetSize( - TEncryptedStream * pStream, // Pointer to an open stream - ULONGLONG NewSize) // new size of the file -{ - // Keep compiler happy - pStream = pStream; - NewSize = NewSize; + // Load one MPQE chunk and try to detect the file key + if(pStream->BaseRead(pStream, &ByteOffset, EncryptedHeader, sizeof(EncryptedHeader))) + { + // Attempt to decrypt the MPQ header with all known keys + szKey = DetectFileKey(EncryptedHeader); + if(szKey != NULL) + { + // Copy the key for the file + memcpy(pStream->Key, szKey, MPQE_CHUNK_SIZE); + BSWAP_ARRAY32_UNSIGNED(pStream->Key, MPQE_CHUNK_SIZE); + + // Assign functions + pStream->StreamRead = (STREAM_READ)EncryptedStream_Read; + pStream->StreamGetPos = pStream->BaseGetPos; + pStream->StreamGetSize = pStream->BaseGetSize; + pStream->StreamGetTime = pStream->BaseGetTime; + pStream->StreamGetBmp = (STREAM_GETBMP)Dummy_GetBitmap; + pStream->StreamClose = pStream->BaseClose; + + // We need to reset the position back to the begin of the file + pStream->BaseRead(pStream, &ByteOffset, EncryptedHeader, 0); + return true; + } - // Not allowed + // An unknown key + SetLastError(ERROR_UNKNOWN_FILE_KEY); + } return false; } @@ -1151,7 +1712,7 @@ static bool EncryptedFile_SetSize( // Public functions /** - * This function creates a new file for read or read-write access + * This function creates a new file for read-write access * * - If the current platform supports file sharing, * the file must be created for read sharing (i.e. another application @@ -1168,35 +1729,45 @@ static bool EncryptedFile_SetSize( */ TFileStream * FileStream_CreateFile( - const TCHAR * szFileName) // Name of the file to create + const TCHAR * szFileName, + DWORD dwStreamFlags) { - TFileStream * pStream = NULL; - HANDLE hFile; + TFileStream * pStream; - // Create the file - hFile = CreateNewFile(szFileName); - if(hFile != INVALID_HANDLE_VALUE) + // We only support creation of linear, local file + if((dwStreamFlags & (STREAM_PROVIDER_MASK | BASE_PROVIDER_MASK)) != (STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE)) { - // Allocate the FileStream structure and fill it - pStream = STORM_ALLOC(TFileStream, 1); - if(pStream != NULL) - { - // Reset entire structure to zero - memset(pStream, 0, sizeof(TFileStream)); - - // Save file name and set function pointers - _tcscpy(pStream->szFileName, szFileName); - pStream->StreamGetPos = File_GetPos; - pStream->StreamRead = File_Read; - pStream->StreamWrite = File_Write; - pStream->StreamGetSize = File_GetSize; - pStream->StreamSetSize = File_SetSize; - pStream->hFile = hFile; - } - else + SetLastError(ERROR_NOT_SUPPORTED); + return NULL; + } + + // Allocate file stream structure for linear stream + pStream = STORM_ALLOC(TFileStream, 1); + if(pStream != NULL) + { + // Reset entire structure to zero + memset(pStream, 0, sizeof(TFileStream)); + _tcscpy(pStream->szFileName, szFileName); + + // Attempt to create the disk file + if(BaseFile_Create(pStream, szFileName, dwStreamFlags)) { - CloseTheFile(hFile); + // Fill the stream provider functions + pStream->StreamRead = pStream->BaseRead; + pStream->StreamWrite = pStream->BaseWrite; + pStream->StreamGetPos = pStream->BaseGetPos; + pStream->StreamGetSize = pStream->BaseGetSize; + pStream->StreamSetSize = pStream->BaseSetSize; + pStream->StreamGetTime = pStream->BaseGetTime; + pStream->StreamGetBmp = (STREAM_GETBMP)Dummy_GetBitmap;; + pStream->StreamSwitch = (STREAM_SWITCH)LinearStream_Switch; + pStream->StreamClose = pStream->BaseClose; + return pStream; } + + // File create failed, delete the stream + STORM_FREE(pStream); + pStream = NULL; } // Return the stream @@ -1212,185 +1783,106 @@ TFileStream * FileStream_CreateFile( * - If the file exists but cannot be open, then function must return NULL * - The parameters of the function must be validate by the caller * - The function must check if the file is a PART file, - * and create TPartFileStream object if so. + * and create TPartialStream object if so. * - The function must initialize all stream function pointers in TFileStream * - If the function fails from any reason, it must close all handles * and free all memory that has been allocated in the process of stream creation, * including the TFileStream structure itself * * \a szFileName Name of the file to open - * \a bWriteAccess false for read only, true for read+write + * \a dwStreamFlags specifies the provider and base storage type */ -TFileStream * FileStream_OpenRawFile( - const TCHAR * szFileName, // Name of the file to create - bool bWriteAccess) // false = read-only, true = read+write +TFileStream * FileStream_OpenFile( + const TCHAR * szFileName, + DWORD dwStreamFlags) { - TFileStream * pStream; - HANDLE hFile; - - // Create the file - hFile = OpenExistingFile(szFileName, bWriteAccess); - if(hFile == INVALID_HANDLE_VALUE) - return NULL; + TFileStream * pStream = NULL; + size_t StreamSize = 0; + bool bStreamResult = false; + bool bBaseResult = false; - // Initialize the file as normal file stream - pStream = STORM_ALLOC(TFileStream, 1); - if(pStream != NULL) + // Allocate file stream for each stream provider + switch(dwStreamFlags & STREAM_PROVIDER_MASK) { - // Reset entire structure to zero - memset(pStream, 0, sizeof(TFileStream)); - - // Save file name and set function pointers - _tcscpy(pStream->szFileName, szFileName); - pStream->StreamGetPos = File_GetPos; - pStream->StreamRead = File_Read; - pStream->StreamWrite = File_Write; - pStream->StreamGetSize = File_GetSize; - pStream->StreamSetSize = File_SetSize; - if(bWriteAccess == false) - pStream->StreamFlags |= STREAM_FLAG_READ_ONLY; - pStream->hFile = hFile; - return pStream; - } + case STREAM_PROVIDER_LINEAR: // Allocate structure for linear stream + StreamSize = sizeof(TLinearStream); + break; - CloseTheFile(hFile); - return NULL; -} + case STREAM_PROVIDER_PARTIAL: + dwStreamFlags |= STREAM_FLAG_READ_ONLY; + StreamSize = sizeof(TPartialStream); + break; -/** - * Opens a file - * - * \a szFileName Name of the file to open - * \a bWriteAccess false for read only, true for read+write - */ + case STREAM_PROVIDER_ENCRYPTED: + dwStreamFlags |= STREAM_FLAG_READ_ONLY; + StreamSize = sizeof(TEncryptedStream); + break; -TFileStream * FileStream_OpenFile(const TCHAR * szFileName, bool bWriteAccess) -{ - PART_FILE_HEADER PartHdr; - ULONGLONG VirtualSize; // Size of the file stored in part file - ULONGLONG ByteOffset = {0}; - TFileStream * pStream; - size_t nStructLength; - DWORD BlockCount; + default: + return NULL; + } - // Open the file as normal stream - pStream = FileStream_OpenRawFile(szFileName, bWriteAccess); + // Allocate the stream for each type + pStream = (TFileStream *)STORM_ALLOC(BYTE, StreamSize); if(pStream == NULL) return NULL; - // Attempt to read PART file header - if(FileStream_Read(pStream, &ByteOffset, &PartHdr, sizeof(PART_FILE_HEADER))) - { - // We need to swap PART file header on big-endian platforms - BSWAP_PART_HEADER(&PartHdr); - - // Verify the PART file header - if(IsPartHeader(&PartHdr)) - { - TPartFileStream * pPartStream; + // Fill the stream structure with zeros + memset(pStream, 0, StreamSize); + _tcscpy(pStream->szFileName, szFileName); - // Calculate the number of parts in the file - VirtualSize = MAKE_OFFSET64(PartHdr.FileSizeHi, PartHdr.FileSizeLo); - BlockCount = (DWORD)((VirtualSize + PartHdr.BlockSize - 1) / PartHdr.BlockSize); + // Now initialize the respective base provider + switch(dwStreamFlags & BASE_PROVIDER_MASK) + { + case BASE_PROVIDER_FILE: + bBaseResult = BaseFile_Open(pStream, szFileName, dwStreamFlags); + break; - // Calculate the size of the entire structure - // Note that we decrement number of parts by one, - // because there already is one entry in the TPartFileStream structure - nStructLength = sizeof(TPartFileStream) + (BlockCount - 1) * sizeof(PART_FILE_MAP_ENTRY); - pPartStream = (TPartFileStream *)STORM_ALLOC(char, nStructLength); - if(pPartStream != NULL) - { - // Initialize the part file stream - memset(pPartStream, 0, nStructLength); - memcpy(pPartStream, pStream, sizeof(TFileStream)); + case BASE_PROVIDER_MAP: + dwStreamFlags |= STREAM_FLAG_READ_ONLY; + bBaseResult = BaseMap_Open(pStream, szFileName, dwStreamFlags); + break; - // Load the block map - if(!FileStream_Read(pPartStream, NULL, pPartStream->PartMap, BlockCount * sizeof(PART_FILE_MAP_ENTRY))) - { - FileStream_Close(pStream); - STORM_FREE(pPartStream); - return NULL; - } + case BASE_PROVIDER_HTTP: + dwStreamFlags |= STREAM_FLAG_READ_ONLY; + bBaseResult = BaseHttp_Open(pStream, szFileName, dwStreamFlags); + break; + } - // Swap the array of file map entries - BSWAP_ARRAY32_UNSIGNED(pPartStream->PartMap, BlockCount * sizeof(PART_FILE_MAP_ENTRY)); + // If we failed to open the base storage, fail the operation + if(bBaseResult == false) + { + STORM_FREE(pStream); + return NULL; + } - // Set new function pointers - pPartStream->StreamGetPos = (STREAM_GETPOS)PartFile_GetPos; - pPartStream->StreamRead = (STREAM_READ)PartFile_Read; - pPartStream->StreamWrite = (STREAM_WRITE)PartFile_Write; - pPartStream->StreamGetSize = (STREAM_GETSIZE)PartFile_GetSize; - pPartStream->StreamSetSize = (STREAM_SETSIZE)PartFile_SetSize; - pPartStream->StreamFlags |= (STREAM_FLAG_READ_ONLY | STREAM_FLAG_PART_FILE); + // Now initialize the stream provider + switch(dwStreamFlags & STREAM_PROVIDER_MASK) + { + case STREAM_PROVIDER_LINEAR: + bStreamResult = LinearStream_Open((TLinearStream *)pStream); + break; - // Fill the members of PART file stream - pPartStream->VirtualSize = ((ULONGLONG)PartHdr.FileSizeHi) + PartHdr.FileSizeLo; - pPartStream->VirtualPos = 0; - pPartStream->BlockCount = BlockCount; - pPartStream->BlockSize = PartHdr.BlockSize; + case STREAM_PROVIDER_PARTIAL: + bStreamResult = PartialStream_Open((TPartialStream *)pStream); + break; - STORM_FREE(pStream); - } - return pPartStream; - } + case STREAM_PROVIDER_ENCRYPTED: + bStreamResult = EncryptedStream_Open((TEncryptedStream *)pStream); + break; } - // If the file doesn't contain PART file header, - // reset the file position to begin of the file - FileStream_Read(pStream, &ByteOffset, NULL, 0); - return pStream; -} - -TFileStream * FileStream_OpenEncrypted(const TCHAR * szFileName) -{ - TEncryptedStream * pEncryptedStream; - TFileStream * pStream; - - // Open the file as raw stream - pStream = FileStream_OpenRawFile(szFileName, false); - if(pStream) + // If the operation failed, free the stream and set it to NULL + if(bStreamResult == false) { - // Allocate new stream for handling encryption - pEncryptedStream = STORM_ALLOC(TEncryptedStream, 1); - if(pEncryptedStream != NULL) - { - // Copy the file stream to the encrypted stream - memset(pEncryptedStream, 0, sizeof(TEncryptedStream)); - memcpy(pEncryptedStream, pStream, sizeof(TFileStream)); - - // Assign functions - pEncryptedStream->StreamRead = (STREAM_READ)EncryptedFile_Read; - pEncryptedStream->StreamWrite = (STREAM_WRITE)EncryptedFile_Write; - pEncryptedStream->StreamSetSize = (STREAM_SETSIZE)EncryptedFile_SetSize; - pEncryptedStream->StreamFlags |= (STREAM_FLAG_READ_ONLY | STREAM_FLAG_ENCRYPTED_FILE); - - // Get the file key - if(DetectFileKey(pEncryptedStream)) - return pEncryptedStream; - - // Close the encrypted stream - STORM_FREE(pEncryptedStream); - pEncryptedStream = NULL; - } - - FileStream_Close(pStream); + // Only close the base stream + pStream->BaseClose(pStream); + STORM_FREE(pStream); pStream = NULL; } - SetLastError(ERROR_UNKNOWN_FILE_KEY); - return NULL; -} - -/** - * This function returns the current file position - * \a pStream - * \a ByteOffset - */ -bool FileStream_GetPos(TFileStream * pStream, ULONGLONG & ByteOffset) -{ - assert(pStream->StreamGetPos != NULL); - return pStream->StreamGetPos(pStream, ByteOffset); + return pStream; } /** @@ -1432,67 +1924,22 @@ bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBu */ bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite) { - if(pStream->StreamFlags & STREAM_FLAG_READ_ONLY) + if(pStream->dwFlags & STREAM_FLAG_READ_ONLY) return false; - assert(pStream->StreamWrite != NULL); + assert(pStream->StreamWrite != NULL); return pStream->StreamWrite(pStream, pByteOffset, pvBuffer, dwBytesToWrite); } - /** - * Returns the last write time of a file - * - * \a pStream Pointer to an open stream - * \a pFileType Pointer where to store the file last write time + * This function returns the current file position + * \a pStream + * \a ByteOffset */ -bool FileStream_GetLastWriteTime(TFileStream * pStream, ULONGLONG * pFileTime) +bool FileStream_GetPos(TFileStream * pStream, ULONGLONG & ByteOffset) { -#ifdef PLATFORM_WINDOWS - FILETIME ft; - - if(!GetFileTime(pStream->hFile, NULL, NULL, &ft)) - return false; - - *pFileTime = MAKE_OFFSET64(ft.dwHighDateTime, ft.dwLowDateTime); - return true; -#endif - -#ifdef PLATFORM_MAC - OSErr theErr; - FSRef theFileRef; - FSCatalogInfo theCatInfo; - - theErr = FSGetForkCBInfo((short)(long)pStream->hFile, 0, NULL, NULL, NULL, &theFileRef, NULL); - if(theErr != noErr) - { - nLastError = theErr; - return false; - } - - theErr = FSGetCatalogInfo(&theFileRef, kFSCatInfoContentMod, &theCatInfo, NULL, NULL, NULL); - if(theErr != noErr) - { - nLastError = theErr; - return false; - } - - ConvertUTCDateTimeToFileTime(&theCatInfo.contentModDate, pFileTime); - return true; -#endif - -#ifdef PLATFORM_LINUX - struct stat file_stats; - - if(fstat((int)(size_t)pStream->hFile, &file_stats) == -1) - { - nLastError = errno; - return false; - } - - ConvertTimeTToFileTime(pFileTime, file_stats.st_mtime); - return true; -#endif + assert(pStream->StreamGetPos != NULL); + return pStream->StreamGetPos(pStream, ByteOffset); } /** @@ -1515,14 +1962,26 @@ bool FileStream_GetSize(TFileStream * pStream, ULONGLONG & FileSize) */ bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize) { - if(pStream->StreamFlags & STREAM_FLAG_READ_ONLY) + if(pStream->dwFlags & STREAM_FLAG_READ_ONLY) return false; - assert(pStream->StreamSetSize != NULL); + assert(pStream->StreamSetSize != NULL); return pStream->StreamSetSize(pStream, NewFileSize); } /** + * Returns the last write time of a file + * + * \a pStream Pointer to an open stream + * \a pFileType Pointer where to store the file last write time + */ +bool FileStream_GetTime(TFileStream * pStream, ULONGLONG * pFileTime) +{ + assert(pStream->StreamGetTime != NULL); + return pStream->StreamGetTime(pStream, pFileTime); +} + +/** * Switches a stream with another. Used for final phase of archive compacting. * Performs these steps: * @@ -1533,37 +1992,86 @@ bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize) * \a pStream Pointer to an open stream * \a pTempStream Temporary ("working") stream (created during archive compacting) */ -bool FileStream_MoveFile(TFileStream * pStream, TFileStream * pTempStream) +bool FileStream_Switch(TFileStream * pStream, TFileStream * pNewStream) +{ + if(pStream->dwFlags & STREAM_FLAG_READ_ONLY) + return false; + + assert(pStream->StreamSwitch != NULL); + return pStream->StreamSwitch(pStream, pNewStream); +} + +/** + * Returns the file name of the stream + * + * \a pStream Pointer to an open stream + */ +TCHAR * FileStream_GetFileName(TFileStream * pStream) { - bool bWriteAccess; + assert(pStream != NULL); + return pStream->szFileName; +} - // Close the handle to the temporary file - CloseTheFile(pTempStream->hFile); - pTempStream->hFile = INVALID_HANDLE_VALUE; +/** + * Returns true if the stream is read-only + * + * \a pStream Pointer to an open stream + */ +bool FileStream_IsReadOnly(TFileStream * pStream) +{ + return (pStream->dwFlags & STREAM_FLAG_READ_ONLY) ? true : false; +} + +/** + * This function enabled a linear stream to include data bitmap. + * Used by MPQs v 4.0 from WoW. Each file block is represented by + * a bit in the bitmap. 1 means the block is present, 0 means it's not. + * + * \a pStream Pointer to an open stream + * \a pBitmap Pointer to file bitmap + */ - // Close the handle to the source file - CloseTheFile(pStream->hFile); - pStream->hFile = INVALID_HANDLE_VALUE; +bool FileStream_SetBitmap(TFileStream * pStream, TFileBitmap * pBitmap) +{ + TLinearStream * pLinearStream; - // Rename the temp file to the final file - if(!RenameFile(pTempStream->szFileName, pStream->szFileName)) + // It must be a linear stream. + if((pStream->dwFlags & STREAM_PROVIDER_MASK) != STREAM_PROVIDER_LINEAR) return false; + pLinearStream = (TLinearStream *)pStream; - // Now open the renamed file again, and store its handle to the old stream - bWriteAccess = (pStream->StreamFlags & STREAM_FLAG_READ_ONLY) ? false : true; - pStream->hFile = OpenExistingFile(pStream->szFileName, bWriteAccess); - if(pStream->hFile == INVALID_HANDLE_VALUE) + // Two bitmaps are not allowed + if(pLinearStream->pBitmap != NULL) return false; - // Delete the temporary file stream - FileStream_Close(pTempStream); + // We need to change some entry points + pLinearStream->StreamRead = (STREAM_READ)LinearStream_Read; + pLinearStream->StreamGetBmp = (STREAM_GETBMP)LinearStream_GetBitmap; - // The file position has been reset to zero by reopening the file - pStream->RawFilePos = 0; + // Using data bitmap renders the stream to be read only. + pLinearStream->dwFlags |= STREAM_FLAG_READ_ONLY; + pLinearStream->pBitmap = pBitmap; return true; } /** + * This function retrieves the file bitmap. A file bitmap is an array + * of bits, each bit representing one file block. A value of 1 means + * that the block is present in the file, a value of 0 means that the + * block is not present. + * + * \a pStream Pointer to an open stream + * \a pBitmap Pointer to buffer where to store the file bitmap + * \a Length Size of buffer pointed by pBitmap, in bytes + * \a LengthNeeded If non-NULL, the function supplies the necessary byte size of the buffer + */ +bool FileStream_GetBitmap(TFileStream * pStream, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded) +{ + assert(pStream->StreamGetBmp != NULL); + return pStream->StreamGetBmp(pStream, pBitmap, Length, LengthNeeded); +} + +/** * This function closes an archive file and frees any data buffers * that have been allocated for stream management. The function must also * support partially allocated structure, i.e. one or more buffers @@ -1576,9 +2084,10 @@ void FileStream_Close(TFileStream * pStream) // Check if the stream structure is allocated at all if(pStream != NULL) { - // Close the file handle - if(pStream->hFile != INVALID_HANDLE_VALUE) - CloseTheFile(pStream->hFile); + // Close the stream provider. + // This will also close the base stream + assert(pStream->StreamClose != NULL); + pStream->StreamClose(pStream); // Free the stream itself STORM_FREE(pStream); @@ -1587,275 +2096,199 @@ void FileStream_Close(TFileStream * pStream) //----------------------------------------------------------------------------- // main - for testing purposes -/* -int main(void) + +#ifdef __STORMLIB_TEST__ +int FileStream_Test(const TCHAR * szFileName, DWORD dwStreamFlags) { - ULONGLONG FilePos; - ULONGLONG FileSize; - TMPQFileTime * pFT; - TFileStream * pTempStream; TFileStream * pStream; + TMPQHeader MpqHeader; + ULONGLONG FilePos; TMPQBlock * pBlock; TMPQHash * pHash; - TMPQHeader2 MpqHeader; - char szString1[100] = "This is a single line\n\r"; - char szString2[100]; - char Buffer[0x80]; - DWORD dwLength = strlen(szString1); - // - // Test 1: Write to a stream - // + InitializeMpqCryptography(); - pStream = FileStream_CreateFile("E:\\Stream.bin"); + pStream = FileStream_OpenFile(szFileName, dwStreamFlags); if(pStream == NULL) + return GetLastError(); + + // Read the MPQ header + FileStream_Read(pStream, NULL, &MpqHeader, MPQ_HEADER_SIZE_V2); + if(MpqHeader.dwID != ID_MPQ) + return ERROR_FILE_CORRUPT; + + // Read the hash table + pHash = STORM_ALLOC(TMPQHash, MpqHeader.dwHashTableSize); + if(pHash != NULL) { - printf("Failed to create new file\n"); - return -1; + FilePos = MpqHeader.dwHashTablePos; + FileStream_Read(pStream, &FilePos, pHash, MpqHeader.dwHashTableSize * sizeof(TMPQHash)); + DecryptMpqBlock(pHash, MpqHeader.dwHashTableSize * sizeof(TMPQHash), MPQ_KEY_HASH_TABLE); + STORM_FREE(pHash); } - for(int i = 0; i < 10; i++) + // Read the block table + pBlock = STORM_ALLOC(TMPQBlock, MpqHeader.dwBlockTableSize); + if(pBlock != NULL) { - if(!FileStream_Write(pStream, NULL, szString1, dwLength)) - { - printf("Failed to write to the stream\n"); - return -1; - } + FilePos = MpqHeader.dwBlockTablePos; + FileStream_Read(pStream, &FilePos, pBlock, MpqHeader.dwBlockTableSize * sizeof(TMPQBlock)); + DecryptMpqBlock(pBlock, MpqHeader.dwBlockTableSize * sizeof(TMPQBlock), MPQ_KEY_BLOCK_TABLE); + STORM_FREE(pBlock); } + FileStream_Close(pStream); + return ERROR_SUCCESS; +} +#endif + +/* +int FileStream_Test() +{ + TFileStream * pStream; + + InitializeMpqCryptography(); // - // Test2: Read from the stream + // Test 1: Write to a stream // - pStream = FileStream_OpenFile("E:\\Stream.bin", false); - if(pStream == NULL) + pStream = FileStream_CreateFile("E:\\Stream.bin", 0); + if(pStream != NULL) { - printf("Failed to open existing file\n"); - return -1; - } + char szString1[100] = "This is a single line\n\r"; + DWORD dwLength = strlen(szString1); - // This call must end with an error - if(FileStream_Write(pStream, NULL, "aaa", 3)) - { - printf("Write succeeded while it should fail\n"); - return -1; + for(int i = 0; i < 10; i++) + { + if(!FileStream_Write(pStream, NULL, szString1, dwLength)) + { + printf("Failed to write to the stream\n"); + return ERROR_CAN_NOT_COMPLETE; + } + } + FileStream_Close(pStream); } - for(int i = 0; i < 10; i++) + // + // Test2: Read from the stream + // + + pStream = FileStream_OpenFile("E:\\Stream.bin", STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); + if(pStream != NULL) { - if(!FileStream_Read(pStream, NULL, szString2, dwLength)) + char szString1[100] = "This is a single line\n\r"; + char szString2[100]; + DWORD dwLength = strlen(szString1); + + // This call must end with an error + if(FileStream_Write(pStream, NULL, "aaa", 3)) { - printf("Failed to read from the stream\n"); + printf("Write succeeded while it should fail\n"); return -1; } - szString2[dwLength] = 0; - if(strcmp(szString1, szString2)) + for(int i = 0; i < 10; i++) { - printf("Data read from file are different from data written\n"); - return -1; + if(!FileStream_Read(pStream, NULL, szString2, dwLength)) + { + printf("Failed to read from the stream\n"); + return -1; + } + + szString2[dwLength] = 0; + if(strcmp(szString1, szString2)) + { + printf("Data read from file are different from data written\n"); + return -1; + } } + FileStream_Close(pStream); } - FileStream_Close(pStream); // // Test3: Open the temp stream, write some data and switch it to the original stream // - pStream = FileStream_OpenFile("E:\\Stream.bin", false); - if(pStream == NULL) - { - printf("Failed to open existing file\n"); - return -1; - } - - pTempStream = FileStream_CreateFile("E:\\TempStream.bin"); - if(pTempStream == NULL) - { - printf("Failed to create temp stream\n"); - return -1; - } - - // Copy the original stream to the temp - if(!FileStream_GetSize(pStream, &FileSize)) - { - printf("Failed to get the file size\n"); - return -1; - } - - while(FileSize.QuadPart != 0) + pStream = FileStream_OpenFile("E:\\Stream.bin", STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); + if(pStream != NULL) { - DWORD dwBytesToRead = FileSize.LowPart; + TFileStream * pTempStream; + ULONGLONG FileSize; - if(dwBytesToRead > sizeof(Buffer)) - dwBytesToRead = sizeof(Buffer); - - if(!FileStream_Read(pStream, NULL, Buffer, dwBytesToRead)) + pTempStream = FileStream_CreateFile("E:\\TempStream.bin", 0); + if(pTempStream == NULL) { - printf("CopyStream: Read source file failed\n"); + printf("Failed to create temp stream\n"); return -1; } - if(!FileStream_Write(pTempStream, NULL, Buffer, dwBytesToRead)) + // Copy the original stream to the temp + if(!FileStream_GetSize(pStream, FileSize)) { - printf("CopyStream: Write target file failed\n"); + printf("Failed to get the file size\n"); return -1; } - FileSize.QuadPart -= dwBytesToRead; - } + while(FileSize != 0) + { + DWORD dwBytesToRead = (DWORD)FileSize; + char Buffer[0x80]; - // Switch the streams - // Note that the pTempStream is closed by the operation - FileStream_MoveFile(pStream, pTempStream); - FileStream_Close(pStream); + if(dwBytesToRead > sizeof(Buffer)) + dwBytesToRead = sizeof(Buffer); - // - // Test4: Read from the stream again - // + if(!FileStream_Read(pStream, NULL, Buffer, dwBytesToRead)) + { + printf("CopyStream: Read source file failed\n"); + return -1; + } - pStream = FileStream_OpenFile("E:\\Stream.bin", false); - if(pStream == NULL) - { - printf("Failed to open existing file\n"); - return -1; - } + if(!FileStream_Write(pTempStream, NULL, Buffer, dwBytesToRead)) + { + printf("CopyStream: Write target file failed\n"); + return -1; + } - for(int i = 0; i < 10; i++) - { - if(!FileStream_Read(pStream, NULL, szString2, dwLength)) - { - printf("Failed to read from the stream\n"); - return -1; + FileSize -= dwBytesToRead; } - szString2[dwLength] = 0; - if(strcmp(szString1, szString2)) - { - printf("Data read from file are different from data written\n"); - return -1; - } + // Switch the streams + // Note that the pTempStream is closed by the operation + FileStream_Switch(pStream, pTempStream); + FileStream_Close(pStream); } - FileStream_Close(pStream); // - // Test5: Open partial MPQ stream + // Test4: Read from the stream again // -// InitializeMpqCryptography(); - pStream = FileStream_OpenFile("e:\\Multimedia\\MPQs\\PartialMPQs\\patch.MPQ.part", false); + pStream = FileStream_OpenFile("E:\\Stream.bin", STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); if(pStream != NULL) { - // Read the MPQ header - FileStream_Read(pStream, NULL, &MpqHeader, MPQ_HEADER_SIZE_V2); - - // Read the hash table - pHash = STORM_ALLOC(TMPQHash, MpqHeader.dwHashTableSize); - FilePos.HighPart = 0; - FilePos.LowPart = MpqHeader.dwHashTablePos; - FileStream_Read(pStream, &FilePos, pHash, MpqHeader.dwHashTableSize * sizeof(TMPQHash)); - - // - // At this point, the encrypted hash table should be like this: - // - // 416c7175 5ddfb61b 84bb75c8 c0399515 - // a9793eca 9ec773d7 ed8a54d6 74fb2adf - // 6acd4ae5 b13816b5 ffad2341 2f2b2a54 - // 614339c7 5fd0adf0 62434e91 d62439e3 - // 8f317aa5 f12706d6 bd83d2ca 97d7f108 - // 7586d373 51d85b05 8540beca f37ef3d7 - // d931d4d6 d592aadf 9044e960 c4592e92 - // 47dc03f7 0982dea4 afb31943 7c3c7cec - // 0c28fd0d bcbfb7df 4d13b6e4 b5b0ef31 - // e1a33b70 ec30e4b9 7aaa5e7a fb6d46ec - // 61732791 55fe757e 8ba18b5d d5f93246 - // 6d275f38 a89b5781 c34189a9 654c6472 - // 07e1d4e1 814bc8ee c72d2730 815afd43 - // 40bd2a92 640a9391 d868f813 0f61b73d - // 6d202746 2c5124ca 65db3ad0 5b1c3e39 - // b731013c 73776405 eac0c746 6e50c938 - // a4a7fd00 56db3805 6d6dbab7 44fed28a - // 2383394b bf617bdd a3edfaa2 e7d3aaaf - // - - // Decrypt the hash table -// DecryptMpqBlock(pHash, MpqHeader.dwHashTableSize * sizeof(TMPQHash), MPQ_KEY_HASH_TABLE); - - // - // At this point, the hash table should be like this: - // - // c750beb9 72c2538a 00000000 00000466 - // ffffffff ffffffff ffffffff ffffffff - // 898fdc7a 18963b5d 00000000 000005e1 - // ffffffff ffffffff ffffffff ffffffff - // e3c6fc32 d8afff2b 00000000 000001ea - // ffffffff ffffffff ffffffff ffffffff - // ffffffff ffffffff ffffffff ffffffff - // ffffffff ffffffff ffffffff ffffffff - // ffffffff ffffffff ffffffff ffffffff - // ffffffff ffffffff ffffffff ffffffff - // ffffffff ffffffff ffffffff ffffffff - // 0fa4fd60 3fbe8626 00000000 0000076f - // 9ee5bccf 031b277b 00000000 0000095c - // f4e154c5 0aadd1c1 00000000 00000876 - // 9e1ce9e7 e12d575d 00000000 0000071d - // - - // Read the block table - pBlock = STORM_ALLOC(TMPQBlock, MpqHeader.dwBlockTableSize); - FilePos.HighPart = 0; - FilePos.LowPart = MpqHeader.dwBlockTablePos; - FileStream_Read(pStream, &FilePos, pBlock, MpqHeader.dwBlockTableSize * sizeof(TMPQBlock)); + char szString1[100] = "This is a single line\n\r"; + char szString2[100]; + DWORD dwLength = strlen(szString1); - // - // At this point, the encrypted block table should be like this: - // - // 3d4867a7 ca0f533e f82c54d6 ed3c9dec - // d8d607dc d9ad13ab f4588b46 8d058704 - // e8084fc8 63bc8064 b058c777 3683e9e3 - // 6c0da998 7703be0d 91ce3607 c14e29b9 - // 481b5c0d 42d902d2 8302acb7 e8f3e715 - // c9cdfc91 7cc38c15 ea3dfd22 ad20c856 - // b6450c7f 08522866 4cedb064 e03e3a86 - // 4509c7cc ddffbfc3 82fc8c66 e82a4424 - // afc4a982 23169037 5af6a3e2 34e1d24e - // 362c9e34 846cfc3d 4c611fcd d645fe8f - // f4061640 6d08d196 f330a975 66e30993 - // fd96a033 2b16def6 62ff30af 3e190b0b - // 664a5b91 b8558235 fd631825 a7807be7 - // ec906b9b 76d8b32e 36f3ea0b 1b0f5391 - // - - // Decrypt the block table -// DecryptMpqBlock(pBlock, MpqHeader.dwBlockTableSize * sizeof(TMPQBlock), MPQ_KEY_BLOCK_TABLE); - - // - // At this point, the block table should be like this: - // - // 0000002c 00078093 00116824 84000200 - // 000780bf 000002d5 00008044 84000200 - // 00078394 00001516 0000874c 84000200 - // 000798aa 00003797 0000af4e 84000200 - // 0007d041 000001db 00008044 84000200 - // 0007d21c 0000005e 0000005e 84000200 - // 0007d27a 000022fb 00009674 84000200 - // 0007f575 00002389 00009c64 84000200 - // 000818fe 000023cb 00009d58 84000200 - // 00083cc9 000024d9 0000a0d8 84000200 - // 000861a2 00002356 00009c70 84000200 - // 000884f8 000023d3 00009da4 84000200 - // 0008a8cb 000022d6 00009cd4 84000200 - // 0008cba1 00002339 00009714 84000200 - // 0008eeda 000023dc 00009b24 84000200 - // 000912b6 00002481 00009eac 84000200 - // 00093737 00002444 0000a028 84000200 - // 00095b7b 00002440 00009fc4 84000200 - // + for(int i = 0; i < 10; i++) + { + if(!FileStream_Read(pStream, NULL, szString2, dwLength)) + { + printf("Failed to read from the stream\n"); + return -1; + } + szString2[dwLength] = 0; + if(strcmp(szString1, szString2)) + { + printf("Data read from file are different from data written\n"); + return -1; + } + } FileStream_Close(pStream); } return 0; } */ + diff --git a/dep/StormLib/src/FileStream.h b/dep/StormLib/src/FileStream.h new file mode 100644 index 00000000000..31fe757514d --- /dev/null +++ b/dep/StormLib/src/FileStream.h @@ -0,0 +1,189 @@ +/*****************************************************************************/ +/* FileStream.h Copyright (c) Ladislav Zezula 2012 */ +/*---------------------------------------------------------------------------*/ +/* Description: Definitions for FileStream object */ +/*---------------------------------------------------------------------------*/ +/* Date Ver Who Comment */ +/* -------- ---- --- ------- */ +/* 14.04.12 1.00 Lad The first version of FileStream.h */ +/*****************************************************************************/ + +#ifndef __FILESTREAM_H__ +#define __FILESTREAM_H__ + +//----------------------------------------------------------------------------- +// Function prototypes + +typedef bool (*STREAM_READ)( + struct TFileStream * pStream, // Pointer to an open stream + ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position + void * pvBuffer, // Pointer to data to be read + DWORD dwBytesToRead // Number of bytes to read from the file + ); + +typedef bool (*STREAM_WRITE)( + struct TFileStream * pStream, // Pointer to an open stream + ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it writes to the current position + const void * pvBuffer, // Pointer to data to be written + DWORD dwBytesToWrite // Number of bytes to read from the file + ); + +typedef bool (*STREAM_GETPOS)( + struct TFileStream * pStream, // Pointer to an open stream + ULONGLONG & ByteOffset // Pointer to store current file position + ); + +typedef bool (*STREAM_GETSIZE)( + struct TFileStream * pStream, // Pointer to an open stream + ULONGLONG & FileSize // Receives the file size, in bytes + ); + +typedef bool (*STREAM_SETSIZE)( + struct TFileStream * pStream, // Pointer to an open stream + ULONGLONG FileSize // New size for the file, in bytes + ); + +typedef bool (*STREAM_GETTIME)( + struct TFileStream * pStream, + ULONGLONG * pFT + ); + +typedef bool (*STREAM_SWITCH)( + struct TFileStream * pStream, + struct TFileStream * pNewStream + ); + +typedef bool (*STREAM_GETBMP)( + TFileStream * pStream, + TFileBitmap * pBitmap, + DWORD Length, + LPDWORD LengthNeeded + ); + +typedef void (*STREAM_CLOSE)( + struct TFileStream * pStream + ); + +//----------------------------------------------------------------------------- +// Local structures - part file structure + +typedef struct _PART_FILE_HEADER +{ + DWORD PartialVersion; // Always set to 2 + char GameBuildNumber[0x20]; // Minimum build number of the game that can use this MPQ + DWORD Flags; // Flags (details unknown) + DWORD FileSizeLo; // Low 32 bits of the contained file size + DWORD FileSizeHi; // High 32 bits of the contained file size + DWORD BlockSize; // Size of one file block, in bytes + +} PART_FILE_HEADER, *PPART_FILE_HEADER; + +// Structure describing the block-to-file map entry +typedef struct _PART_FILE_MAP_ENTRY +{ + DWORD Flags; // 3 = the block is present in the file + DWORD BlockOffsLo; // Low 32 bits of the block position in the file + DWORD BlockOffsHi; // High 32 bits of the block position in the file + DWORD LargeValueLo; // 64-bit value, meaning is unknown + DWORD LargeValueHi; + +} PART_FILE_MAP_ENTRY, *PPART_FILE_MAP_ENTRY; + +//----------------------------------------------------------------------------- +// Local structures + +union TBaseData +{ + struct + { + ULONGLONG FileSize; // Size of the file + ULONGLONG FilePos; // Current file position + ULONGLONG FileTime; // Date/time of last modification of the file + HANDLE hFile; // File handle + } File; + + struct + { + ULONGLONG FileSize; // Mapped file size + ULONGLONG FilePos; // Current stream position + ULONGLONG FileTime; // Date/time of last modification of the file + LPBYTE pbFile; // Pointer to mapped view + } Map; + + struct + { + ULONGLONG FileSize; // Size of the internet file + ULONGLONG FilePos; // Current position in the file + ULONGLONG FileTime; // Date/time of last modification of the file + HANDLE hInternet; // Internet handle + HANDLE hConnect; // Connection to the internet server + } Http; +}; + +//----------------------------------------------------------------------------- +// Structure for linear stream + +struct TFileStream +{ + // Stream provider functions + STREAM_READ StreamRead; // Pointer to stream read function for this archive. Do not use directly. + STREAM_WRITE StreamWrite; // Pointer to stream write function for this archive. Do not use directly. + STREAM_GETPOS StreamGetPos; // Pointer to function that returns current file position + STREAM_GETSIZE StreamGetSize; // Pointer to function returning file size + STREAM_SETSIZE StreamSetSize; // Pointer to function changing file size + STREAM_GETTIME StreamGetTime; // Pointer to function retrieving the file time + STREAM_GETBMP StreamGetBmp; // Pointer to function that retrieves the file bitmap + STREAM_SWITCH StreamSwitch; // Pointer to function changing the stream to another file + STREAM_CLOSE StreamClose; // Pointer to function closing the stream + + // Stream provider data members + TCHAR szFileName[MAX_PATH]; // File name + DWORD dwFlags; // Stream flags + + // Base provider functions + STREAM_READ BaseRead; + STREAM_WRITE BaseWrite; + STREAM_GETPOS BaseGetPos; // Pointer to function that returns current file position + STREAM_GETSIZE BaseGetSize; // Pointer to function returning file size + STREAM_SETSIZE BaseSetSize; // Pointer to function changing file size + STREAM_GETTIME BaseGetTime; // Pointer to function retrieving the file time + STREAM_CLOSE BaseClose; // Pointer to function closing the stream + + // Base provider data members + TBaseData Base; // Base provider data + + // Followed by stream provider data, with variable length +}; + +//----------------------------------------------------------------------------- +// Structure for linear stream + +struct TLinearStream : public TFileStream +{ + TFileBitmap * pBitmap; // Pointer to the stream bitmap +}; + +//----------------------------------------------------------------------------- +// Structure for partial stream + +struct TPartialStream : public TFileStream +{ + ULONGLONG VirtualSize; // Virtual size of the file + ULONGLONG VirtualPos; // Virtual position in the file + DWORD BlockCount; // Number of file blocks. Used by partial file stream + DWORD BlockSize; // Size of one block. Used by partial file stream + + PPART_FILE_MAP_ENTRY PartMap; // File map, variable length +}; + +//----------------------------------------------------------------------------- +// Structure for encrypted stream + +#define MPQE_CHUNK_SIZE 0x40 // Size of one chunk to be decrypted + +struct TEncryptedStream : public TFileStream +{ + BYTE Key[MPQE_CHUNK_SIZE]; // File key +}; + +#endif // __FILESTREAM_H__ diff --git a/dep/StormLib/src/SBaseCommon.cpp b/dep/StormLib/src/SBaseCommon.cpp index 9db708a2fe7..65818784521 100644 --- a/dep/StormLib/src/SBaseCommon.cpp +++ b/dep/StormLib/src/SBaseCommon.cpp @@ -15,12 +15,11 @@ #include "StormLib.h" #include "StormCommon.h" -char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Ladislav Zezula 1998-2011"; +char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Ladislav Zezula 1998-2012"; //----------------------------------------------------------------------------- // The buffer for decryption engine. -DWORD dwGlobalFlags = 0; // Global flags LCID lcFileLocale = LANG_NEUTRAL; // File locale USHORT wPlatform = 0; // File platform @@ -319,6 +318,20 @@ int ConvertMpqHeaderToFormat4( } //----------------------------------------------------------------------------- +// Default flags for (attributes) and (listfile) + +DWORD GetDefaultSpecialFileFlags(TMPQArchive * ha, DWORD dwFileSize) +{ + // Fixed for format 1.0 + if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) + return MPQ_FILE_COMPRESS | MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY; + + // Size-dependent for formats 2.0-4.0 + return (dwFileSize > 0x4000) ? (MPQ_FILE_COMPRESS | MPQ_FILE_SECTOR_CRC) : (MPQ_FILE_COMPRESS | MPQ_FILE_SINGLE_UNIT); +} + + +//----------------------------------------------------------------------------- // Encrypting and decrypting MPQ file data void EncryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwSeed1) @@ -692,11 +705,9 @@ void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos) FreeSpacePos = pFileEntry->ByteOffset + pFileEntry->dwCmpSize; // Add the MD5 chunks, if present - if(pHeader->dwRawChunkSize != 0) + if(pHeader->dwRawChunkSize != 0 && pFileEntry->dwCmpSize != 0) { - dwChunkCount = pFileEntry->dwCmpSize / pHeader->dwRawChunkSize; - if(pFileEntry->dwCmpSize % pHeader->dwRawChunkSize) - dwChunkCount++; + dwChunkCount = ((pFileEntry->dwCmpSize - 1) / pHeader->dwRawChunkSize) + 1; FreeSpacePos += dwChunkCount * MD5_DIGEST_SIZE; } } @@ -773,7 +784,7 @@ int LoadMpqTable( int cbOutBuffer = (int)dwRealSize; int cbInBuffer = (int)dwCompressedSize; - if(!SCompDecompress((char *)pvTable, &cbOutBuffer, (char *)pbCompressed, cbInBuffer)) + if(!SCompDecompress2((char *)pvTable, &cbOutBuffer, (char *)pbCompressed, cbInBuffer)) nError = GetLastError(); // Free the temporary buffer @@ -828,13 +839,11 @@ unsigned char * AllocateMd5Buffer( DWORD cbMd5Size; // Sanity check + assert(dwRawDataSize != 0); assert(dwChunkSize != 0); // Calculate how many MD5's we will calculate - cbMd5Size = dwRawDataSize / dwChunkSize; - if(dwRawDataSize % dwChunkSize) - cbMd5Size++; - cbMd5Size *= MD5_DIGEST_SIZE; + cbMd5Size = (((dwRawDataSize - 1) / dwChunkSize) + 1) * MD5_DIGEST_SIZE; // Allocate space for array or MD5s md5_array = STORM_ALLOC(BYTE, cbMd5Size); @@ -853,9 +862,12 @@ int AllocateSectorBuffer(TMPQFile * hf) // Caller of AllocateSectorBuffer must ensure these assert(hf->pbFileSector == NULL); assert(hf->pFileEntry != NULL); - assert(hf->dwDataSize != 0); assert(hf->ha != NULL); + // Don't allocate anything if the file has zero size + if(hf->pFileEntry->dwFileSize == 0 || hf->dwDataSize == 0) + return ERROR_SUCCESS; + // Determine the file sector size and allocate buffer for it hf->dwSectorSize = (hf->pFileEntry->dwFlags & MPQ_FILE_SINGLE_UNIT) ? hf->dwDataSize : ha->dwSectorSize; hf->pbFileSector = STORM_ALLOC(BYTE, hf->dwSectorSize); @@ -889,7 +901,7 @@ __AllocateAndLoadPatchInfo: // Load the patch header if(!FileStream_Read(ha->pStream, &hf->RawFilePos, hf->pPatchInfo, dwLength)) { - // Free the sector offsets + // Free the patch info STORM_FREE(hf->pPatchInfo); hf->pPatchInfo = NULL; return GetLastError(); @@ -904,10 +916,14 @@ __AllocateAndLoadPatchInfo: // If it's not default size, we have to reload them if(hf->pPatchInfo->dwLength > dwLength) { + // Free the patch info dwLength = hf->pPatchInfo->dwLength; STORM_FREE(hf->pPatchInfo); hf->pPatchInfo = NULL; + // If the length is out of all possible ranges, fail the operation + if(dwLength > 0x400) + return ERROR_FILE_CORRUPT; goto __AllocateAndLoadPatchInfo; } @@ -947,6 +963,7 @@ int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) } // Calculate the number of data sectors + // Note that this doesn't work if the file size is zero hf->dwSectorCount = ((hf->dwDataSize - 1) / hf->dwSectorSize) + 1; // Calculate the number of file sectors @@ -961,6 +978,8 @@ int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) // Only allocate and load the table if the file is compressed if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) { + __LoadSectorOffsets: + // Allocate the sector offset table hf->SectorOffsets = (DWORD *)STORM_ALLOC(BYTE, dwSectorOffsLen); if(hf->SectorOffsets == NULL) @@ -1044,10 +1063,18 @@ int AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) // There may be various extra DWORDs loaded after the sector offset table. // They are mostly empty on WoW release MPQs, but on MPQs from PTR, // they contain random non-zero data. Their meaning is unknown. - // At this point, we completely ignore them + // + // These extra values are, however, include in the dwCmpSize in the file + // table. We cannot ignore them, because compacting archive would fail // -// assert(dwSectorOffsLen == hf->SectorOffsets[0]); + if(hf->SectorOffsets[0] > dwSectorOffsLen) + { + dwSectorOffsLen = hf->SectorOffsets[0]; + STORM_FREE(hf->SectorOffsets); + hf->SectorOffsets = NULL; + goto __LoadSectorOffsets; + } } else { @@ -1388,6 +1415,10 @@ void FreeMPQArchive(TMPQArchive *& ha) if(ha->haPatch != NULL) FreeMPQArchive(ha->haPatch); + // Close the file stream + FileStream_Close(ha->pStream); + ha->pStream = NULL; + // Free the file names from the file table if(ha->pFileTable != NULL) { @@ -1402,11 +1433,12 @@ void FreeMPQArchive(TMPQArchive *& ha) STORM_FREE(ha->pFileTable); } + if(ha->pBitmap != NULL) + STORM_FREE(ha->pBitmap); if(ha->pHashTable != NULL) STORM_FREE(ha->pHashTable); if(ha->pHetTable != NULL) FreeHetTable(ha->pHetTable); - FileStream_Close(ha->pStream); STORM_FREE(ha); ha = NULL; } diff --git a/dep/StormLib/src/SBaseDumpData.cpp b/dep/StormLib/src/SBaseDumpData.cpp index f2b5fad1e8f..c9dcf0a3366 100644 --- a/dep/StormLib/src/SBaseDumpData.cpp +++ b/dep/StormLib/src/SBaseDumpData.cpp @@ -17,18 +17,18 @@ void DumpMpqHeader(TMPQHeader * pHeader) { printf("== MPQ Header =================================\n"); - printf("DWORD dwID = %08lX\n", pHeader->dwID); - printf("DWORD dwHeaderSize = %08lX\n", pHeader->dwHeaderSize); - printf("DWORD dwArchiveSize = %08lX\n", pHeader->dwArchiveSize); - printf("USHORT wFormatVersion = %04lX\n", pHeader->wFormatVersion); - printf("USHORT wSectorSize = %04lX\n", pHeader->wSectorSize); - printf("DWORD dwHashTablePos = %08lX\n", pHeader->dwHashTablePos); - printf("DWORD dwBlockTablePos = %08lX\n", pHeader->dwBlockTablePos); - printf("DWORD dwHashTableSize = %08lX\n", pHeader->dwHashTableSize); - printf("DWORD dwBlockTableSize = %08lX\n", pHeader->dwBlockTableSize); + printf("DWORD dwID = %08X\n", pHeader->dwID); + printf("DWORD dwHeaderSize = %08X\n", pHeader->dwHeaderSize); + printf("DWORD dwArchiveSize = %08X\n", pHeader->dwArchiveSize); + printf("USHORT wFormatVersion = %04X\n", pHeader->wFormatVersion); + printf("USHORT wSectorSize = %04X\n", pHeader->wSectorSize); + printf("DWORD dwHashTablePos = %08X\n", pHeader->dwHashTablePos); + printf("DWORD dwBlockTablePos = %08X\n", pHeader->dwBlockTablePos); + printf("DWORD dwHashTableSize = %08X\n", pHeader->dwHashTableSize); + printf("DWORD dwBlockTableSize = %08X\n", pHeader->dwBlockTableSize); printf("ULONGLONG HiBlockTablePos64 = %016llX\n", pHeader->HiBlockTablePos64); - printf("USHORT wHashTablePosHi = %04lX\n", pHeader->wHashTablePosHi); - printf("USHORT wBlockTablePosHi = %04lX\n", pHeader->wBlockTablePosHi); + printf("USHORT wHashTablePosHi = %04X\n", pHeader->wHashTablePosHi); + printf("USHORT wBlockTablePosHi = %04X\n", pHeader->wBlockTablePosHi); printf("ULONGLONG ArchiveSize64 = %016llX\n", pHeader->ArchiveSize64); printf("ULONGLONG BetTablePos64 = %016llX\n", pHeader->BetTablePos64); printf("ULONGLONG HetTablePos64 = %016llX\n", pHeader->HetTablePos64); @@ -37,7 +37,7 @@ void DumpMpqHeader(TMPQHeader * pHeader) printf("ULONGLONG HiBlockTableSize64 = %016llX\n", pHeader->HiBlockTableSize64); printf("ULONGLONG HetTableSize64 = %016llX\n", pHeader->HetTableSize64); printf("ULONGLONG BetTableSize64 = %016llX\n", pHeader->BetTableSize64); - printf("DWORD dwRawChunkSize = %08lX\n", pHeader->dwRawChunkSize); + printf("DWORD dwRawChunkSize = %08X\n", pHeader->dwRawChunkSize); printf("-----------------------------------------------\n\n"); } @@ -51,31 +51,31 @@ void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable) printf("== HET Header =================================\n"); printf("ULONGLONG AndMask64 = %016llX\n", pHetTable->AndMask64); printf("ULONGLONG OrMask64 = %016llX\n", pHetTable->OrMask64); - printf("DWORD dwIndexSizeTotal = %08lX\n", pHetTable->dwIndexSizeTotal); - printf("DWORD dwIndexSizeExtra = %08lX\n", pHetTable->dwIndexSizeExtra); - printf("DWORD dwIndexSize = %08lX\n", pHetTable->dwIndexSize); - printf("DWORD dwMaxFileCount = %08lX\n", pHetTable->dwMaxFileCount); - printf("DWORD dwHashTableSize = %08lX\n", pHetTable->dwHashTableSize); - printf("DWORD dwHashBitSize = %08lX\n", pHetTable->dwHashBitSize); + printf("DWORD dwIndexSizeTotal = %08X\n", pHetTable->dwIndexSizeTotal); + printf("DWORD dwIndexSizeExtra = %08X\n", pHetTable->dwIndexSizeExtra); + printf("DWORD dwIndexSize = %08X\n", pHetTable->dwIndexSize); + printf("DWORD dwMaxFileCount = %08X\n", pHetTable->dwMaxFileCount); + printf("DWORD dwHashTableSize = %08X\n", pHetTable->dwHashTableSize); + printf("DWORD dwHashBitSize = %08X\n", pHetTable->dwHashBitSize); printf("-----------------------------------------------\n\n"); printf("== BET Header =================================\n"); - printf("DWORD dwTableEntrySize = %08lX\n", pBetTable->dwTableEntrySize); - printf("DWORD dwBitIndex_FilePos = %08lX\n", pBetTable->dwBitIndex_FilePos); - printf("DWORD dwBitIndex_FileSize = %08lX\n", pBetTable->dwBitIndex_FileSize); - printf("DWORD dwBitIndex_CmpSize = %08lX\n", pBetTable->dwBitIndex_CmpSize); - printf("DWORD dwBitIndex_FlagIndex = %08lX\n", pBetTable->dwBitIndex_FlagIndex); - printf("DWORD dwBitIndex_Unknown = %08lX\n", pBetTable->dwBitIndex_Unknown); - printf("DWORD dwBitCount_FilePos = %08lX\n", pBetTable->dwBitCount_FilePos); - printf("DWORD dwBitCount_FileSize = %08lX\n", pBetTable->dwBitCount_FileSize); - printf("DWORD dwBitCount_CmpSize = %08lX\n", pBetTable->dwBitCount_CmpSize); - printf("DWORD dwBitCount_FlagIndex = %08lX\n", pBetTable->dwBitCount_FlagIndex); - printf("DWORD dwBitCount_Unknown = %08lX\n", pBetTable->dwBitCount_Unknown); - printf("DWORD dwBetHashSizeTotal = %08lX\n", pBetTable->dwBetHashSizeTotal); - printf("DWORD dwBetHashSizeExtra = %08lX\n", pBetTable->dwBetHashSizeExtra); - printf("DWORD dwBetHashSize = %08lX\n", pBetTable->dwBetHashSize); - printf("DWORD dwMaxFileCount = %08lX\n", pBetTable->dwMaxFileCount); - printf("DWORD dwFlagCount = %08lX\n", pBetTable->dwFlagCount); + printf("DWORD dwTableEntrySize = %08X\n", pBetTable->dwTableEntrySize); + printf("DWORD dwBitIndex_FilePos = %08X\n", pBetTable->dwBitIndex_FilePos); + printf("DWORD dwBitIndex_FileSize = %08X\n", pBetTable->dwBitIndex_FileSize); + printf("DWORD dwBitIndex_CmpSize = %08X\n", pBetTable->dwBitIndex_CmpSize); + printf("DWORD dwBitIndex_FlagIndex = %08X\n", pBetTable->dwBitIndex_FlagIndex); + printf("DWORD dwBitIndex_Unknown = %08X\n", pBetTable->dwBitIndex_Unknown); + printf("DWORD dwBitCount_FilePos = %08X\n", pBetTable->dwBitCount_FilePos); + printf("DWORD dwBitCount_FileSize = %08X\n", pBetTable->dwBitCount_FileSize); + printf("DWORD dwBitCount_CmpSize = %08X\n", pBetTable->dwBitCount_CmpSize); + printf("DWORD dwBitCount_FlagIndex = %08X\n", pBetTable->dwBitCount_FlagIndex); + printf("DWORD dwBitCount_Unknown = %08X\n", pBetTable->dwBitCount_Unknown); + printf("DWORD dwBetHashSizeTotal = %08X\n", pBetTable->dwBetHashSizeTotal); + printf("DWORD dwBetHashSizeExtra = %08X\n", pBetTable->dwBetHashSizeExtra); + printf("DWORD dwBetHashSize = %08X\n", pBetTable->dwBetHashSize); + printf("DWORD dwMaxFileCount = %08X\n", pBetTable->dwMaxFileCount); + printf("DWORD dwFlagCount = %08X\n", pBetTable->dwFlagCount); printf("-----------------------------------------------\n\n"); printf("== HET & Bet Table ======================================================================\n\n"); @@ -128,7 +128,7 @@ void DumpHetAndBetTable(TMPQHetTable * pHetTable, TMPQBetTable * pBetTable) dwFlags = pBetTable->pFileFlags[dwFlagIndex]; } - printf(" %04lX %02lX %04lX %016llX %016llX %08lX %08lX %04lX %08lX\n", i, + printf(" %04X %02lX %04X %016llX %016llX %08X %08X %04X %08X\n", i, pHetTable->pHetHashes[i], dwBetIndex, BetHash, diff --git a/dep/StormLib/src/SBaseFileTable.cpp b/dep/StormLib/src/SBaseFileTable.cpp index 83d31bbac94..09379ca5da7 100644 --- a/dep/StormLib/src/SBaseFileTable.cpp +++ b/dep/StormLib/src/SBaseFileTable.cpp @@ -15,7 +15,8 @@ //----------------------------------------------------------------------------- // Local defines -#define MAX_FLAG_INDEX 256 +#define INVALID_FLAG_VALUE 0xCCCCCCCC +#define MAX_FLAG_INDEX 512 //----------------------------------------------------------------------------- // Local structures @@ -62,63 +63,10 @@ typedef struct _BET_TABLE_HEADER //----------------------------------------------------------------------------- // Support for calculating bit sizes -static DWORD GetNecessaryBitCount(ULONGLONG MaxValue) -{ - DWORD dwBitCount = 0; - - while(MaxValue > 0) - { - MaxValue >>= 1; - dwBitCount++; - } - - return dwBitCount; -} - -static BYTE GetFlagsComboIndex(DWORD dwFlags) +static void InitFileFlagArray(LPDWORD FlagArray) { - BYTE FlagComboIndex = 0; - - // - // We only use 8 different bits. This allows us to - // construct 256 unique values for every possible combination of MPQ file flags. - // - - if(dwFlags & MPQ_FILE_IMPLODE) - FlagComboIndex |= 0x01; - dwFlags &= ~MPQ_FILE_IMPLODE; - - if(dwFlags & MPQ_FILE_COMPRESS) - FlagComboIndex |= 0x02; - dwFlags &= ~MPQ_FILE_COMPRESS; - - if(dwFlags & MPQ_FILE_ENCRYPTED) - FlagComboIndex |= 0x04; - dwFlags &= ~MPQ_FILE_ENCRYPTED; - - if(dwFlags & MPQ_FILE_FIX_KEY) - FlagComboIndex |= 0x08; - dwFlags &= ~MPQ_FILE_FIX_KEY; - - if(dwFlags & MPQ_FILE_PATCH_FILE) - FlagComboIndex |= 0x10; - dwFlags &= ~MPQ_FILE_PATCH_FILE; - - if(dwFlags & MPQ_FILE_SINGLE_UNIT) - FlagComboIndex |= 0x20; - dwFlags &= ~MPQ_FILE_SINGLE_UNIT; - - if(dwFlags & MPQ_FILE_DELETE_MARKER) - FlagComboIndex |= 0x40; - dwFlags &= ~MPQ_FILE_DELETE_MARKER; - - if(dwFlags & MPQ_FILE_SECTOR_CRC) - FlagComboIndex |= 0x80; - dwFlags &= ~MPQ_FILE_SECTOR_CRC; - - // Sanity check - the flags must now be zero - assert((dwFlags & 0x7FFFFFFF) == 0); - return FlagComboIndex; + for(DWORD dwFlagIndex = 0; dwFlagIndex < MAX_FLAG_INDEX; dwFlagIndex++) + FlagArray[dwFlagIndex] = INVALID_FLAG_VALUE; } static DWORD GetFileFlagIndex(LPDWORD FlagArray, DWORD dwFlags) @@ -126,7 +74,7 @@ static DWORD GetFileFlagIndex(LPDWORD FlagArray, DWORD dwFlags) // Find free or equal entry in the flag array for(DWORD dwFlagIndex = 0; dwFlagIndex < MAX_FLAG_INDEX; dwFlagIndex++) { - if(FlagArray[dwFlagIndex] == 0 || FlagArray[dwFlagIndex] == dwFlags) + if(FlagArray[dwFlagIndex] == INVALID_FLAG_VALUE || FlagArray[dwFlagIndex] == dwFlags) { FlagArray[dwFlagIndex] = dwFlags; return dwFlagIndex; @@ -138,6 +86,19 @@ static DWORD GetFileFlagIndex(LPDWORD FlagArray, DWORD dwFlags) return 0xFFFFFFFF; } +static DWORD GetNecessaryBitCount(ULONGLONG MaxValue) +{ + DWORD dwBitCount = 0; + + while(MaxValue > 0) + { + MaxValue >>= 1; + dwBitCount++; + } + + return dwBitCount; +} + //----------------------------------------------------------------------------- // Support functions for BIT_ARRAY @@ -420,8 +381,7 @@ static TMPQBlock * TranslateBlockTable( BlockTableSize = sizeof(TMPQBlock) * ha->dwFileTableSize; for(DWORD i = 0; i < ha->dwFileTableSize; i++) { - if(pFileEntry->ByteOffset >> 32) - bNeedHiBlockTable = true; + bNeedHiBlockTable = (pFileEntry->ByteOffset >> 32) ? true : false; pBlock->dwFilePos = (DWORD)pFileEntry->ByteOffset; pBlock->dwFSize = pFileEntry->dwFileSize; pBlock->dwCSize = pFileEntry->dwCmpSize; @@ -519,11 +479,15 @@ TMPQExtTable * LoadExtTable( int cbOutBuffer = (int)pCompressed->dwDataSize; int cbInBuffer = (int)Size; - // Decompress the XXX block + // Decompress the extended table pExtTable->dwSignature = pCompressed->dwSignature; pExtTable->dwVersion = pCompressed->dwVersion; pExtTable->dwDataSize = pCompressed->dwDataSize; - SCompDecompress((char *)(pExtTable + 1), &cbOutBuffer, (char *)(pCompressed + 1), cbInBuffer); + if(!SCompDecompress2((char *)(pExtTable + 1), &cbOutBuffer, (char *)(pCompressed + 1), cbInBuffer)) + { + STORM_FREE(pExtTable); + pExtTable = NULL; + } } // Free the compressed block @@ -537,9 +501,9 @@ TMPQExtTable * LoadExtTable( } // Used in MPQ Editor -void FreeExtTable(TMPQExtTable * pExtTable) +void FreeMpqBuffer(void * pvBuffer) { - STORM_FREE(pExtTable); + STORM_FREE(pvBuffer); } static int SaveMpqTable( @@ -1018,26 +982,18 @@ static void CreateBetHeader( TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; TFileEntry * pFileEntry; ULONGLONG MaxByteOffset = 0; + DWORD FlagArray[MAX_FLAG_INDEX]; + DWORD dwMaxFlagIndex = 0; DWORD dwMaxFileSize = 0; DWORD dwMaxCmpSize = 0; - DWORD dwFlagCount = 0; - BYTE FlagComboArray[MAX_FLAG_INDEX]; - BYTE FlagComboIndex; + DWORD dwFlagIndex; // Initialize array of flag combinations - memset(FlagComboArray, 0, sizeof(FlagComboArray)); + InitFileFlagArray(FlagArray); // Get the maximum values for the BET table for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++) { - // We don't allow the file table to have free entries in the middle - // This must be a bug in the library somewhere. - if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0) - { - pFileEntry->dwFlags = MPQ_FILE_EXISTS | MPQ_FILE_DELETE_MARKER; - assert(false); - } - // Highest file position in the MPQ if(pFileEntry->ByteOffset > MaxByteOffset) MaxByteOffset = pFileEntry->ByteOffset; @@ -1051,10 +1007,9 @@ static void CreateBetHeader( dwMaxCmpSize = pFileEntry->dwCmpSize; // Check if this flag was there before - FlagComboIndex = GetFlagsComboIndex(pFileEntry->dwFlags); - if(FlagComboArray[FlagComboIndex] == 0) - dwFlagCount++; - FlagComboArray[FlagComboIndex] = 1; + dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags); + if(dwFlagIndex > dwMaxFlagIndex) + dwMaxFlagIndex = dwFlagIndex; } // Now save bit count for every piece of file information @@ -1068,7 +1023,7 @@ static void CreateBetHeader( pBetHeader->dwBitCount_CmpSize = GetNecessaryBitCount(dwMaxCmpSize); pBetHeader->dwBitIndex_FlagIndex = pBetHeader->dwBitIndex_CmpSize + pBetHeader->dwBitCount_CmpSize; - pBetHeader->dwBitCount_FlagIndex = GetNecessaryBitCount(dwFlagCount); + pBetHeader->dwBitCount_FlagIndex = GetNecessaryBitCount(dwMaxFlagIndex + 1); pBetHeader->dwBitIndex_Unknown = pBetHeader->dwBitIndex_FlagIndex + pBetHeader->dwBitCount_FlagIndex; pBetHeader->dwBitCount_Unknown = 0; @@ -1082,7 +1037,7 @@ static void CreateBetHeader( // Save the file count and flag count pBetHeader->dwFileCount = ha->dwFileTableSize; - pBetHeader->dwFlagCount = dwFlagCount; + pBetHeader->dwFlagCount = dwMaxFlagIndex + 1; pBetHeader->dwUnknown08 = 0x10; // Save the total size of the BET hash @@ -1224,8 +1179,8 @@ TMPQExtTable * TranslateBetTable( DWORD i; // Calculate the bit sizes of various entries + InitFileFlagArray(FlagArray); CreateBetHeader(ha, &BetHeader); - memset(FlagArray, 0, sizeof(FlagArray)); // Calculate the size of the BET table BetTableSize = sizeof(BET_TABLE_HEADER) + @@ -1260,30 +1215,32 @@ TMPQExtTable * TranslateBetTable( // Construct the array of flag values and bit-based file table for(i = 0; i < BetHeader.dwFileCount; i++, pFileEntry++) { - // Only count files that exist - if(pFileEntry->dwFlags & MPQ_FILE_EXISTS) - { - // Save the byte offset - pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FilePos, - BetHeader.dwBitCount_FilePos, - &pFileEntry->ByteOffset, - 8); - pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FileSize, - BetHeader.dwBitCount_FileSize, - &pFileEntry->dwFileSize, - 4); - pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_CmpSize, - BetHeader.dwBitCount_CmpSize, - &pFileEntry->dwCmpSize, - 4); - - // Get the flag array for the file - dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags); - pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FlagIndex, - BetHeader.dwBitCount_FlagIndex, - &dwFlagIndex, - 4); - } + // + // Note: Blizzard MPQs contain valid values even for non-existant files + // (FilePos, FileSize, CmpSize and FlagIndex) + // Note: If flags is zero, it must be in the flag table too !!! + // + + // Save the byte offset + pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FilePos, + BetHeader.dwBitCount_FilePos, + &pFileEntry->ByteOffset, + 8); + pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FileSize, + BetHeader.dwBitCount_FileSize, + &pFileEntry->dwFileSize, + 4); + pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_CmpSize, + BetHeader.dwBitCount_CmpSize, + &pFileEntry->dwCmpSize, + 4); + + // Save the flag index + dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags); + pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FlagIndex, + BetHeader.dwBitCount_FlagIndex, + &dwFlagIndex, + 4); // Move the bit offset nBitOffset += BetHeader.dwTableEntrySize; @@ -1480,7 +1437,7 @@ void AllocateFileName(TFileEntry * pFileEntry, const char * szFileName) TFileEntry * FindFreeFileEntry(TMPQArchive * ha) { TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; - TFileEntry * pDeletedEntry = NULL; + TFileEntry * pFreeEntry = NULL; TFileEntry * pFileEntry; // Try to find a free entry @@ -1488,18 +1445,22 @@ TFileEntry * FindFreeFileEntry(TMPQArchive * ha) { // If that entry is free, we reuse it if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0) - return pFileEntry; + { + pFreeEntry = pFileEntry; + break; + } - // If that entry is deleted, remember it - if(pFileEntry->dwFlags & MPQ_FILE_DELETE_MARKER) - pDeletedEntry = pFileEntry; + // + // Note: Files with "delete marker" are not deleted. + // Don't consider them free entries + // } // Do we have a deleted entry? - if(pDeletedEntry != NULL) + if(pFreeEntry != NULL) { - ClearFileEntry(ha, pDeletedEntry); - return pDeletedEntry; + ClearFileEntry(ha, pFreeEntry); + return pFreeEntry; } // If no file entry within the existing file table is free, @@ -1702,9 +1663,11 @@ void ClearFileEntry( 4); } - // Free the file name, and zero the entire entry + // Free the file name, and set the file entry as deleted if(pFileEntry->szFileName != NULL) STORM_FREE(pFileEntry->szFileName); + + // Invalidate the file entry memset(pFileEntry, 0, sizeof(TFileEntry)); } @@ -1718,7 +1681,7 @@ int FreeFileEntry( // // If we have HET table, we cannot just get rid of the file - // Doing so would lead to empty gaps in the HET and BET tables + // Doing so would lead to empty gaps in the HET table // We have to keep BET hash, hash index, HET index, locale, platform and file name // @@ -1750,14 +1713,10 @@ int FreeFileEntry( } else { - memset(pFileEntry->md5, 0, MD5_DIGEST_SIZE); - pFileEntry->ByteOffset = 0; - pFileEntry->FileTime = 0; - pFileEntry->dwFileSize = 0; - pFileEntry->dwCmpSize = 0; - pFileEntry->dwFlags = MPQ_FILE_EXISTS | MPQ_FILE_DELETE_MARKER; - pFileEntry->dwCrc32 = 0; - nError = ERROR_MARKED_FOR_DELETE; + // Note: Deleted entries in Blizzard MPQs version 4.0 + // normally contain valid byte offset and length + pFileEntry->dwFlags &= ~MPQ_FILE_EXISTS; + nError = ERROR_SUCCESS; } return nError; @@ -1785,49 +1744,104 @@ void InvalidateInternalFiles(TMPQArchive * ha) ha->dwFlags |= MPQ_FLAG_INV_ATTRIBUTES; } - // Remember that the MPQ has been changed and it will ne necessary + // Remember that the MPQ has been changed and it will be necessary // to update the tables ha->dwFlags |= MPQ_FLAG_CHANGED; } //----------------------------------------------------------------------------- -// Support for file tables - hash table, block table, hi-block table, -// (attributes) and (listfile) +// Functions that loads and verify MPQ data bitmap -static void FixBlockTableSize( - TMPQArchive * ha, - TMPQBlock * pBlockTable, - DWORD dwClaimedSize) +int LoadMpqDataBitmap(TMPQArchive * ha, ULONGLONG FileSize, bool * pbFileIsComplete) { - TMPQHeader * pHeader = ha->pHeader; - ULONGLONG BlockTableStart; - ULONGLONG BlockTableEnd; - ULONGLONG FileDataStart; + TMPQBitmap * pBitmap = NULL; + TMPQBitmap DataBitmap; + ULONGLONG BitmapOffset; + ULONGLONG EndOfMpq; + DWORD DataBlockCount = 0; + DWORD BitmapByteSize; + DWORD WholeByteCount; + DWORD ExtraBitsCount; + + // Is there enough space for a MPQ bitmap? + EndOfMpq = ha->MpqPos + ha->pHeader->ArchiveSize64; + FileSize = FileSize - sizeof(TMPQBitmap); + if(FileSize > EndOfMpq) + { + // Try to load the data bitmap from the end of the file + if(FileStream_Read(ha->pStream, &FileSize, &DataBitmap, sizeof(TMPQBitmap))) + { + // Is it a valid data bitmap? + BSWAP_ARRAY32_UNSIGNED((LPDWORD)(&DataBitmap), sizeof(TMPQBitmap)); + if(DataBitmap.dwSignature == MPQ_DATA_BITMAP_SIGNATURE) + { + // We assume that MPQs with data bitmap begin at position 0 + assert(ha->MpqPos == 0); - // Only perform this check on MPQs version 1.0 - if(pHeader->dwHeaderSize == MPQ_HEADER_SIZE_V1) + // Calculate the number of extra bytes for data bitmap + DataBlockCount = (DWORD)(((ha->pHeader->ArchiveSize64 - 1) / DataBitmap.dwBlockSize) + 1); + BitmapByteSize = ((DataBlockCount - 1) / 8) + 1; + + // Verify the data block size + BitmapOffset = ((ULONGLONG)DataBitmap.dwMapOffsetHi << 32) | DataBitmap.dwMapOffsetLo; + assert((DWORD)(FileSize - BitmapOffset) == BitmapByteSize); + + // Allocate space for the data bitmap + pBitmap = (TMPQBitmap *)STORM_ALLOC(BYTE, sizeof(TMPQBitmap) + BitmapByteSize); + if(pBitmap != NULL) + { + // Copy the bitmap header + memcpy(pBitmap, &DataBitmap, sizeof(TMPQBitmap)); + + // Read the remaining part + if(!FileStream_Read(ha->pStream, &BitmapOffset, (pBitmap + 1), BitmapByteSize)) + { + STORM_FREE(pBitmap); + pBitmap = NULL; + } + } + } + } + } + + // If the caller asks for file completeness, check it + if(pBitmap != NULL && pbFileIsComplete != NULL) { - // Calculate claimed block table begin and end - BlockTableStart = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); - BlockTableEnd = BlockTableStart + (pHeader->dwBlockTableSize * sizeof(TMPQBlock)); + LPBYTE pbBitmap = (LPBYTE)(pBitmap + 1); + DWORD i; + bool bFileIsComplete = true; - for(DWORD i = 0; i < dwClaimedSize; i++) + // Calculate the number of whole bytes and extra bits of the bitmap + WholeByteCount = (DataBlockCount / 8); + ExtraBitsCount = (DataBlockCount & 7); + + // Verify the whole bytes - their value must be 0xFF + for(i = 0; i < WholeByteCount; i++) { - // If the block table end goes into that file, fix the block table end - FileDataStart = ha->MpqPos + pBlockTable[i].dwFilePos; - if(BlockTableStart < FileDataStart && BlockTableEnd > FileDataStart) - { - dwClaimedSize = (DWORD)((FileDataStart - BlockTableStart) / sizeof(TMPQBlock)); - BlockTableEnd = FileDataStart; - } + if(pbBitmap[i] != 0xFF) + bFileIsComplete = false; + } + + // If there are extra bits, calculate the mask + if(ExtraBitsCount != 0) + { + BYTE ExpectedValue = (BYTE)((1 << ExtraBitsCount) - 1); + + if(pbBitmap[i] != ExpectedValue) + bFileIsComplete = false; } + + // Give the result to the caller + *pbFileIsComplete = bFileIsComplete; } - // Fix the block table size - pHeader->BlockTableSize64 = dwClaimedSize * sizeof(TMPQBlock); - pHeader->dwBlockTableSize = dwClaimedSize; + ha->pBitmap = pBitmap; + return ERROR_SUCCESS; } +//----------------------------------------------------------------------------- +// Support for file tables - hash table, block table, hi-block table + int CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize) { TMPQHash * pHashTable; @@ -1851,7 +1865,7 @@ int CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize) return ERROR_SUCCESS; } -int LoadHashTable(TMPQArchive * ha) +TMPQHash * LoadHashTable(TMPQArchive * ha) { TMPQHeader * pHeader = ha->pHeader; ULONGLONG ByteOffset; @@ -1862,17 +1876,17 @@ int LoadHashTable(TMPQArchive * ha) // If the MPQ has no hash table, do nothing if(pHeader->dwHashTablePos == 0 && pHeader->wHashTablePosHi == 0) - return ERROR_SUCCESS; + return NULL; // If the hash table size is zero, do nothing if(pHeader->dwHashTableSize == 0) - return ERROR_SUCCESS; + return NULL; // Allocate buffer for the hash table dwTableSize = pHeader->dwHashTableSize * sizeof(TMPQHash); pHashTable = STORM_ALLOC(TMPQHash, pHeader->dwHashTableSize); if(pHashTable == NULL) - return ERROR_NOT_ENOUGH_MEMORY; + return NULL; // Compressed size of the hash table dwCmpSize = (DWORD)pHeader->HashTableSize64; @@ -1891,17 +1905,108 @@ int LoadHashTable(TMPQArchive * ha) { STORM_FREE(pHashTable); pHashTable = NULL; - return nError; } - // Set the maximum file count to the size of the hash table - // In case there is HET table, we have to keep the file limit - if(ha->pHetTable == NULL) - ha->dwMaxFileCount = pHeader->dwHashTableSize; + // Return the hash table + return pHashTable; +} - // Store the hash table to the MPQ - ha->pHashTable = pHashTable; - return ERROR_SUCCESS; +static void FixBlockTableSize( + TMPQArchive * ha, + TMPQBlock * pBlockTable, + DWORD dwClaimedSize) +{ + TMPQHeader * pHeader = ha->pHeader; + ULONGLONG BlockTableStart; + ULONGLONG BlockTableEnd; + ULONGLONG FileDataStart; + + // Only perform this check on MPQs version 1.0 + if(pHeader->dwHeaderSize == MPQ_HEADER_SIZE_V1) + { + // Calculate claimed block table begin and end + BlockTableStart = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); + BlockTableEnd = BlockTableStart + (pHeader->dwBlockTableSize * sizeof(TMPQBlock)); + + for(DWORD i = 0; i < dwClaimedSize; i++) + { + // If the block table end goes into that file, fix the block table end + FileDataStart = ha->MpqPos + pBlockTable[i].dwFilePos; + if(BlockTableStart < FileDataStart && BlockTableEnd > FileDataStart) + { + dwClaimedSize = (DWORD)((FileDataStart - BlockTableStart) / sizeof(TMPQBlock)); + BlockTableEnd = FileDataStart; + } + } + } + + // Fix the block table size + pHeader->BlockTableSize64 = dwClaimedSize * sizeof(TMPQBlock); + pHeader->dwBlockTableSize = dwClaimedSize; +} + +TMPQBlock * LoadBlockTable(TMPQArchive * ha, ULONGLONG FileSize) +{ + TMPQHeader * pHeader = ha->pHeader; + TMPQBlock * pBlockTable; + ULONGLONG ByteOffset; + DWORD dwTableSize; + DWORD dwCmpSize; + int nError; + + // Do nothing if the block table position is zero + if(pHeader->dwBlockTablePos == 0 && pHeader->wBlockTablePosHi == 0) + return NULL; + + // Do nothing if the block table size is zero + if(pHeader->dwBlockTableSize == 0) + return NULL; + + // Sanity check, enforced by LoadAnyHashTable + assert(ha->dwMaxFileCount >= pHeader->dwBlockTableSize); + + // Calculate sizes of both tables + ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); + dwTableSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock); + dwCmpSize = (DWORD)pHeader->BlockTableSize64; + + // Allocate space for the block table + // Note: pHeader->dwBlockTableSize can be zero !!! + pBlockTable = STORM_ALLOC(TMPQBlock, ha->dwMaxFileCount); + if(pBlockTable == NULL) + return NULL; + + // Fill the block table with zeros + memset(pBlockTable, 0, dwTableSize); + + // I found a MPQ which claimed 0x200 entries in the block table, + // but the file was cut and there was only 0x1A0 entries. + // We will handle this case properly. + if(dwTableSize == dwCmpSize && (ByteOffset + dwTableSize) > FileSize) + { + pHeader->dwBlockTableSize = (DWORD)((FileSize - ByteOffset) / sizeof(TMPQBlock)); + pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock); + dwTableSize = dwCmpSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock); + } + + // + // One of the first cracked versions of Diablo I had block table unencrypted + // StormLib does NOT support such MPQs anymore, as they are incompatible + // with compressed block table feature + // + + // Load the block table + nError = LoadMpqTable(ha, ByteOffset, pBlockTable, dwCmpSize, dwTableSize, MPQ_KEY_BLOCK_TABLE); + if(nError != ERROR_SUCCESS) + { + // Failed, sorry + STORM_FREE(pBlockTable); + return NULL; + } + + // Defense against MPQs that claim block table to be bigger than it really is + FixBlockTableSize(ha, pBlockTable, pHeader->dwBlockTableSize); + return pBlockTable; } int LoadHetTable(TMPQArchive * ha) @@ -1963,19 +2068,25 @@ TMPQBetTable * LoadBetTable(TMPQArchive * ha) int LoadAnyHashTable(TMPQArchive * ha) { TMPQHeader * pHeader = ha->pHeader; - bool bHashTableLoaded = false; // If the MPQ archive is empty, don't bother trying to load anything if(pHeader->dwHashTableSize == 0 && pHeader->HetTableSize64 == 0) return CreateHashTable(ha, HASH_TABLE_SIZE_DEFAULT); - // Try to load HET table - if(LoadHetTable(ha) == ERROR_SUCCESS) - bHashTableLoaded = true; + // Try to load HET and/or classic hash table + LoadHetTable(ha); - // Try to load the classic hash table - if(LoadHashTable(ha) == ERROR_SUCCESS) - bHashTableLoaded = true; + // Load the HASH table + ha->pHashTable = LoadHashTable(ha); + + // Set the maximum file count to the size of the hash table + // In case there is HET table, we have to keep the file limit + if(ha->pHetTable == NULL) + ha->dwMaxFileCount = pHeader->dwHashTableSize; + + // Did at least one succeed? + if(ha->pHetTable == NULL && ha->pHashTable == NULL) + return ERROR_FILE_CORRUPT; // In theory, a MPQ could have bigger block table than hash table if(ha->pHeader->dwBlockTableSize > ha->dwMaxFileCount) @@ -1984,7 +2095,7 @@ int LoadAnyHashTable(TMPQArchive * ha) ha->dwFlags |= MPQ_FLAG_READ_ONLY; } - return bHashTableLoaded ? ERROR_SUCCESS : ERROR_FILE_CORRUPT; + return ERROR_SUCCESS; } int BuildFileTable_Classic( @@ -2001,118 +2112,80 @@ int BuildFileTable_Classic( // Sanity checks assert(ha->pHashTable != NULL); - // Do nothing if the size of the block table is zero - if(pHeader->dwBlockTablePos != 0 && pHeader->dwBlockTableSize != 0) + // Load the block table + pBlockTable = LoadBlockTable(ha, FileSize); + if(pBlockTable != NULL) { - // Sanity check, enforced by LoadAnyHashTable - assert(ha->dwMaxFileCount >= pHeader->dwBlockTableSize); + TMPQHash * pHashEnd = ha->pHashTable + pHeader->dwHashTableSize; + TMPQHash * pHash; - // Allocate space for the block table - // Note: pHeader->dwBlockTableSize can be zero !!! - pBlockTable = STORM_ALLOC(TMPQBlock, ha->dwMaxFileCount); - if(pBlockTable != NULL) + // If we don't have HET table, we build the file entries from the hash&block tables + if(ha->pHetTable == NULL) { - ULONGLONG ByteOffset = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); - TMPQHash * pHashEnd = ha->pHashTable + pHeader->dwHashTableSize; - TMPQHash * pHash; - DWORD dwTableSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock); - DWORD dwCmpSize = (DWORD)pHeader->BlockTableSize64; - - // Fill the block table with zeros - memset(pBlockTable, 0, dwTableSize); - - // I have found a MPQ which claimed 0x200 entries in the block table, - // but the file was cut and there was only 0x1A0 entries. - // We will handle this case properly. - if(dwTableSize == dwCmpSize && (ByteOffset + dwTableSize) > FileSize) + for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) { - pHeader->dwBlockTableSize = (DWORD)((FileSize - ByteOffset) / sizeof(TMPQBlock)); - pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock); - dwTableSize = dwCmpSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock); - } - - // - // One of the first cracked versions of Diablo I had block table unencrypted - // StormLib does NOT support such MPQs anymore, as they are incompatible - // with compressed block table feature - // - - // Load the block table - nError = LoadMpqTable(ha, ByteOffset, pBlockTable, dwCmpSize, dwTableSize, MPQ_KEY_BLOCK_TABLE); - if(nError == ERROR_SUCCESS) - { - // Defense against MPQs that claim block table to be bigger than it really is - FixBlockTableSize(ha, pBlockTable, pHeader->dwBlockTableSize); - - // If we don't have HET table, we build the file entries from the hash&block tables - if(ha->pHetTable == NULL) + if(pHash->dwBlockIndex < pHeader->dwBlockTableSize) { - for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) + pFileEntry = pFileTable + pHash->dwBlockIndex; + pBlock = pBlockTable + pHash->dwBlockIndex; + + // + // Yet another silly map protector: For each valid file, + // there are 4 items in the hash table, that appears to be valid: + // + // a6d79af0 e61a0932 001e0000 0000770b <== Fake valid + // a6d79af0 e61a0932 0000d761 0000dacb <== Fake valid + // a6d79af0 e61a0932 00000000 0000002f <== Real file entry + // a6d79af0 e61a0932 00005a4f 000093bc <== Fake valid + // + + if(!(pBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS) && (pBlock->dwFlags & MPQ_FILE_EXISTS)) { - if(pHash->dwBlockIndex < pHeader->dwBlockTableSize) - { - pFileEntry = pFileTable + pHash->dwBlockIndex; - pBlock = pBlockTable + pHash->dwBlockIndex; - - // - // Yet another silly map protector: For each valid file, - // there are 4 items in the hash table, that appears to be valid: - // - // a6d79af0 e61a0932 001e0000 0000770b <== Fake valid - // a6d79af0 e61a0932 0000d761 0000dacb <== Fake valid - // a6d79af0 e61a0932 00000000 0000002f <== Real file entry - // a6d79af0 e61a0932 00005a4f 000093bc <== Fake valid - // - - if(!(pBlock->dwFlags & ~MPQ_FILE_VALID_FLAGS) && (pBlock->dwFlags & MPQ_FILE_EXISTS)) - { - // Fill the entry - pFileEntry->ByteOffset = pBlock->dwFilePos; - pFileEntry->dwHashIndex = (DWORD)(pHash - ha->pHashTable); - pFileEntry->dwFileSize = pBlock->dwFSize; - pFileEntry->dwCmpSize = pBlock->dwCSize; - pFileEntry->dwFlags = pBlock->dwFlags; - pFileEntry->lcLocale = pHash->lcLocale; - pFileEntry->wPlatform = pHash->wPlatform; - } - else - { - // If the hash table entry doesn't point to the valid file item, - // we invalidate the entire hash table entry - pHash->dwName1 = 0xFFFFFFFF; - pHash->dwName2 = 0xFFFFFFFF; - pHash->lcLocale = 0xFFFF; - pHash->wPlatform = 0xFFFF; - pHash->dwBlockIndex = HASH_ENTRY_DELETED; - } - } + // Fill the entry + pFileEntry->ByteOffset = pBlock->dwFilePos; + pFileEntry->dwHashIndex = (DWORD)(pHash - ha->pHashTable); + pFileEntry->dwFileSize = pBlock->dwFSize; + pFileEntry->dwCmpSize = pBlock->dwCSize; + pFileEntry->dwFlags = pBlock->dwFlags; + pFileEntry->lcLocale = pHash->lcLocale; + pFileEntry->wPlatform = pHash->wPlatform; } - } - else - { - for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) + else { - if(pHash->dwBlockIndex < ha->dwFileTableSize) - { - pFileEntry = pFileTable + pHash->dwBlockIndex; - if(pFileEntry->dwFlags & MPQ_FILE_EXISTS) - { - pFileEntry->dwHashIndex = (DWORD)(pHash - ha->pHashTable); - pFileEntry->lcLocale = pHash->lcLocale; - pFileEntry->wPlatform = pHash->wPlatform; - } - } + // If the hash table entry doesn't point to the valid file item, + // we invalidate the entire hash table entry + pHash->dwName1 = 0xFFFFFFFF; + pHash->dwName2 = 0xFFFFFFFF; + pHash->lcLocale = 0xFFFF; + pHash->wPlatform = 0xFFFF; + pHash->dwBlockIndex = HASH_ENTRY_DELETED; } } } - - // Free the block table - STORM_FREE(pBlockTable); } else { - nError = ERROR_NOT_ENOUGH_MEMORY; + for(pHash = ha->pHashTable; pHash < pHashEnd; pHash++) + { + if(pHash->dwBlockIndex < ha->dwFileTableSize) + { + pFileEntry = pFileTable + pHash->dwBlockIndex; + if(pFileEntry->dwFlags & MPQ_FILE_EXISTS) + { + pFileEntry->dwHashIndex = (DWORD)(pHash - ha->pHashTable); + pFileEntry->lcLocale = pHash->lcLocale; + pFileEntry->wPlatform = pHash->wPlatform; + } + } + } } + + // Free the block table + STORM_FREE(pBlockTable); + } + else + { + nError = ERROR_NOT_ENOUGH_MEMORY; } // Load the hi-block table diff --git a/dep/StormLib/src/SCompression.cpp b/dep/StormLib/src/SCompression.cpp index 88351499ef7..5c7432248dc 100644 --- a/dep/StormLib/src/SCompression.cpp +++ b/dep/StormLib/src/SCompression.cpp @@ -175,7 +175,7 @@ void Compress_ZLIB( // Storm.dll uses zlib version 1.1.3 // Wow.exe uses zlib version 1.2.3 nResult = deflateInit2(&z, - Z_DEFAULT_COMPRESSION, + 6, // Compression level used by WoW MPQs Z_DEFLATED, windowBits, 8, @@ -292,7 +292,13 @@ static void Compress_PKLIB( Info.pbOutBuff = pbOutBuffer; Info.pbOutBuffEnd = pbOutBuffer + *pcbOutBuffer; - // Set the compression type and dictionary size + // + // Set the dictionary size + // + // Diablo I ues fixed dictionary size of CMP_IMPLODE_DICT_SIZE3 + // Starcraft uses the variable dictionary size based on algorithm below + // + if (cbInBuffer < 0x600) dict_size = CMP_IMPLODE_DICT_SIZE1; else if(0x600 <= cbInBuffer && cbInBuffer < 0xC00) @@ -455,7 +461,7 @@ static void LZMA_Callback_Free(void *p, void *address) // the data compressed by StormLib. // -static void Compress_LZMA( +/*static */ void Compress_LZMA( char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, @@ -752,13 +758,13 @@ int WINAPI SCompExplode(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffe static TCompressTable cmp_table[] = { - {MPQ_COMPRESSION_SPARSE, Compress_SPARSE}, // Sparse compression - {MPQ_COMPRESSION_WAVE_MONO, Compress_ADPCM_mono}, // IMA ADPCM mono compression - {MPQ_COMPRESSION_WAVE_STEREO, Compress_ADPCM_stereo}, // IMA ADPCM stereo compression - {MPQ_COMPRESSION_HUFFMANN, Compress_huff}, // Huffmann compression - {MPQ_COMPRESSION_ZLIB, Compress_ZLIB}, // Compression with the "zlib" library - {MPQ_COMPRESSION_PKWARE, Compress_PKLIB}, // Compression with Pkware DCL - {MPQ_COMPRESSION_BZIP2, Compress_BZIP2} // Compression Bzip2 library + {MPQ_COMPRESSION_SPARSE, Compress_SPARSE}, // Sparse compression + {MPQ_COMPRESSION_ADPCM_MONO, Compress_ADPCM_mono}, // IMA ADPCM mono compression + {MPQ_COMPRESSION_ADPCM_STEREO, Compress_ADPCM_stereo}, // IMA ADPCM stereo compression + {MPQ_COMPRESSION_HUFFMANN, Compress_huff}, // Huffmann compression + {MPQ_COMPRESSION_ZLIB, Compress_ZLIB}, // Compression with the "zlib" library + {MPQ_COMPRESSION_PKWARE, Compress_PKLIB}, // Compression with Pkware DCL + {MPQ_COMPRESSION_BZIP2, Compress_BZIP2} // Compression Bzip2 library }; int WINAPI SCompCompress( @@ -904,13 +910,13 @@ int WINAPI SCompCompress( // of compressed data static TDecompressTable dcmp_table[] = { - {MPQ_COMPRESSION_BZIP2, Decompress_BZIP2}, // Decompression with Bzip2 library - {MPQ_COMPRESSION_PKWARE, Decompress_PKLIB}, // Decompression with Pkware Data Compression Library - {MPQ_COMPRESSION_ZLIB, Decompress_ZLIB}, // Decompression with the "zlib" library - {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression - {MPQ_COMPRESSION_WAVE_STEREO, Decompress_ADPCM_stereo}, // IMA ADPCM stereo decompression - {MPQ_COMPRESSION_WAVE_MONO, Decompress_ADPCM_mono}, // IMA ADPCM mono decompression - {MPQ_COMPRESSION_SPARSE, Decompress_SPARSE} // Sparse decompression + {MPQ_COMPRESSION_BZIP2, Decompress_BZIP2}, // Decompression with Bzip2 library + {MPQ_COMPRESSION_PKWARE, Decompress_PKLIB}, // Decompression with Pkware Data Compression Library + {MPQ_COMPRESSION_ZLIB, Decompress_ZLIB}, // Decompression with the "zlib" library + {MPQ_COMPRESSION_HUFFMANN, Decompress_huff}, // Huffmann decompression + {MPQ_COMPRESSION_ADPCM_STEREO, Decompress_ADPCM_stereo}, // IMA ADPCM stereo decompression + {MPQ_COMPRESSION_ADPCM_MONO, Decompress_ADPCM_mono}, // IMA ADPCM mono decompression + {MPQ_COMPRESSION_SPARSE, Decompress_SPARSE} // Sparse decompression }; int WINAPI SCompDecompress( @@ -919,109 +925,86 @@ int WINAPI SCompDecompress( char * pbInBuffer, int cbInBuffer) { - DECOMPRESS DecompressFuncArray[0x10]; // Array of compression functions, applied sequentially char * pbWorkBuffer = NULL; // Temporary storage for decompressed data char * pbOutput = pbOutBuffer; // Where to store decompressed data char * pbInput; // Where to store decompressed data unsigned uCompressionMask; // Decompressions applied to the data + unsigned uCompressionCopy; // Decompressions applied to the data int cbOutBuffer = *pcbOutBuffer; // Current size of the output buffer int cbInLength; // Current size of the input buffer int nCompressCount = 0; // Number of compressions to be applied int nCompressIndex = 0; int nResult = 1; - // Zero input data bring zero output data - if(cbInBuffer == 0) - { - *pcbOutBuffer = 0; - return 1; - } + // Verify buffer sizes + if(cbOutBuffer < cbInBuffer || cbInBuffer < 1) + return 0; -/* // If the input length is the same as output length, do nothing. - // Unfortunately, some data in WoW-Cataclysm BETA MPQs are like that .... - if(cbInBuffer == cbOutBuffer) + if(cbOutBuffer == cbInBuffer) { // If the buffers are equal, don't copy anything. - if(pbInBuffer == pbOutBuffer) - return 1; - - memcpy(pbOutBuffer, pbInBuffer, cbInBuffer); + if(pbInBuffer != pbOutBuffer) + memcpy(pbOutBuffer, pbInBuffer, cbInBuffer); return 1; } -*/ // Get applied compression types and decrement data length - uCompressionMask = (unsigned char)*pbInBuffer++; + uCompressionMask = uCompressionCopy = (unsigned char)*pbInBuffer++; cbInBuffer--; // Get current compressed data and length of it pbInput = pbInBuffer; cbInLength = cbInBuffer; - // - // Beginning with Starcraft II, the decompression byte can no longer contain - // any arbitrary combination types. Instead, it can be one of the few - // pre-set values (0x02, 0x08, 0x10, 0x12, 0x20, 0x22, 0x30) - // Note that Starcraft II no longer uses WAVE files, so compressions 0x41, 0x48, 0x81, 0x88 - // are no longer used. - // + // This compression function doesn't support LZMA + assert(uCompressionMask != MPQ_COMPRESSION_LZMA); - // Special case: LZMA decompression (added in Starcraft II) - if(uCompressionMask == MPQ_COMPRESSION_LZMA) + // Parse the compression mask + for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++) { - DecompressFuncArray[0] = Decompress_LZMA; - nCompressCount = 1; - } - else - { - // Fill the compressions array - for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++) + // If the mask agrees, insert the compression function to the array + if(uCompressionMask & dcmp_table[i].uMask) { - // If the mask agrees, insert the compression function to the array - if(uCompressionMask & dcmp_table[i].uMask) - { - DecompressFuncArray[nCompressCount] = dcmp_table[i].Decompress; - uCompressionMask &= ~dcmp_table[i].uMask; - nCompressCount++; - } + uCompressionCopy &= ~dcmp_table[i].uMask; + nCompressCount++; } + } - // If at least one of the compressions remaing unknown, return an error - if(uCompressionMask != 0) - { - SetLastError(ERROR_NOT_SUPPORTED); - return 0; - } + // If at least one of the compressions remaing unknown, return an error + if(nCompressCount == 0 || uCompressionCopy != 0) + { + SetLastError(ERROR_NOT_SUPPORTED); + return 0; } - // If there is at least one decompression, do it - if(nCompressCount > 0) + // If there is more than one compression, we have to allocate extra buffer + if(nCompressCount > 1) { - // If there is more than one compression, we have to allocate extra buffer - if(nCompressCount > 1) + pbWorkBuffer = STORM_ALLOC(char, cbOutBuffer); + if(pbWorkBuffer == NULL) { - pbWorkBuffer = STORM_ALLOC(char, *pcbOutBuffer); - if(pbWorkBuffer == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; } + } - // Get the current compression index - nCompressIndex = nCompressCount - 1; + // Get the current compression index + nCompressIndex = nCompressCount - 1; - // Apply all decompressions - for(int i = 0; i < nCompressCount; i++) + // Apply all decompressions + for(size_t i = 0; i < (sizeof(dcmp_table) / sizeof(TDecompressTable)); i++) + { + // Perform the (next) decompression + if(uCompressionMask & dcmp_table[i].uMask) { // Get the correct output buffer pbOutput = (nCompressIndex & 1) ? pbWorkBuffer : pbOutBuffer; nCompressIndex--; - - // Perform the (next) decompression + + // Perform the decompression cbOutBuffer = *pcbOutBuffer; - nResult = DecompressFuncArray[i](pbOutput, &cbOutBuffer, pbInput, cbInLength); + nResult = dcmp_table[i].Decompress(pbOutput, &cbOutBuffer, pbInput, cbInLength); if(nResult == 0 || cbOutBuffer == 0) { SetLastError(ERROR_FILE_CORRUPT); @@ -1030,21 +1013,123 @@ int WINAPI SCompDecompress( } // Switch buffers - pbInput = pbOutput; cbInLength = cbOutBuffer; + pbInput = pbOutput; } + } + + // Put the length of the decompressed data to the output buffer + *pcbOutBuffer = cbOutBuffer; + + // Cleanup and return + if(pbWorkBuffer != NULL) + STORM_FREE(pbWorkBuffer); + return nResult; +} + +int WINAPI SCompDecompress2( + char * pbOutBuffer, + int * pcbOutBuffer, + char * pbInBuffer, + int cbInBuffer) +{ + DECOMPRESS pfnDecompress1 = NULL; + DECOMPRESS pfnDecompress2 = NULL; + char * pbWorkBuffer = pbOutBuffer; + int cbWorkBuffer = *pcbOutBuffer; + int nResult; + char CompressionMethod; + + // Verify buffer sizes + if(*pcbOutBuffer < cbInBuffer || cbInBuffer < 1) + return 0; - // Put the length of the decompressed data to the output buffer - *pcbOutBuffer = cbOutBuffer; + // If the outputbuffer is as big as input buffer, just copy the block + if(*pcbOutBuffer == cbInBuffer) + { + if(pbOutBuffer != pbInBuffer) + memcpy(pbOutBuffer, pbInBuffer, cbInBuffer); + return 1; } - else + + // Get the compression methods + CompressionMethod = *pbInBuffer++; + cbInBuffer--; + + // We only recognize a fixed set of compression methods + switch((unsigned char)CompressionMethod) { - memcpy(pbOutBuffer, pbInBuffer, cbInBuffer); - *pcbOutBuffer = cbInBuffer; + case MPQ_COMPRESSION_ZLIB: + pfnDecompress1 = Decompress_ZLIB; + break; + + case MPQ_COMPRESSION_PKWARE: + pfnDecompress1 = Decompress_PKLIB; + break; + + case MPQ_COMPRESSION_BZIP2: + pfnDecompress1 = Decompress_BZIP2; + break; + + case MPQ_COMPRESSION_LZMA: + pfnDecompress1 = Decompress_LZMA; + break; + + case MPQ_COMPRESSION_SPARSE: + pfnDecompress1 = Decompress_SPARSE; + break; + + case (MPQ_COMPRESSION_SPARSE | MPQ_COMPRESSION_ZLIB): + pfnDecompress1 = Decompress_ZLIB; + pfnDecompress2 = Decompress_SPARSE; + break; + + case (MPQ_COMPRESSION_SPARSE | MPQ_COMPRESSION_BZIP2): + pfnDecompress1 = Decompress_BZIP2; + pfnDecompress2 = Decompress_SPARSE; + break; + + // + // Note: Any combination including MPQ_COMPRESSION_ADPCM_MONO, + // MPQ_COMPRESSION_ADPCM_STEREO or MPQ_COMPRESSION_HUFFMANN + // is not supported by newer MPQs. + // + + default: + SetLastError(ERROR_FILE_CORRUPT); + return 0; } - // Cleanup and return - if(pbWorkBuffer != NULL) + // If we have to use two decompressions, allocate temporary buffer + if(pfnDecompress2 != NULL) + { + pbWorkBuffer = STORM_ALLOC(char, *pcbOutBuffer); + if(pbWorkBuffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + + // Apply the first decompression method + nResult = pfnDecompress1(pbWorkBuffer, &cbWorkBuffer, pbInBuffer, cbInBuffer); + + // Apply the second decompression method, if any + if(pfnDecompress2 != NULL && nResult != 0) + { + cbInBuffer = cbWorkBuffer; + cbWorkBuffer = *pcbOutBuffer; + nResult = pfnDecompress2(pbOutBuffer, &cbWorkBuffer, pbWorkBuffer, cbInBuffer); + } + + // Supply the output buffer size + *pcbOutBuffer = cbWorkBuffer; + + // Free temporary buffer + if(pbWorkBuffer != pbOutBuffer) STORM_FREE(pbWorkBuffer); + + if(nResult == 0) + SetLastError(ERROR_FILE_CORRUPT); return nResult; } diff --git a/dep/StormLib/src/SFileAddFile.cpp b/dep/StormLib/src/SFileAddFile.cpp index e908d644990..dda47370bd1 100644 --- a/dep/StormLib/src/SFileAddFile.cpp +++ b/dep/StormLib/src/SFileAddFile.cpp @@ -13,6 +13,33 @@ #include "StormCommon.h" //----------------------------------------------------------------------------- +// Local structures + +#define FILE_SIGNATURE_RIFF 0x46464952 +#define FILE_SIGNATURE_WAVE 0x45564157 +#define FILE_SIGNATURE_FMT 0x20746D66 +#define AUDIO_FORMAT_PCM 1 + +typedef struct _WAVE_FILE_HEADER +{ + DWORD dwChunkId; // 0x52494646 ("RIFF") + DWORD dwChunkSize; // Size of that chunk, in bytes + DWORD dwFormat; // Must be 0x57415645 ("WAVE") + + // Format sub-chunk + DWORD dwSubChunk1Id; // 0x666d7420 ("fmt ") + DWORD dwSubChunk1Size; // 0x16 for PCM + USHORT wAudioFormat; // 1 = PCM. Other value means some sort of compression + USHORT wChannels; // Number of channels + DWORD dwSampleRate; // 8000, 44100, etc. + DWORD dwBytesRate; // SampleRate * NumChannels * BitsPerSample/8 + USHORT wBlockAlign; // NumChannels * BitsPerSample/8 + USHORT wBitsPerSample; // 8 bits = 8, 16 bits = 16, etc. + + // Followed by "data" sub-chunk (we don't care) +} WAVE_FILE_HEADER, *PWAVE_FILE_HEADER; + +//----------------------------------------------------------------------------- // Local variables // Data compression for SFileAddFile @@ -27,6 +54,29 @@ static void * pvUserData = NULL; #define LOSSY_COMPRESSION_MASK (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN) +static int IsWaveFile( + LPBYTE pbFileData, + DWORD cbFileData, + LPDWORD pdwChannels) +{ + PWAVE_FILE_HEADER pWaveHdr = (PWAVE_FILE_HEADER)pbFileData; + + if(cbFileData > sizeof(WAVE_FILE_HEADER)) + { + if(pWaveHdr->dwChunkId == FILE_SIGNATURE_RIFF && pWaveHdr->dwFormat == FILE_SIGNATURE_WAVE) + { + if(pWaveHdr->dwSubChunk1Id == FILE_SIGNATURE_FMT && pWaveHdr->wAudioFormat == AUDIO_FORMAT_PCM) + { + *pdwChannels = pWaveHdr->wChannels; + return true; + } + } + } + + return false; +} + + static int WriteDataToMpqFile( TMPQArchive * ha, TMPQFile * hf, @@ -86,16 +136,6 @@ static int WriteDataToMpqFile( // Set the position in the file ByteOffset = hf->RawFilePos + pFileEntry->dwCmpSize; - // If the file is compressed, allocate buffer for the compressed data. - // Note that we allocate buffer that is a bit longer than sector size, - // for case if the compression method performs a buffer overrun - if((pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) && pbCompressed == NULL) - { - pbToWrite = pbCompressed = STORM_ALLOC(BYTE, hf->dwSectorSize + 0x100); - if(pbCompressed == NULL) - nError = ERROR_NOT_ENOUGH_MEMORY; - } - // Update CRC32 and MD5 of the file md5_process((hash_state *)hf->hctx, hf->pbFileSector, dwBytesInSector); hf->dwCrc32 = crc32(hf->dwCrc32, hf->pbFileSector, dwBytesInSector); @@ -106,7 +146,18 @@ static int WriteDataToMpqFile( int nOutBuffer = (int)dwBytesInSector; int nInBuffer = (int)dwBytesInSector; - assert(pbCompressed != NULL); + // If the file is compressed, allocate buffer for the compressed data. + // Note that we allocate buffer that is a bit longer than sector size, + // for case if the compression method performs a buffer overrun + if(pbCompressed == NULL) + { + pbToWrite = pbCompressed = STORM_ALLOC(BYTE, hf->dwSectorSize + 0x100); + if(pbCompressed == NULL) + { + nError = ERROR_NOT_ENOUGH_MEMORY; + break; + } + } // // Note that both SCompImplode and SCompCompress give original buffer, @@ -319,11 +370,17 @@ int SFileAddFile_Init( // flags get to this point // - // Adjust file flags for too-small files - if(dwFileSize < 0x04) - dwFlags &= ~(MPQ_FILE_ENCRYPTED | MPQ_FILE_FIX_KEY); - if(dwFileSize < 0x20) - dwFlags &= ~(MPQ_FILE_COMPRESSED | MPQ_FILE_SECTOR_CRC); + // Sestor CRC is not allowed with single unit files + if(dwFlags & MPQ_FILE_SINGLE_UNIT) + dwFlags &= ~MPQ_FILE_SECTOR_CRC; + + // Sector CRC is not allowed if the file is not compressed + if(!(dwFlags & MPQ_FILE_COMPRESSED)) + dwFlags &= ~MPQ_FILE_SECTOR_CRC; + + // Fix Key is not allowed if the file is not enrypted + if(!(dwFlags & MPQ_FILE_ENCRYPTED)) + dwFlags &= ~MPQ_FILE_FIX_KEY; // If the MPQ is of version 3.0 or higher, we ignore file locale. // This is because HET and BET tables have no known support for it @@ -371,12 +428,9 @@ int SFileAddFile_Init( } else { - // If the file is marked as deleted, it's OK - if(!(pFileEntry->dwFlags & MPQ_FILE_DELETE_MARKER)) - { - if((dwFlags & MPQ_FILE_REPLACEEXISTING) == 0) - nError = ERROR_ALREADY_EXISTS; - } + // If the file exists and "replace existing" is not set, fail it + if((dwFlags & MPQ_FILE_REPLACEEXISTING) == 0) + nError = ERROR_ALREADY_EXISTS; // If the file entry already contains a file // and it is a pseudo-name, replace it @@ -459,7 +513,7 @@ int SFileAddFile_Write(TMPQFile * hf, const void * pvData, DWORD dwSize, DWORD d } // Allocate patch info, if the data is patch - if(hf->pPatchInfo == NULL && IsPatchData(pvData, dwSize, &hf->dwPatchedFileSize)) + if(hf->pPatchInfo == NULL && IsIncrementalPatchFile(pvData, dwSize, &hf->dwPatchedFileSize)) { // Set the MPQ_FILE_PATCH_FILE flag hf->pFileEntry->dwFlags |= MPQ_FILE_PATCH_FILE; @@ -782,6 +836,9 @@ bool WINAPI SFileAddFileEx( DWORD dwBytesRemaining = 0; DWORD dwBytesToRead; DWORD dwSectorSize = 0x1000; + DWORD dwChannels = 0; + bool bIsAdpcmCompression = false; + bool bIsFirstSector = true; int nError = ERROR_SUCCESS; // Check parameters @@ -791,7 +848,7 @@ bool WINAPI SFileAddFileEx( // Open added file if(nError == ERROR_SUCCESS) { - pStream = FileStream_OpenFile(szFileName, false); + pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); if(pStream == NULL) nError = GetLastError(); } @@ -799,7 +856,7 @@ bool WINAPI SFileAddFileEx( // Get the file size and file time if(nError == ERROR_SUCCESS) { - FileStream_GetLastWriteTime(pStream, &FileTime); + FileStream_GetTime(pStream, &FileTime); FileStream_GetSize(pStream, FileSize); // Files bigger than 4GB cannot be added to MPQ @@ -821,16 +878,19 @@ bool WINAPI SFileAddFileEx( { // When the compression for next blocks is set to default, // we will copy the compression for the first sector - if(dwCompressionNext == 0xFFFFFFFF) + if(dwCompressionNext == MPQ_COMPRESSION_NEXT_SAME) dwCompressionNext = dwCompression; - // If the caller wants ADPCM compression, we make sure that the first sector is not - // compressed with lossy compression - if(dwCompressionNext & (MPQ_COMPRESSION_WAVE_MONO | MPQ_COMPRESSION_WAVE_STEREO)) + // If the caller wants ADPCM compression, we make sure + // that the first sector is not compressed with lossy compression + if(dwCompressionNext & (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO)) { // The first compression must not be WAVE - if(dwCompression & (MPQ_COMPRESSION_WAVE_MONO | MPQ_COMPRESSION_WAVE_STEREO)) + if(dwCompression & (MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO)) dwCompression = MPQ_COMPRESSION_PKWARE; + + dwCompressionNext &= ~(MPQ_COMPRESSION_ADPCM_MONO | MPQ_COMPRESSION_ADPCM_STEREO); + bIsAdpcmCompression = true; } // Initiate adding file to the MPQ @@ -853,6 +913,21 @@ bool WINAPI SFileAddFileEx( break; } + // If the file being added is a WAVE file, we check number of channels + if(bIsFirstSector && bIsAdpcmCompression) + { + // The file must really be a wave file, otherwise it's data corruption + if(!IsWaveFile(pbFileData, dwBytesToRead, &dwChannels)) + { + nError = ERROR_BAD_FORMAT; + break; + } + + // Setup the compression according to number of channels + dwCompressionNext |= (dwChannels == 1) ? MPQ_COMPRESSION_ADPCM_MONO : MPQ_COMPRESSION_ADPCM_STEREO; + bIsFirstSector = false; + } + // Add the file sectors to the MPQ if(!SFileWriteFile(hMpqFile, pbFileData, dwBytesToRead, dwCompression)) { @@ -920,12 +995,12 @@ bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szA case MPQ_WAVE_QUALITY_MEDIUM: // WaveCompressionLevel = 4; - dwCompression = MPQ_COMPRESSION_WAVE_STEREO | MPQ_COMPRESSION_HUFFMANN; + dwCompression = MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN; break; case MPQ_WAVE_QUALITY_LOW: // WaveCompressionLevel = 2; - dwCompression = MPQ_COMPRESSION_WAVE_STEREO | MPQ_COMPRESSION_HUFFMANN; + dwCompression = MPQ_COMPRESSION_ADPCM_STEREO | MPQ_COMPRESSION_HUFFMANN; break; } diff --git a/dep/StormLib/src/SFileAttributes.cpp b/dep/StormLib/src/SFileAttributes.cpp index 091950885c8..0f056088fa3 100644 --- a/dep/StormLib/src/SFileAttributes.cpp +++ b/dep/StormLib/src/SFileAttributes.cpp @@ -23,6 +23,7 @@ typedef struct _MPQ_ATTRIBUTES_HEADER // Followed by an array of CRC32 // Followed by an array of file times // Followed by an array of MD5 + // Followed by an array of patch bits } MPQ_ATTRIBUTES_HEADER, *PMPQ_ATTRIBUTES_HEADER; //----------------------------------------------------------------------------- @@ -147,6 +148,40 @@ int SAttrLoadAttributes(TMPQArchive * ha) nError = ERROR_NOT_ENOUGH_MEMORY; } + // Read the patch bit for each file + if(nError == ERROR_SUCCESS && (AttrHeader.dwFlags & MPQ_ATTRIBUTE_PATCH_BIT)) + { + LPBYTE pbBitArray; + DWORD dwByteSize = ((dwBlockTableSize - 1) / 8) + 1; + + pbBitArray = STORM_ALLOC(BYTE, dwByteSize); + if(pbBitArray != NULL) + { + SFileReadFile(hFile, pbBitArray, dwByteSize, &dwBytesRead, NULL); + if(dwBytesRead == dwByteSize) + { + for(i = 0; i < dwBlockTableSize; i++) + { + DWORD dwByteIndex = i / 8; + DWORD dwBitMask = 0x80 >> (i & 7); + + // Is the appropriate bit set? + if(pbBitArray[dwByteIndex] & dwBitMask) + { + // At the moment, we assume that the patch bit is present + // in both file table and (attributes) + assert((ha->pFileTable[i].dwFlags & MPQ_FILE_PATCH_FILE) != 0); + ha->pFileTable[i].dwFlags |= MPQ_FILE_PATCH_FILE; + } + } + } + else + nError = ERROR_FILE_CORRUPT; + + STORM_FREE(pbBitArray); + } + } + // // Note: Version 7.00 of StormLib saved the (attributes) incorrectly. // Sometimes, number of entries in the (attributes) was 1 item less @@ -174,6 +209,19 @@ int SAttrFileSaveToMpq(TMPQArchive * ha) DWORD i; int nError = ERROR_SUCCESS; + // Now we have to check if we need patch bits in the (attributes) + if(nError == ERROR_SUCCESS) + { + for(i = 0; i < ha->dwFileTableSize; i++) + { + if(ha->pFileTable[i].dwFlags & MPQ_FILE_PATCH_FILE) + { + ha->dwAttrFlags |= MPQ_ATTRIBUTE_PATCH_BIT; + break; + } + } + } + // If the (attributes) is not in the file table yet, // we have to increase the final block table size pFileEntry = GetFileEntryExact(ha, ATTRIBUTES_NAME, LANG_NEUTRAL); @@ -210,15 +258,20 @@ int SAttrFileSaveToMpq(TMPQArchive * ha) dwFileSize += dwFinalBlockTableSize * sizeof(ULONGLONG); if(ha->dwAttrFlags & MPQ_ATTRIBUTE_MD5) dwFileSize += dwFinalBlockTableSize * MD5_DIGEST_SIZE; + if(ha->dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT) + dwFileSize += ((dwFinalBlockTableSize - 1)) / 8 + 1; } + // Determine the flags for (attributes) + if(ha->dwFileFlags2 == 0) + ha->dwFileFlags2 = GetDefaultSpecialFileFlags(ha, dwFileSize); + // Create the attributes file in the MPQ - assert(ha->dwFileFlags2 != 0); nError = SFileAddFile_Init(ha, ATTRIBUTES_NAME, 0, dwFileSize, LANG_NEUTRAL, - ha->dwFileFlags2, + ha->dwFileFlags2 | MPQ_FILE_REPLACEEXISTING, &hf); // Write all parts of the (attributes) file @@ -226,8 +279,9 @@ int SAttrFileSaveToMpq(TMPQArchive * ha) { assert(ha->dwFileTableSize == dwFinalBlockTableSize); + // Note that we don't know what the new bit (0x08) means. AttrHeader.dwVersion = BSWAP_INT32_UNSIGNED(100); - AttrHeader.dwFlags = BSWAP_INT32_UNSIGNED(ha->dwAttrFlags); + AttrHeader.dwFlags = BSWAP_INT32_UNSIGNED((ha->dwAttrFlags & MPQ_ATTRIBUTE_ALL)); dwToWrite = sizeof(MPQ_ATTRIBUTES_HEADER); nError = SFileAddFile_Write(hf, &AttrHeader, dwToWrite, MPQ_COMPRESSION_ZLIB); } @@ -283,6 +337,30 @@ int SAttrFileSaveToMpq(TMPQArchive * ha) } } + // Write the array of patch bits + if(nError == ERROR_SUCCESS && (ha->dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)) + { + LPBYTE pbBitArray; + DWORD dwByteSize = ((ha->dwFileTableSize - 1) / 8) + 1; + + pbBitArray = STORM_ALLOC(BYTE, dwByteSize); + if(pbBitArray != NULL) + { + memset(pbBitArray, 0, dwByteSize); + for(i = 0; i < ha->dwFileTableSize; i++) + { + DWORD dwByteIndex = i / 8; + DWORD dwBitMask = 0x80 >> (i & 7); + + if(ha->pFileTable[i].dwFlags & MPQ_FILE_PATCH_FILE) + pbBitArray[dwByteIndex] |= dwBitMask; + } + + nError = SFileAddFile_Write(hf, pbBitArray, dwByteSize, MPQ_COMPRESSION_ZLIB); + STORM_FREE(pbBitArray); + } + } + // Finalize the file in the archive if(hf != NULL) { diff --git a/dep/StormLib/src/SFileCompactArchive.cpp b/dep/StormLib/src/SFileCompactArchive.cpp index 09cb179bd74..319108b08f4 100644 --- a/dep/StormLib/src/SFileCompactArchive.cpp +++ b/dep/StormLib/src/SFileCompactArchive.cpp @@ -194,6 +194,7 @@ static int CopyMpqFileSectors( if(!FileStream_Write(pNewStream, NULL, SectorOffsetsCopy, dwSectorOffsLen)) nError = GetLastError(); + dwBytesToCopy -= dwSectorOffsLen; dwCmpSize += dwSectorOffsLen; } @@ -216,10 +217,6 @@ static int CopyMpqFileSectors( DWORD dwRawDataInSector = hf->dwSectorSize; DWORD dwRawByteOffset = dwSector * hf->dwSectorSize; - // Last sector: If there is not enough bytes remaining in the file, cut the raw size - if(dwRawDataInSector > dwBytesToCopy) - dwRawDataInSector = dwBytesToCopy; - // Fix the raw data length if the file is compressed if(hf->SectorOffsets != NULL) { @@ -227,6 +224,10 @@ static int CopyMpqFileSectors( dwRawByteOffset = hf->SectorOffsets[dwSector]; } + // Last sector: If there is not enough bytes remaining in the file, cut the raw size + if(dwRawDataInSector > dwBytesToCopy) + dwRawDataInSector = dwBytesToCopy; + // Calculate the raw file offset of the file sector CalculateRawSectorOffset(RawFilePos, hf, dwRawByteOffset); @@ -263,7 +264,7 @@ static int CopyMpqFileSectors( } // Adjust byte counts - dwBytesToCopy -= hf->dwSectorSize; + dwBytesToCopy -= dwRawDataInSector; dwCmpSize += dwRawDataInSector; } } @@ -291,10 +292,39 @@ static int CopyMpqFileSectors( } // Size of the CRC block is also included in the compressed file size + dwBytesToCopy -= dwCrcLength; dwCmpSize += dwCrcLength; } } + // There might be extra data beyond sector checksum table + // Sometimes, these data are even part of sector offset table + // Examples: + // 2012 - WoW\15354\locale-enGB.MPQ:DBFilesClient\SpellLevels.dbc + // 2012 - WoW\15354\locale-enGB.MPQ:Interface\AddOns\Blizzard_AuctionUI\Blizzard_AuctionUI.xml + if(nError == ERROR_SUCCESS && dwBytesToCopy != 0) + { + LPBYTE pbExtraData; + + // Allocate space for the extra data + pbExtraData = STORM_ALLOC(BYTE, dwBytesToCopy); + if(pbExtraData != NULL) + { + if(!FileStream_Read(ha->pStream, NULL, pbExtraData, dwBytesToCopy)) + nError = GetLastError(); + + if(!FileStream_Write(pNewStream, NULL, pbExtraData, dwBytesToCopy)) + nError = GetLastError(); + + // Include these extra data in the compressed size + dwCmpSize += dwBytesToCopy; + dwBytesToCopy = 0; + STORM_FREE(pbExtraData); + } + else + nError = ERROR_NOT_ENOUGH_MEMORY; + } + // Write the MD5's of the raw file data, if needed if(nError == ERROR_SUCCESS && ha->pHeader->dwRawChunkSize != 0) { @@ -469,13 +499,13 @@ bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile, bool /* bR // Get the temporary file name and create it if(nError == ERROR_SUCCESS) { - _tcscpy(szTempFile, ha->pStream->szFileName); + _tcscpy(szTempFile, FileStream_GetFileName(ha->pStream)); if((szTemp = _tcsrchr(szTempFile, '.')) != NULL) _tcscpy(szTemp + 1, _T("mp_")); else _tcscat(szTempFile, _T("_")); - pTempStream = FileStream_CreateFile(szTempFile); + pTempStream = FileStream_CreateFile(szTempFile, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); if(pTempStream == NULL) nError = GetLastError(); } @@ -531,7 +561,7 @@ bool WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile, bool /* bR // If succeeded, switch the streams if(nError == ERROR_SUCCESS) { - if(FileStream_MoveFile(ha->pStream, pTempStream)) + if(FileStream_Switch(ha->pStream, pTempStream)) pTempStream = NULL; else nError = ERROR_CAN_NOT_COMPLETE; diff --git a/dep/StormLib/src/SFileCreateArchive.cpp b/dep/StormLib/src/SFileCreateArchive.cpp index 6e8be7c46ec..59f3d3fa9e8 100644 --- a/dep/StormLib/src/SFileCreateArchive.cpp +++ b/dep/StormLib/src/SFileCreateArchive.cpp @@ -68,17 +68,46 @@ static int WriteNakedMPQHeader(TMPQArchive * ha) bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq) { + SFILE_CREATE_MPQ CreateInfo; + + // Fill the create structure + memset(&CreateInfo, 0, sizeof(SFILE_CREATE_MPQ)); + CreateInfo.cbSize = sizeof(SFILE_CREATE_MPQ); + CreateInfo.dwMpqVersion = (dwFlags & MPQ_CREATE_ARCHIVE_VMASK) >> FLAGS_TO_FORMAT_SHIFT; + CreateInfo.dwStreamFlags = STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE; + CreateInfo.dwAttrFlags = (dwFlags & MPQ_CREATE_ATTRIBUTES) ? MPQ_ATTRIBUTE_ALL : 0; + CreateInfo.dwSectorSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_3) ? 0x4000 : 0x1000; + CreateInfo.dwRawChunkSize = (CreateInfo.dwMpqVersion >= MPQ_FORMAT_VERSION_4) ? 0x4000 : 0; + CreateInfo.dwMaxFileCount = dwMaxFileCount; + return SFileCreateArchive2(szMpqName, &CreateInfo, phMpq); +} + +bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq) +{ TFileStream * pStream = NULL; // File stream TMPQArchive * ha = NULL; // MPQ archive handle ULONGLONG MpqPos = 0; // Position of MPQ header in the file HANDLE hMpq = NULL; - USHORT wFormatVersion = MPQ_FORMAT_VERSION_1; DWORD dwBlockTableSize = 0; // Initial block table size DWORD dwHashTableSize = 0; + DWORD dwMaxFileCount; int nError = ERROR_SUCCESS; // Check the parameters, if they are valid - if(szMpqName == NULL || *szMpqName == 0 || phMpq == NULL) + if(szMpqName == NULL || *szMpqName == 0 || pCreateInfo == NULL || phMpq == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + // Verify if all variables in SFILE_CREATE_MPQ are correct + if((pCreateInfo->cbSize == 0 || pCreateInfo->cbSize > sizeof(SFILE_CREATE_MPQ)) || + (pCreateInfo->dwMpqVersion > MPQ_FORMAT_VERSION_4) || + (pCreateInfo->pvUserData != NULL || pCreateInfo->cbUserData != 0) || + (pCreateInfo->dwAttrFlags & ~MPQ_ATTRIBUTE_ALL) || + (pCreateInfo->dwSectorSize & (pCreateInfo->dwSectorSize - 1)) || + (pCreateInfo->dwRawChunkSize & (pCreateInfo->dwRawChunkSize - 1)) || + (pCreateInfo->dwMaxFileCount < 4)) { SetLastError(ERROR_INVALID_PARAMETER); return false; @@ -89,7 +118,7 @@ bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwM // We verify if the file already exists and if it's a MPQ archive. // If yes, we won't allow to overwrite it. - if(SFileOpenArchive(szMpqName, 0, dwFlags, &hMpq)) + if(SFileOpenArchive(szMpqName, 0, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE | MPQ_OPEN_NO_ATTRIBUTES | MPQ_OPEN_NO_LISTFILE, &hMpq)) { SFileCloseArchive(hMpq); SetLastError(ERROR_ALREADY_EXISTS); @@ -102,25 +131,18 @@ bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwM // - If the file doesn't exist, create new empty file // - pStream = FileStream_OpenFile(szMpqName, true); + pStream = FileStream_OpenFile(szMpqName, pCreateInfo->dwStreamFlags); if(pStream == NULL) { - pStream = FileStream_CreateFile(szMpqName); + pStream = FileStream_CreateFile(szMpqName, pCreateInfo->dwStreamFlags); if(pStream == NULL) return false; } - // Decide what format to use - wFormatVersion = (USHORT)((dwFlags & MPQ_CREATE_ARCHIVE_VMASK) >> 16); - if(wFormatVersion > MPQ_FORMAT_VERSION_4) - { - SetLastError(ERROR_INVALID_PARAMETER); - return false; - } - // Increment the maximum amount of files to have space // for listfile and attributes file - if(dwFlags & MPQ_CREATE_ATTRIBUTES) + dwMaxFileCount = pCreateInfo->dwMaxFileCount; + if(pCreateInfo->dwAttrFlags != 0) dwMaxFileCount++; dwMaxFileCount++; @@ -150,19 +172,18 @@ bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwM { memset(ha, 0, sizeof(TMPQArchive)); ha->pStream = pStream; - ha->dwSectorSize = (wFormatVersion >= MPQ_FORMAT_VERSION_3) ? 0x4000 : 0x1000; + ha->dwSectorSize = pCreateInfo->dwSectorSize; ha->UserDataPos = MpqPos; ha->MpqPos = MpqPos; ha->pHeader = (TMPQHeader *)ha->HeaderData; ha->dwMaxFileCount = dwMaxFileCount; ha->dwFileTableSize = 0; - ha->dwFileFlags1 = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING; - ha->dwFileFlags2 = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING; + ha->dwFileFlags1 = pCreateInfo->dwFileFlags1; + ha->dwFileFlags2 = pCreateInfo->dwFileFlags2; ha->dwFlags = 0; // Setup the attributes - if(dwFlags & MPQ_CREATE_ATTRIBUTES) - ha->dwAttrFlags = MPQ_ATTRIBUTE_CRC32 | MPQ_ATTRIBUTE_FILETIME | MPQ_ATTRIBUTE_MD5; + ha->dwAttrFlags = pCreateInfo->dwAttrFlags; pStream = NULL; } @@ -174,9 +195,9 @@ bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwM // Fill the MPQ header memset(pHeader, 0, sizeof(ha->HeaderData)); pHeader->dwID = ID_MPQ; - pHeader->dwHeaderSize = MpqHeaderSizes[wFormatVersion]; + pHeader->dwHeaderSize = MpqHeaderSizes[pCreateInfo->dwMpqVersion]; pHeader->dwArchiveSize = pHeader->dwHeaderSize + dwHashTableSize * sizeof(TMPQHash); - pHeader->wFormatVersion = wFormatVersion; + pHeader->wFormatVersion = (USHORT)pCreateInfo->dwMpqVersion; pHeader->wSectorSize = GetSectorSizeShift(ha->dwSectorSize); pHeader->dwHashTablePos = pHeader->dwHeaderSize; pHeader->dwHashTableSize = dwHashTableSize; @@ -185,8 +206,8 @@ bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwM // For MPQs version 4 and higher, we set the size of raw data block // for calculating MD5 - if(wFormatVersion >= MPQ_FORMAT_VERSION_4) - pHeader->dwRawChunkSize = 0x4000; + if(pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_4) + pHeader->dwRawChunkSize = pCreateInfo->dwRawChunkSize; // Write the naked MPQ header nError = WriteNakedMPQHeader(ha); @@ -196,7 +217,7 @@ bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwM } // Create initial HET table, if the caller required an MPQ format 3.0 or newer - if(nError == ERROR_SUCCESS && wFormatVersion >= MPQ_FORMAT_VERSION_3) + if(nError == ERROR_SUCCESS && pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_3) { ha->pHetTable = CreateHetTable(ha->dwMaxFileCount, 0x40, true); if(ha->pHetTable == NULL) diff --git a/dep/StormLib/src/SFileExtractFile.cpp b/dep/StormLib/src/SFileExtractFile.cpp index f46ef178fbc..c8053ed4e62 100644 --- a/dep/StormLib/src/SFileExtractFile.cpp +++ b/dep/StormLib/src/SFileExtractFile.cpp @@ -28,7 +28,7 @@ bool WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const TCHAR // Create the local file if(nError == ERROR_SUCCESS) { - pLocalFile = FileStream_CreateFile(szExtracted); + pLocalFile = FileStream_CreateFile(szExtracted, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); if(pLocalFile == NULL) nError = GetLastError(); } diff --git a/dep/StormLib/src/SFileFindFile.cpp b/dep/StormLib/src/SFileFindFile.cpp index 542637b3668..337be7d2c54 100644 --- a/dep/StormLib/src/SFileFindFile.cpp +++ b/dep/StormLib/src/SFileFindFile.cpp @@ -31,7 +31,7 @@ struct TMPQSearch DWORD dwSearchTableItems; // Number of items in the search table DWORD dwNextIndex; // Next file index to be checked DWORD dwFlagMask; // For checking flag mask - char * szSearchMask; // Search mask (variable length) + char szSearchMask[1]; // Search mask (variable length) }; //----------------------------------------------------------------------------- @@ -69,7 +69,7 @@ bool CheckWildCard(const char * szString, const char * szWildCard) szString++; } - // If there is '*', means zero or more chars. We have to + // If there is '*', means zero or more chars. We have to // find the sequence after '*' if(*szWildCard == '*') { @@ -337,8 +337,6 @@ static void FreeMPQSearch(TMPQSearch *& hs) { if(hs->pSearchTable != NULL) STORM_FREE(hs->pSearchTable); - if(hs->szSearchMask != NULL) - free(hs->szSearchMask); // allocated with strdup STORM_FREE(hs); hs = NULL; } @@ -378,7 +376,7 @@ HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DA if(nError == ERROR_SUCCESS) { memset(hs, 0, sizeof(TMPQSearch)); - hs->szSearchMask = strdup(szMask); + strcpy(&hs->szSearchMask[0], szMask); hs->dwFlagMask = MPQ_FILE_EXISTS; hs->ha = ha; @@ -408,7 +406,7 @@ HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DA FreeMPQSearch(hs); SetLastError(nError); } - + // Return the result value return (HANDLE)hs; } diff --git a/dep/StormLib/src/SFileListFile.cpp b/dep/StormLib/src/SFileListFile.cpp index 9f476d1e4a4..4604206ed0a 100644 --- a/dep/StormLib/src/SFileListFile.cpp +++ b/dep/StormLib/src/SFileListFile.cpp @@ -343,13 +343,16 @@ int SListFileSaveToMpq(TMPQArchive * ha) } } + // Determine the flags for (listfile) + if(ha->dwFileFlags1 == 0) + ha->dwFileFlags1 = GetDefaultSpecialFileFlags(ha, dwFileSize); + // Create the listfile in the MPQ - assert(ha->dwFileFlags1 != 0); nError = SFileAddFile_Init(ha, LISTFILE_NAME, 0, dwFileSize, LANG_NEUTRAL, - ha->dwFileFlags1, + ha->dwFileFlags1 | MPQ_FILE_REPLACEEXISTING, &hf); // Add all file names if(nError == ERROR_SUCCESS) diff --git a/dep/StormLib/src/SFileOpenArchive.cpp b/dep/StormLib/src/SFileOpenArchive.cpp index d7b04aba70e..b36b7d35ea7 100644 --- a/dep/StormLib/src/SFileOpenArchive.cpp +++ b/dep/StormLib/src/SFileOpenArchive.cpp @@ -32,6 +32,34 @@ static bool IsAviFile(void * pvFileBegin) return (DwordValue0 == 0x46464952 && DwordValue2 == 0x20495641 && DwordValue3 == 0x5453494C); } +static TFileBitmap * CreateFileBitmap(TMPQArchive * ha, TMPQBitmap * pMpqBitmap, bool bFileIsComplete) +{ + TFileBitmap * pBitmap; + size_t nLength; + + // Calculate the length of the bitmap in blocks and in bytes + nLength = (size_t)(((ha->pHeader->ArchiveSize64 - 1) / pMpqBitmap->dwBlockSize) + 1); + nLength = (size_t)(((nLength - 1) / 8) + 1); + + // Allocate the file bitmap + pBitmap = (TFileBitmap *)STORM_ALLOC(BYTE, sizeof(TFileBitmap) + nLength); + if(pBitmap != NULL) + { + // Fill the structure + pBitmap->StartOffset = ha->MpqPos; + pBitmap->EndOffset = ha->MpqPos + ha->pHeader->ArchiveSize64; + pBitmap->IsComplete = bFileIsComplete ? 1 : 0; + pBitmap->BitmapSize = (DWORD)nLength; + pBitmap->BlockSize = pMpqBitmap->dwBlockSize; + pBitmap->Reserved = 0; + + // Copy the file bitmap + memcpy((pBitmap + 1), (pMpqBitmap + 1), nLength); + } + + return pBitmap; +} + // This function gets the right positions of the hash table and the block table. static int VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize) { @@ -91,19 +119,6 @@ static int VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize) // SFileGetLocale and SFileSetLocale // Set the locale for all newly opened files -DWORD WINAPI SFileGetGlobalFlags() -{ - return dwGlobalFlags; -} - -DWORD WINAPI SFileSetGlobalFlags(DWORD dwNewFlags) -{ - DWORD dwOldFlags = dwGlobalFlags; - - dwGlobalFlags = dwNewFlags; - return dwOldFlags; -} - LCID WINAPI SFileGetLocale() { return lcFileLocale; @@ -145,18 +160,10 @@ bool WINAPI SFileOpenArchive( // Open the MPQ archive file if(nError == ERROR_SUCCESS) { - if(!(dwFlags & MPQ_OPEN_ENCRYPTED)) - { - pStream = FileStream_OpenFile(szMpqName, (dwFlags & MPQ_OPEN_READ_ONLY) ? false : true); - if(pStream == NULL) - nError = GetLastError(); - } - else - { - pStream = FileStream_OpenEncrypted(szMpqName); - if(pStream == NULL) - nError = GetLastError(); - } + // Initialize the stream + pStream = FileStream_OpenFile(szMpqName, (dwFlags & STREAM_OPTIONS_MASK)); + if(pStream == NULL) + nError = GetLastError(); } // Allocate the MPQhandle @@ -175,7 +182,7 @@ bool WINAPI SFileOpenArchive( pStream = NULL; // Remember if the archive is open for write - if(ha->pStream->StreamFlags & (STREAM_FLAG_READ_ONLY | STREAM_FLAG_ENCRYPTED_FILE)) + if(FileStream_IsReadOnly(ha->pStream)) ha->dwFlags |= MPQ_FLAG_READ_ONLY; // Also remember if we shall check sector CRCs when reading file @@ -276,10 +283,6 @@ bool WINAPI SFileOpenArchive( if(dwFlags & (MPQ_OPEN_NO_LISTFILE | MPQ_OPEN_NO_ATTRIBUTES)) ha->dwFlags |= MPQ_FLAG_READ_ONLY; - // Set the default file flags for (listfile) and (attributes) - ha->dwFileFlags1 = - ha->dwFileFlags2 = MPQ_FILE_ENCRYPTED | MPQ_FILE_COMPRESS | MPQ_FILE_REPLACEEXISTING; - // Set the size of file sector ha->dwSectorSize = (0x200 << ha->pHeader->wSectorSize); @@ -287,6 +290,24 @@ bool WINAPI SFileOpenArchive( nError = VerifyMpqTablePositions(ha, FileSize); } + // Check if the MPQ has data bitmap. If yes, we can verify if the MPQ is complete + if(nError == ERROR_SUCCESS && ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_4) + { + TFileBitmap * pBitmap; + bool bFileIsComplete = true; + + LoadMpqDataBitmap(ha, FileSize, &bFileIsComplete); + if(ha->pBitmap != NULL && bFileIsComplete == false) + { + // Convert the MPQ bitmap to the file bitmap + pBitmap = CreateFileBitmap(ha, ha->pBitmap, bFileIsComplete); + + // Set the data bitmap into the file stream for additional checks + FileStream_SetBitmap(ha->pStream, pBitmap); + ha->dwFlags |= MPQ_FLAG_READ_ONLY; + } + } + // Read the hash table. Ignore the result, as hash table is no longer required // Read HET table. Ignore the result, as HET table is no longer required if(nError == ERROR_SUCCESS) @@ -369,6 +390,16 @@ bool WINAPI SFileOpenArchive( } //----------------------------------------------------------------------------- +// SFileGetArchiveBitmap + +bool WINAPI SFileGetArchiveBitmap(HANDLE hMpq, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded) +{ + TMPQArchive * ha = (TMPQArchive *)hMpq; + + return FileStream_GetBitmap(ha->pStream, pBitmap, Length, LengthNeeded); +} + +//----------------------------------------------------------------------------- // bool SFileFlushArchive(HANDLE hMpq) // // Saves all dirty data into MPQ archive. diff --git a/dep/StormLib/src/SFileOpenFileEx.cpp b/dep/StormLib/src/SFileOpenFileEx.cpp index c35ac9f969c..e03a8b17998 100644 --- a/dep/StormLib/src/SFileOpenFileEx.cpp +++ b/dep/StormLib/src/SFileOpenFileEx.cpp @@ -29,10 +29,10 @@ static bool OpenLocalFile(const char * szFileName, HANDLE * phFile) for(i = 0; szFileName[i] != 0; i++) szFileNameT[i] = szFileName[i]; szFileNameT[i] = 0; - pStream = FileStream_OpenFile(szFileNameT, false); + pStream = FileStream_OpenFile(szFileNameT, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); #else - pStream = FileStream_OpenFile(szFileName, false); + pStream = FileStream_OpenFile(szFileName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); #endif if(pStream != NULL) @@ -73,7 +73,7 @@ bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, DWORD dwReserved, HAN { // Construct the name of the patch file strcpy(szPatchFileName, ha->szPatchPrefix); - strcat(szPatchFileName, szFileName); + strcpy(&szPatchFileName[ha->cchPatchPrefix], szFileName); if(SFileOpenFileEx((HANDLE)ha, szPatchFileName, SFILE_OPEN_FROM_MPQ, (HANDLE *)&hfBase)) { // The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE @@ -102,7 +102,7 @@ bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, DWORD dwReserved, HAN { // Construct patch file name strcpy(szPatchFileName, ha->szPatchPrefix); - strcat(szPatchFileName, szFileName); + strcpy(&szPatchFileName[ha->cchPatchPrefix], szFileName); if(SFileOpenFileEx((HANDLE)ha, szPatchFileName, SFILE_OPEN_FROM_MPQ, &hPatchFile)) { // Remember the new version @@ -229,7 +229,11 @@ int WINAPI SFileEnumLocales( bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName) { TMPQArchive * ha = (TMPQArchive *)hMpq; + TFileEntry * pFileEntry; + DWORD dwFlagsToCheck = MPQ_FILE_EXISTS; DWORD dwFileIndex = 0; + char szPatchFileName[MAX_PATH]; + bool bIsPseudoName; int nError = ERROR_SUCCESS; if(!IsValidMpqHandle(ha)) @@ -240,26 +244,39 @@ bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName) // Prepare the file opening if(nError == ERROR_SUCCESS) { - if(!IsPseudoFileName(szFileName, &dwFileIndex)) - { - if(GetFileEntryLocale(ha, szFileName, lcFileLocale) == NULL) - { - nError = ERROR_FILE_NOT_FOUND; - } - } - else + // Different processing for pseudo-names + bIsPseudoName = IsPseudoFileName(szFileName, &dwFileIndex); + + // Walk through the MPQ and all patches + while(ha != NULL) { - if(GetFileEntryByIndex(ha, dwFileIndex) == NULL) + // Verify presence of the file + pFileEntry = (bIsPseudoName == false) ? GetFileEntryLocale(ha, szFileName, lcFileLocale) + : GetFileEntryByIndex(ha, dwFileIndex); + // Verify the file flags + if(pFileEntry != NULL && (pFileEntry->dwFlags & dwFlagsToCheck) == MPQ_FILE_EXISTS) + return true; + + // If this is patched archive, go to the patch + dwFlagsToCheck = MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE; + ha = ha->haPatch; + + // Prepare the patched file name + if(ha != NULL) { - nError = ERROR_FILE_NOT_FOUND; + strcpy(szPatchFileName, ha->szPatchPrefix); + strcat(szPatchFileName, szFileName); + szFileName = szPatchFileName; } } + + // Not found, sorry + nError = ERROR_FILE_NOT_FOUND; } // Cleanup - if(nError != ERROR_SUCCESS) - SetLastError(nError); - return (nError == ERROR_SUCCESS); + SetLastError(nError); + return false; } diff --git a/dep/StormLib/src/SFilePatchArchives.cpp b/dep/StormLib/src/SFilePatchArchives.cpp index 02f149be968..24ae2c52c37 100644 --- a/dep/StormLib/src/SFilePatchArchives.cpp +++ b/dep/StormLib/src/SFilePatchArchives.cpp @@ -400,7 +400,7 @@ static int ApplyMpqPatch( //----------------------------------------------------------------------------- // Public functions (StormLib internals) -bool IsPatchData(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize) +bool IsIncrementalPatchFile(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize) { TPatchHeader * pPatchHeader = (TPatchHeader *)pvData; BLIZZARD_BSDIFF40_FILE DiffFile; @@ -520,7 +520,7 @@ bool WINAPI SFileOpenPatchArchive( if(nError == ERROR_SUCCESS) { - if((ha->pStream->StreamFlags & STREAM_FLAG_READ_ONLY) == 0) + if(!FileStream_IsReadOnly(ha->pStream)) nError = ERROR_ACCESS_DENIED; } @@ -539,7 +539,7 @@ bool WINAPI SFileOpenPatchArchive( { if(!SFileHasFile(hPatchMpq, PATCH_METADATA_NAME)) { - GetDefaultPatchPrefix(ha->pStream->szFileName, szPatchPrefixBuff); + GetDefaultPatchPrefix(FileStream_GetFileName(ha->pStream), szPatchPrefixBuff); szPatchPathPrefix = szPatchPrefixBuff; } } diff --git a/dep/StormLib/src/SFileReadFile.cpp b/dep/StormLib/src/SFileReadFile.cpp index 8c6482c13d2..5570fd466c5 100644 --- a/dep/StormLib/src/SFileReadFile.cpp +++ b/dep/StormLib/src/SFileReadFile.cpp @@ -75,13 +75,14 @@ static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo if(hf->pStream != NULL) { // Calculate the length needed - cchCharsNeeded += _tcslen(hf->pStream->szFileName) + 1; + szFileName = FileStream_GetFileName(hf->pStream); + cchCharsNeeded += _tcslen(szFileName) + 1; cbLengthNeeded = (DWORD)(cchCharsNeeded * sizeof(TCHAR)); // If we have enough space, copy the file name if(cbFileInfo >= cbLengthNeeded) { - nLength = _tcslen(szFileName = hf->pStream->szFileName) + 1; + nLength = _tcslen(szFileName) + 1; memcpy(szPatchChain, szFileName, nLength * sizeof(TCHAR)); szPatchChain += nLength; @@ -93,7 +94,7 @@ static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo { // Calculate number of characters needed for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatchFile) - cchCharsNeeded += _tcslen(hfTemp->ha->pStream->szFileName) + 1; + cchCharsNeeded += _tcslen(FileStream_GetFileName(hfTemp->ha->pStream)) + 1; cbLengthNeeded = (DWORD)(cchCharsNeeded * sizeof(TCHAR)); // If we have enough space, the copy the patch chain @@ -101,7 +102,8 @@ static bool GetFilePatchChain(TMPQFile * hf, void * pvFileInfo, DWORD cbFileInfo { for(hfTemp = hf; hfTemp != NULL; hfTemp = hfTemp->hfPatchFile) { - nLength = _tcslen(szFileName = hfTemp->ha->pStream->szFileName) + 1; + szFileName = FileStream_GetFileName(hfTemp->ha->pStream); + nLength = _tcslen(szFileName) + 1; memcpy(szPatchChain, szFileName, nLength * sizeof(TCHAR)); szPatchChain += nLength; } @@ -265,15 +267,19 @@ static int ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, DW int cbInSector = dwRawBytesInThisSector; int nResult = 0; - // Is the file compressed by PKWARE Data Compression Library ? - if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE) - nResult = SCompExplode((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector); - // Is the file compressed by Blizzard's multiple compression ? if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS) { - hf->PreviousCompression = pbInSector[0]; - nResult = SCompDecompress((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector); + if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2) + nResult = SCompDecompress2((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector); + else + nResult = SCompDecompress((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector); + } + + // Is the file compressed by PKWARE Data Compression Library ? + else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE) + { + nResult = SCompExplode((char *)pbOutSector, &cbOutSector, (char *)pbInSector, cbInSector); } // Did the decompression fail ? @@ -314,7 +320,6 @@ static int ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos TFileEntry * pFileEntry = hf->pFileEntry; LPBYTE pbCompressed = NULL; LPBYTE pbRawData = NULL; - bool bIsReallyCompressed = false; int nError = ERROR_SUCCESS; // If the file buffer is not allocated yet, do it. @@ -334,13 +339,12 @@ static int ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos if(hf->dwSectorOffs != 0) { // Is the file compressed? - if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS) + if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) { // Allocate space for compressed data pbCompressed = STORM_ALLOC(BYTE, pFileEntry->dwCmpSize); if(pbCompressed == NULL) return ERROR_NOT_ENOUGH_MEMORY; - bIsReallyCompressed = true; pbRawData = pbCompressed; } @@ -359,47 +363,43 @@ static int ReadMpqFileSingleUnit(TMPQFile * hf, void * pvBuffer, DWORD dwFilePos BSWAP_ARRAY32_UNSIGNED(pbRawData, pFileEntry->dwCmpSize); } - // - // In "wow-update-12694.MPQ" from Wow-Cataclysm BETA: - // - // File CmpSize FileSize Data - // -------------------------------------- ------- -------- --------------- - // esES\DBFilesClient\LightSkyBox.dbc 0xBE 0xBC Is compressed - // deDE\DBFilesClient\MountCapability.dbc 0x93 0x77 Is uncompressed - // - // Now tell me how to deal with this mess. - // - - if(hf->pPatchInfo != NULL) - { - if(pbRawData[0] == 'P' && pbRawData[1] == 'T' && pbRawData[2] == 'C' && pbRawData[3] == 'H') - { - assert(pFileEntry->dwCmpSize >= hf->dwDataSize); - bIsReallyCompressed = false; - } - } - else - { - if(pFileEntry->dwCmpSize >= hf->dwDataSize) - bIsReallyCompressed = false; - } - // If the file is compressed, we have to decompress it now - if(bIsReallyCompressed) + if(pFileEntry->dwFlags & MPQ_FILE_COMPRESSED) { int cbOutBuffer = (int)hf->dwDataSize; + int cbInBuffer = (int)pFileEntry->dwCmpSize; + int nResult = 0; - // Note: Single unit files compressed with IMPLODE are not supported by Blizzard - if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE) - { - if(!SCompExplode((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, (int)pFileEntry->dwCmpSize)) - nError = ERROR_FILE_CORRUPT; - } + // + // If the file is an incremental patch, the size of compressed data + // is determined as pFileEntry->dwCmpSize - sizeof(TPatchInfo) + // + // In "wow-update-12694.MPQ" from Wow-Cataclysm BETA: + // + // File CmprSize DcmpSize DataSize Compressed? + // -------------------------------------- ---------- -------- -------- --------------- + // esES\DBFilesClient\LightSkyBox.dbc 0xBE->0xA2 0xBC 0xBC Yes + // deDE\DBFilesClient\MountCapability.dbc 0x93->0x77 0x77 0x77 No + // + + if(pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) + cbInBuffer = cbInBuffer - sizeof(TPatchInfo); + + // Is the file compressed by Blizzard's multiple compression ? if(pFileEntry->dwFlags & MPQ_FILE_COMPRESS) { - if(!SCompDecompress((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, (int)pFileEntry->dwCmpSize)) - nError = ERROR_FILE_CORRUPT; + if(ha->pHeader->wFormatVersion >= MPQ_FORMAT_VERSION_2) + nResult = SCompDecompress2((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, cbInBuffer); + else + nResult = SCompDecompress((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, cbInBuffer); } + + // Is the file compressed by PKWARE Data Compression Library ? + // Note: Single unit files compressed with IMPLODE are not supported by Blizzard + else if(pFileEntry->dwFlags & MPQ_FILE_IMPLODE) + nResult = SCompExplode((char *)hf->pbFileSector, &cbOutBuffer, (char *)pbRawData, cbInBuffer); + + nError = (nResult != 0) ? ERROR_SUCCESS : ERROR_FILE_CORRUPT; } else { @@ -938,7 +938,7 @@ bool WINAPI SFileGetFileName(HANDLE hFile, char * szFileName) if(pFileEntry != NULL && pFileEntry->szFileName != NULL) strcpy(szFileName, pFileEntry->szFileName); else if(hf->pStream != NULL) - CopyFileName(szFileName, hf->pStream->szFileName); + CopyFileName(szFileName, FileStream_GetFileName(hf->pStream)); } return (nError == ERROR_SUCCESS); } @@ -988,8 +988,8 @@ bool WINAPI SFileGetFileInfo( VERIFY_MPQ_HANDLE(ha); // pvFileInfo receives the name of the archive, terminated by 0 - cbLengthNeeded = (DWORD)(_tcslen(ha->pStream->szFileName) + 1) * sizeof(TCHAR); - pvSrcFileInfo = ha->pStream->szFileName; + pvSrcFileInfo = FileStream_GetFileName(ha->pStream); + cbLengthNeeded = (DWORD)(_tcslen((TCHAR *)pvSrcFileInfo) + 1) * sizeof(TCHAR); break; case SFILE_INFO_ARCHIVE_SIZE: // Size of the archive @@ -1056,15 +1056,13 @@ bool WINAPI SFileGetFileInfo( pvSrcFileInfo = &dwFileCount; break; - case SFILE_INFO_STREAM_FLAGS: // Stream flags for the MPQ. See STREAM_FLAG_XXX - VERIFY_MPQ_HANDLE(ha); - cbLengthNeeded = sizeof(DWORD); - pvSrcFileInfo = &ha->pStream->StreamFlags; + case SFILE_INFO_STREAM_FLAGS: // Deprecated + nError = ERROR_INVALID_PARAMETER; break; case SFILE_INFO_IS_READ_ONLY: VERIFY_MPQ_HANDLE(ha); - dwIsReadOnly = ((ha->pStream->StreamFlags & STREAM_FLAG_READ_ONLY) || (ha->dwFlags & MPQ_FLAG_READ_ONLY)); + dwIsReadOnly = (FileStream_IsReadOnly(ha->pStream) || (ha->dwFlags & MPQ_FLAG_READ_ONLY)); cbLengthNeeded = sizeof(DWORD); pvSrcFileInfo = &dwIsReadOnly; break; diff --git a/dep/StormLib/src/SFileVerify.cpp b/dep/StormLib/src/SFileVerify.cpp index 2190caa6994..7457171d88f 100644 --- a/dep/StormLib/src/SFileVerify.cpp +++ b/dep/StormLib/src/SFileVerify.cpp @@ -169,9 +169,7 @@ static void CalculateArchiveRange( TMPQArchive * ha, PMPQ_SIGNATURE_INFO pSI) { - TMPQHeader * pHeader = ha->pHeader; ULONGLONG TempPos = 0; - ULONGLONG MaxPos; char szMapHeader[0x200]; // Get the MPQ begin @@ -188,31 +186,9 @@ static void CalculateArchiveRange( } } - // Get the MPQ data end. The end is calculated as the biggest - // value of (end of the last file), (end of block table), - // (end of ext block table), (end of hash table) - FindFreeMpqSpace(ha, &MaxPos); - - // Check if hash table is beyond - TempPos = ha->MpqPos + MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos) + pHeader->HashTableSize64; - if(TempPos > MaxPos) - MaxPos = TempPos; - - // Check if block table is beyond - TempPos = ha->MpqPos + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos) + pHeader->BlockTableSize64; - if(TempPos > MaxPos) - MaxPos = TempPos; - - // Check if ext block table is beyond - if(pHeader->HiBlockTablePos64 != 0) - { - TempPos = ha->MpqPos + pHeader->HiBlockTablePos64 + pHeader->HiBlockTableSize64; - if(TempPos > MaxPos) - MaxPos = TempPos; - } - - // Give the end - pSI->EndMpqData = MaxPos; + // Get the MPQ data end. This is stored in our MPQ header, + // and it's been already prepared by SFileOpenArchive, + pSI->EndMpqData = ha->MpqPos + ha->pHeader->ArchiveSize64; // Get the size of the entire file FileStream_GetSize(ha->pStream, pSI->EndOfFile); @@ -421,7 +397,7 @@ static bool CalculateMpqHashSha1( sha1_done(&sha1_state_temp, sha1_tail0); memcpy(&sha1_state_temp, &sha1_state, sizeof(hash_state)); - GetPlainAnsiFileName(ha->pStream->szFileName, szPlainName); + GetPlainAnsiFileName(FileStream_GetFileName(ha->pStream), szPlainName); AddTailToSha1(&sha1_state_temp, szPlainName); sha1_done(&sha1_state_temp, sha1_tail1); @@ -449,11 +425,13 @@ static int VerifyRawMpqData( DWORD dwMD5Size; int nError = ERROR_SUCCESS; + // Don't verify zero-sized blocks + if(dwDataSize == 0) + return ERROR_SUCCESS; + // Get the number of data chunks to calculate MD5 assert(dwChunkSize != 0); - dwChunkCount = dwDataSize / dwChunkSize; - if(dwDataSize % dwChunkSize) - dwChunkCount++; + dwChunkCount = ((dwDataSize - 1) / dwChunkSize) + 1; dwMD5Size = dwChunkCount * MD5_DIGEST_SIZE; // Allocate space for data chunk and for the MD5 array @@ -659,6 +637,35 @@ static DWORD VerifyFile( if(SFileIsPatchedArchive(hMpq)) dwSearchScope = SFILE_OPEN_PATCHED_FILE; + // If we have to verify raw data MD5, do it before file open + if(dwFlags & SFILE_VERIFY_RAW_MD5) + { + TMPQArchive * ha = (TMPQArchive *)hMpq; + + // Parse the base MPQ and all patches + while(ha != NULL) + { + // Does the archive have support for raw MD5? + if(ha->pHeader->dwRawChunkSize != 0) + { + // The file has raw MD5 if the archive supports it + dwVerifyResult |= VERIFY_FILE_HAS_RAW_MD5; + + // Find file entry for the file + pFileEntry = GetFileEntryLocale(ha, szFileName, lcFileLocale); + if(pFileEntry != NULL) + { + // If the file's raw MD5 doesn't match, don't bother with more checks + if(VerifyRawMpqData(ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize) != ERROR_SUCCESS) + return dwVerifyResult | VERIFY_FILE_RAW_MD5_ERROR; + } + } + + // Move to the next patch + ha = ha->haPatch; + } + } + // Attempt to open the file if(SFileOpenFileEx(hMpq, szFileName, dwSearchScope, &hFile)) { @@ -671,18 +678,6 @@ static DWORD VerifyFile( md5_init(&md5_state); dwCrc32 = crc32(0, Z_NULL, 0); - // If we have to verify raw data MD5, do it - if(dwFlags & SFILE_VERIFY_RAW_MD5) - { - if(hf->ha->pHeader->dwRawChunkSize != 0) - { - // Note: we have to open the file from the MPQ where it was open from - if(VerifyRawMpqData(hf->ha, pFileEntry->ByteOffset, pFileEntry->dwCmpSize) != ERROR_SUCCESS) - dwVerifyResult |= VERIFY_FILE_RAW_MD5_ERROR; - dwVerifyResult |= VERIFY_FILE_HAS_RAW_MD5; - } - } - // Also turn on sector checksum verification if(dwFlags & SFILE_VERIFY_SECTOR_CRC) hf->bCheckSectorCRCs = true; diff --git a/dep/StormLib/src/StormCommon.h b/dep/StormLib/src/StormCommon.h index 278c44ed810..9a85c4bd5ac 100644 --- a/dep/StormLib/src/StormCommon.h +++ b/dep/StormLib/src/StormCommon.h @@ -109,7 +109,6 @@ __inline void DebugFree(void * ptr) //----------------------------------------------------------------------------- // StormLib internal global variables -extern DWORD dwGlobalFlags; // Global StormLib flags extern LCID lcFileLocale; // Preferred file locale //----------------------------------------------------------------------------- @@ -122,7 +121,7 @@ extern LCID lcFileLocale; // Preferred file locale DWORD HashString(const char * szFileName, DWORD dwHashType); -void InitializeMpqCryptography(); +void InitializeMpqCryptography(); DWORD GetHashTableSizeForFileCount(DWORD dwFileCount); @@ -131,6 +130,8 @@ ULONGLONG HashStringJenkins(const char * szFileName); int ConvertMpqHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags); +DWORD GetDefaultSpecialFileFlags(TMPQArchive * ha, DWORD dwFileSize); + void EncryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwKey); void DecryptMpqBlock(void * pvFileBlock, DWORD dwLength, DWORD dwKey); @@ -158,7 +159,10 @@ DWORD AllocateHetEntry(TMPQArchive * ha, TFileEntry * pFileEntry); void FindFreeMpqSpace(TMPQArchive * ha, ULONGLONG * pFreeSpacePos); -// Functions that load the HET abd BET tables +// Functions that loads and verifies MPQ data bitmap +int LoadMpqDataBitmap(TMPQArchive * ha, ULONGLONG FileSize, bool * pbFileIsComplete); + +// Functions that load the HET and BET tables int CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize); int LoadAnyHashTable(TMPQArchive * ha); int BuildFileTable(TMPQArchive * ha, ULONGLONG FileSize); @@ -206,7 +210,7 @@ int WriteMemDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, void * pvRawD int WriteMpqDataMD5(TFileStream * pStream, ULONGLONG RawDataOffs, DWORD dwRawDataSize, DWORD dwChunkSize); void FreeMPQFile(TMPQFile *& hf); -bool IsPatchData(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize); +bool IsIncrementalPatchFile(const void * pvData, DWORD cbData, LPDWORD pdwPatchedFileSize); int PatchFileData(TMPQFile * hf); void FreeMPQArchive(TMPQArchive *& ha); diff --git a/dep/StormLib/src/StormLib.h b/dep/StormLib/src/StormLib.h index 1f75ffd26c1..a07ae46ca48 100644 --- a/dep/StormLib/src/StormLib.h +++ b/dep/StormLib/src/StormLib.h @@ -64,15 +64,16 @@ /* 20.09.10 8.00 Lad MPQs v 4, HET and BET tables */ /* 07.01.11 8.01 Lad Write support for MPQs v 3 and 4 */ /* 15.09.11 8.04 Lad Bug fixes, testing for Diablo III MPQs */ +/* 26.04.12 8.10 Lad Support for data map, added SFileGetArchiveBitmap */ /*****************************************************************************/ #ifndef __STORMLIB_H__ #define __STORMLIB_H__ #ifdef _MSC_VER -#pragma warning(disable:4668) // 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' +#pragma warning(disable:4668) // 'XXX' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' #pragma warning(disable:4820) // 'XXX' : '2' bytes padding added after data member 'XXX::yyy' -#endif +#endif #include "StormPort.h" @@ -85,118 +86,111 @@ extern "C" { // // The library type is encoded in the library name as the following // StormLibXYZ.lib -// +// // X - D for Debug version, R for Release version // Y - A for ANSI version, U for Unicode version // Z - S for static-linked CRT library, D for multithreaded DLL CRT library // -#if 0 -#if defined(_MSC_VER) && !defined(__STORMLIB_SELF__) - - #ifdef _DEBUG // DEBUG VERSIONS - #ifndef _UNICODE - #ifdef _DLL - #pragma comment(lib, "StormLibDAD.lib") // Debug Ansi CRT-DLL version - #else - #pragma comment(lib, "StormLibDAS.lib") // Debug Ansi CRT-LIB version +#if 0 && defined(_MSC_VER) && !defined(__STORMLIB_SELF__) + + #ifdef _DEBUG // DEBUG VERSIONS + #ifndef _UNICODE + #ifdef _DLL + #pragma comment(lib, "StormLibDAD.lib") // Debug Ansi CRT-DLL version + #else + #pragma comment(lib, "StormLibDAS.lib") // Debug Ansi CRT-LIB version #endif #else - #ifdef _DLL - #pragma comment(lib, "StormLibDUD.lib") // Debug Unicode CRT-DLL version - #else - #pragma comment(lib, "StormLibDUS.lib") // Debug Unicode CRT-LIB version + #ifdef _DLL + #pragma comment(lib, "StormLibDUD.lib") // Debug Unicode CRT-DLL version + #else + #pragma comment(lib, "StormLibDUS.lib") // Debug Unicode CRT-LIB version #endif #endif - #else // RELEASE VERSIONS - #ifndef _UNICODE + #else // RELEASE VERSIONS + #ifndef _UNICODE #ifdef _DLL - #pragma comment(lib, "StormLibRAD.lib") // Release Ansi CRT-DLL version - #else - #pragma comment(lib, "StormLibRAS.lib") // Release Ansi CRT-LIB version + #pragma comment(lib, "StormLibRAD.lib") // Release Ansi CRT-DLL version + #else + #pragma comment(lib, "StormLibRAS.lib") // Release Ansi CRT-LIB version #endif #else #ifdef _DLL - #pragma comment(lib, "StormLibRUD.lib") // Release Unicode CRT-DLL version - #else - #pragma comment(lib, "StormLibRUS.lib") // Release Unicode CRT-LIB version + #pragma comment(lib, "StormLibRUD.lib") // Release Unicode CRT-DLL version + #else + #pragma comment(lib, "StormLibRUS.lib") // Release Unicode CRT-LIB version #endif #endif #endif #endif -#endif //----------------------------------------------------------------------------- // Defines -#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') -#define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') +#define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') +#define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') -#define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file. -#define ERROR_UNKNOWN_FILE_KEY 10001 // Returned by SFileReadFile when can't find file key -#define ERROR_CHECKSUM_ERROR 10002 // Returned by SFileReadFile when sector CRC doesn't match -#define ERROR_INTERNAL_FILE 10003 // The given operation is not allowed on internal file -#define ERROR_BASE_FILE_MISSING 10004 // The file is present as incremental patch file, but base file is missing -#define ERROR_MARKED_FOR_DELETE 10005 // The file was marked as "deleted" in the MPQ +#define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file. +#define ERROR_UNKNOWN_FILE_KEY 10001 // Returned by SFileReadFile when can't find file key +#define ERROR_CHECKSUM_ERROR 10002 // Returned by SFileReadFile when sector CRC doesn't match +#define ERROR_INTERNAL_FILE 10003 // The given operation is not allowed on internal file +#define ERROR_BASE_FILE_MISSING 10004 // The file is present as incremental patch file, but base file is missing +#define ERROR_MARKED_FOR_DELETE 10005 // The file was marked as "deleted" in the MPQ // Values for SFileCreateArchive -#define HASH_TABLE_SIZE_MIN 0x00000004 // Minimum acceptable hash table size -#define HASH_TABLE_SIZE_DEFAULT 0x00001000 // Default hash table size for empty MPQs -#define HASH_TABLE_SIZE_MAX 0x00080000 // Maximum acceptable hash table size +#define HASH_TABLE_SIZE_MIN 0x00000004 // Minimum acceptable hash table size +#define HASH_TABLE_SIZE_DEFAULT 0x00001000 // Default hash table size for empty MPQs +#define HASH_TABLE_SIZE_MAX 0x00080000 // Maximum acceptable hash table size -#define HASH_ENTRY_DELETED 0xFFFFFFFE // Block index for deleted entry in the hash table -#define HASH_ENTRY_FREE 0xFFFFFFFF // Block index for free entry in the hash table +#define HASH_ENTRY_DELETED 0xFFFFFFFE // Block index for deleted entry in the hash table +#define HASH_ENTRY_FREE 0xFFFFFFFF // Block index for free entry in the hash table -#define HET_ENTRY_DELETED 0x80 // HET hash value for a deleted entry -#define HET_ENTRY_FREE 0x00 // HET hash value for free entry +#define HET_ENTRY_DELETED 0x80 // HET hash value for a deleted entry +#define HET_ENTRY_FREE 0x00 // HET hash value for free entry -#define HASH_STATE_SIZE 0x60 // Size of LibTomCrypt's hash_state structure +#define HASH_STATE_SIZE 0x60 // Size of LibTomCrypt's hash_state structure -#define MPQ_PATCH_PREFIX_LEN 0x20 // Maximum length of the patch prefix - -// Values for TFileStream::Flags -#define STREAM_FLAG_READ_ONLY 0x01 // The stream is read only -#define STREAM_FLAG_PART_FILE 0x02 // The stream is a PART file. -#define STREAM_FLAG_ENCRYPTED_FILE 0x04 // The stream is an encrypted MPQ (MPQE). +#define MPQ_PATCH_PREFIX_LEN 0x20 // Maximum length of the patch prefix // Values for SFileOpenArchive -#define SFILE_OPEN_HARD_DISK_FILE 2 // Open the archive on HDD -#define SFILE_OPEN_CDROM_FILE 3 // Open the archive only if it is on CDROM +#define SFILE_OPEN_HARD_DISK_FILE 2 // Open the archive on HDD +#define SFILE_OPEN_CDROM_FILE 3 // Open the archive only if it is on CDROM // Values for SFileOpenFile -#define SFILE_OPEN_FROM_MPQ 0x00000000 // Open the file from the MPQ archive -#define SFILE_OPEN_PATCHED_FILE 0x00000001 // Open the file from the MPQ archive -#define SFILE_OPEN_ANY_LOCALE 0xFFFFFFFE // Reserved for StormLib internal use -#define SFILE_OPEN_LOCAL_FILE 0xFFFFFFFF // Open a local file +#define SFILE_OPEN_FROM_MPQ 0x00000000 // Open the file from the MPQ archive +#define SFILE_OPEN_PATCHED_FILE 0x00000001 // Open the file from the MPQ archive +#define SFILE_OPEN_ANY_LOCALE 0xFFFFFFFE // Reserved for StormLib internal use +#define SFILE_OPEN_LOCAL_FILE 0xFFFFFFFF // Open a local file // Flags for TMPQArchive::dwFlags -#define MPQ_FLAG_READ_ONLY 0x00000001 // If set, the MPQ has been open for read-only access -#define MPQ_FLAG_CHANGED 0x00000002 // If set, the MPQ tables have been changed -#define MPQ_FLAG_PROTECTED 0x00000004 // Set on protected MPQs (like W3M maps) -#define MPQ_FLAG_CHECK_SECTOR_CRC 0x0000008 // Checking sector CRC when reading files -#define MPQ_FLAG_NEED_FIX_SIZE 0x00000010 // Used during opening the archive -#define MPQ_FLAG_INV_LISTFILE 0x00000020 // If set, it means that the (listfile) has been invalidated -#define MPQ_FLAG_INV_ATTRIBUTES 0x00000040 // If set, it means that the (attributes) has been invalidated - -// Return value for SFilGetFileSize and SFileSetFilePointer -#define SFILE_INVALID_SIZE 0xFFFFFFFF -#define SFILE_INVALID_POS 0xFFFFFFFF -#define SFILE_INVALID_ATTRIBUTES 0xFFFFFFFF +#define MPQ_FLAG_READ_ONLY 0x00000001 // If set, the MPQ has been open for read-only access +#define MPQ_FLAG_CHANGED 0x00000002 // If set, the MPQ tables have been changed +#define MPQ_FLAG_PROTECTED 0x00000004 // Set on protected MPQs (like W3M maps) +#define MPQ_FLAG_CHECK_SECTOR_CRC 0x00000008 // Checking sector CRC when reading files +#define MPQ_FLAG_NEED_FIX_SIZE 0x00000010 // Used during opening the archive +#define MPQ_FLAG_INV_LISTFILE 0x00000020 // If set, it means that the (listfile) has been invalidated +#define MPQ_FLAG_INV_ATTRIBUTES 0x00000040 // If set, it means that the (attributes) has been invalidated + +// Return value for SFileGetFileSize and SFileSetFilePointer +#define SFILE_INVALID_SIZE 0xFFFFFFFF +#define SFILE_INVALID_POS 0xFFFFFFFF +#define SFILE_INVALID_ATTRIBUTES 0xFFFFFFFF // Flags for SFileAddFile -#define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library) -#define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (By multiple methods) -#define MPQ_FILE_COMPRESSED 0x0000FF00 // File is compressed -#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted -#define MPQ_FILE_FIX_KEY 0x00020000 // File decryption key has to be fixed -#define MPQ_FILE_PATCH_FILE 0x00100000 // The file is a patch file. Raw file data begin with TPatchInfo structure -#define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam) -#define MPQ_FILE_DELETE_MARKER 0x02000000 // File is a deletion marker, indicating that the file no longer exists. -#define MPQ_FILE_SECTOR_CRC 0x04000000 // File has checksums for each sector. - // Ignored if file is not compressed or imploded. -#define MPQ_FILE_EXISTS 0x80000000 // Set if file exists, reset when the file was deleted -#define MPQ_FILE_REPLACEEXISTING 0x80000000 // Replace when the file exist (SFileAddFile) +#define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library) +#define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (By multiple methods) +#define MPQ_FILE_COMPRESSED 0x0000FF00 // File is compressed +#define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted +#define MPQ_FILE_FIX_KEY 0x00020000 // File decryption key has to be fixed +#define MPQ_FILE_PATCH_FILE 0x00100000 // The file is a patch file. Raw file data begin with TPatchInfo structure +#define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam) +#define MPQ_FILE_DELETE_MARKER 0x02000000 // File is a deletion marker. Used in MPQ patches, indicating that the file no longer exists. +#define MPQ_FILE_SECTOR_CRC 0x04000000 // File has checksums for each sector. + // Ignored if file is not compressed or imploded. +#define MPQ_FILE_EXISTS 0x80000000 // Set if file exists, reset when the file was deleted +#define MPQ_FILE_REPLACEEXISTING 0x80000000 // Replace when the file exist (SFileAddFile) #define MPQ_FILE_VALID_FLAGS (MPQ_FILE_IMPLODE | \ MPQ_FILE_COMPRESS | \ @@ -209,211 +203,180 @@ extern "C" { MPQ_FILE_EXISTS) // Compression types for multiple compressions -#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only) -#define MPQ_COMPRESSION_ZLIB 0x02 // ZLIB compression -#define MPQ_COMPRESSION_PKWARE 0x08 // PKWARE DCL compression -#define MPQ_COMPRESSION_BZIP2 0x10 // BZIP2 compression (added in Warcraft III) -#define MPQ_COMPRESSION_SPARSE 0x20 // Sparse compression (added in Starcraft 2) -#define MPQ_COMPRESSION_ADPCM_MONO 0x40 // IMA ADPCM compression (mono) -#define MPQ_COMPRESSION_ADPCM_STEREO 0x80 // IMA ADPCM compression (stereo) - -// For backward compatibility -#define MPQ_COMPRESSION_WAVE_MONO 0x40 // IMA ADPCM compression (mono) -#define MPQ_COMPRESSION_WAVE_STEREO 0x80 // IMA ADPCM compression (stereo) - -// LZMA compression. Added in Starcraft 2. This value is NOT a combination of flags. -#define MPQ_COMPRESSION_LZMA 0x12 +#define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only) +#define MPQ_COMPRESSION_ZLIB 0x02 // ZLIB compression +#define MPQ_COMPRESSION_PKWARE 0x08 // PKWARE DCL compression +#define MPQ_COMPRESSION_BZIP2 0x10 // BZIP2 compression (added in Warcraft III) +#define MPQ_COMPRESSION_SPARSE 0x20 // Sparse compression (added in Starcraft 2) +#define MPQ_COMPRESSION_ADPCM_MONO 0x40 // IMA ADPCM compression (mono) +#define MPQ_COMPRESSION_ADPCM_STEREO 0x80 // IMA ADPCM compression (stereo) +#define MPQ_COMPRESSION_LZMA 0x12 // LZMA compression. Added in Starcraft 2. This value is NOT a combination of flags. +#define MPQ_COMPRESSION_NEXT_SAME 0xFFFFFFFF // Same compression // Constants for SFileAddWave -#define MPQ_WAVE_QUALITY_HIGH 0 // Best quality, the worst compression -#define MPQ_WAVE_QUALITY_MEDIUM 1 // Medium quality, medium compression -#define MPQ_WAVE_QUALITY_LOW 2 // Low quality, the best compression +#define MPQ_WAVE_QUALITY_HIGH 0 // Best quality, the worst compression +#define MPQ_WAVE_QUALITY_MEDIUM 1 // Medium quality, medium compression +#define MPQ_WAVE_QUALITY_LOW 2 // Low quality, the best compression // Signatures for HET and BET table -#define HET_TABLE_SIGNATURE 0x1A544548 // 'HET\x1a' -#define BET_TABLE_SIGNATURE 0x1A544542 // 'BET\x1a' +#define HET_TABLE_SIGNATURE 0x1A544548 // 'HET\x1a' +#define BET_TABLE_SIGNATURE 0x1A544542 // 'BET\x1a' // Decryption keys for MPQ tables -#define MPQ_KEY_HASH_TABLE 0xC3AF3770 // Obtained by HashString("(hash table)", MPQ_HASH_FILE_KEY) -#define MPQ_KEY_BLOCK_TABLE 0xEC83B3A3 // Obtained by HashString("(block table)", MPQ_HASH_FILE_KEY) +#define MPQ_KEY_HASH_TABLE 0xC3AF3770 // Obtained by HashString("(hash table)", MPQ_HASH_FILE_KEY) +#define MPQ_KEY_BLOCK_TABLE 0xEC83B3A3 // Obtained by HashString("(block table)", MPQ_HASH_FILE_KEY) + +// Block map defines +#define MPQ_DATA_BITMAP_SIGNATURE 0x33767470 // Signature of the MPQ data bitmap ('ptv3') // Constants for SFileGetFileInfo -#define SFILE_INFO_ARCHIVE_NAME 1 // MPQ size (value from header) -#define SFILE_INFO_ARCHIVE_SIZE 2 // MPQ size (value from header) -#define SFILE_INFO_MAX_FILE_COUNT 3 // Max number of files in the MPQ -#define SFILE_INFO_HASH_TABLE_SIZE 4 // Size of hash table, in entries -#define SFILE_INFO_BLOCK_TABLE_SIZE 5 // Number of entries in the block table -#define SFILE_INFO_SECTOR_SIZE 6 // Size of file sector (in bytes) -#define SFILE_INFO_HASH_TABLE 7 // Pointer to Hash table (TMPQHash *) -#define SFILE_INFO_BLOCK_TABLE 8 // Pointer to Block Table (TMPQBlock *) -#define SFILE_INFO_NUM_FILES 9 // Real number of files within archive -#define SFILE_INFO_STREAM_FLAGS 10 // Stream flags for the MPQ. See STREAM_FLAG_XXX -#define SFILE_INFO_IS_READ_ONLY 11 // TRUE of the MPQ was open as read only -//------ -#define SFILE_INFO_HASH_INDEX 100 // Hash index of file in MPQ -#define SFILE_INFO_CODENAME1 101 // The first codename of the file -#define SFILE_INFO_CODENAME2 102 // The second codename of the file -#define SFILE_INFO_LOCALEID 103 // Locale ID of file in MPQ -#define SFILE_INFO_BLOCKINDEX 104 // Index to Block Table -#define SFILE_INFO_FILE_SIZE 105 // Original file size (from the block table) -#define SFILE_INFO_COMPRESSED_SIZE 106 // Compressed file size (from the block table) -#define SFILE_INFO_FLAGS 107 // File flags -#define SFILE_INFO_POSITION 108 // File position within archive -#define SFILE_INFO_KEY 109 // File decryption key -#define SFILE_INFO_KEY_UNFIXED 110 // Decryption key not fixed to file pos and size -#define SFILE_INFO_FILETIME 111 // TMPQFileTime -#define SFILE_INFO_PATCH_CHAIN 112 // Chain of patches - -#define LISTFILE_NAME "(listfile)" // Name of internal listfile -#define SIGNATURE_NAME "(signature)" // Name of internal signature -#define ATTRIBUTES_NAME "(attributes)" // Name of internal attributes file +#define SFILE_INFO_ARCHIVE_NAME 1 // MPQ size (value from header) +#define SFILE_INFO_ARCHIVE_SIZE 2 // MPQ size (value from header) +#define SFILE_INFO_MAX_FILE_COUNT 3 // Max number of files in the MPQ +#define SFILE_INFO_HASH_TABLE_SIZE 4 // Size of hash table, in entries +#define SFILE_INFO_BLOCK_TABLE_SIZE 5 // Number of entries in the block table +#define SFILE_INFO_SECTOR_SIZE 6 // Size of file sector (in bytes) +#define SFILE_INFO_HASH_TABLE 7 // Pointer to Hash table (TMPQHash *) +#define SFILE_INFO_BLOCK_TABLE 8 // Pointer to Block Table (TMPQBlock *) +#define SFILE_INFO_NUM_FILES 9 // Real number of files within archive +#define SFILE_INFO_STREAM_FLAGS 10 // Stream flags for the MPQ. See STREAM_FLAG_XXX +#define SFILE_INFO_IS_READ_ONLY 11 // TRUE of the MPQ was open as read only +//------ +#define SFILE_INFO_HASH_INDEX 100 // Hash index of file in MPQ +#define SFILE_INFO_CODENAME1 101 // The first codename of the file +#define SFILE_INFO_CODENAME2 102 // The second codename of the file +#define SFILE_INFO_LOCALEID 103 // Locale ID of file in MPQ +#define SFILE_INFO_BLOCKINDEX 104 // Index to Block Table +#define SFILE_INFO_FILE_SIZE 105 // Original file size (from the block table) +#define SFILE_INFO_COMPRESSED_SIZE 106 // Compressed file size (from the block table) +#define SFILE_INFO_FLAGS 107 // File flags +#define SFILE_INFO_POSITION 108 // File position within archive +#define SFILE_INFO_KEY 109 // File decryption key +#define SFILE_INFO_KEY_UNFIXED 110 // Decryption key not fixed to file pos and size +#define SFILE_INFO_FILETIME 111 // TMPQFileTime +#define SFILE_INFO_PATCH_CHAIN 112 // Chain of patches + +#define LISTFILE_NAME "(listfile)" // Name of internal listfile +#define SIGNATURE_NAME "(signature)" // Name of internal signature +#define ATTRIBUTES_NAME "(attributes)" // Name of internal attributes file #define PATCH_METADATA_NAME "(patch_metadata)" -#define STORMLIB_VERSION 0x0804 // Current version of StormLib (8.04) -#define STORMLIB_VERSION_STRING "8.04" +#define STORMLIB_VERSION 0x080A // Current version of StormLib (8.10) +#define STORMLIB_VERSION_STRING "8.10" -#define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade -#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer -#define MPQ_FORMAT_VERSION_3 2 // WoW Cataclysm Beta -#define MPQ_FORMAT_VERSION_4 3 // WoW Cataclysm and newer +#define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade +#define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer +#define MPQ_FORMAT_VERSION_3 2 // WoW Cataclysm Beta +#define MPQ_FORMAT_VERSION_4 3 // WoW Cataclysm and newer // Flags for MPQ attributes -#define MPQ_ATTRIBUTE_CRC32 0x00000001 // The "(attributes)" contains CRC32 for each file -#define MPQ_ATTRIBUTE_FILETIME 0x00000002 // The "(attributes)" contains file time for each file -#define MPQ_ATTRIBUTE_MD5 0x00000004 // The "(attributes)" contains MD5 for each file -#define MPQ_ATTRIBUTE_ALL 0x00000007 // Summary mask +#define MPQ_ATTRIBUTE_CRC32 0x00000001 // The "(attributes)" contains CRC32 for each file +#define MPQ_ATTRIBUTE_FILETIME 0x00000002 // The "(attributes)" contains file time for each file +#define MPQ_ATTRIBUTE_MD5 0x00000004 // The "(attributes)" contains MD5 for each file +#define MPQ_ATTRIBUTE_PATCH_BIT 0x00000008 // The "(attributes)" contains a patch bit for each file +#define MPQ_ATTRIBUTE_ALL 0x0000000F // Summary mask -#define MPQ_ATTRIBUTES_V1 100 // (attributes) format version 1.00 +#define MPQ_ATTRIBUTES_V1 100 // (attributes) format version 1.00 // Flags for SFileOpenArchive -#define MPQ_OPEN_NO_LISTFILE 0x0010 // Don't load the internal listfile -#define MPQ_OPEN_NO_ATTRIBUTES 0x0020 // Don't open the attributes -#define MPQ_OPEN_FORCE_MPQ_V1 0x0040 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header -#define MPQ_OPEN_CHECK_SECTOR_CRC 0x0080 // On files with MPQ_FILE_SECTOR_CRC, the CRC will be checked when reading file -#define MPQ_OPEN_READ_ONLY 0x0100 // Open the archive for read-only access -#define MPQ_OPEN_ENCRYPTED 0x0200 // Opens an encrypted MPQ archive (Example: Starcraft II installation) +#define BASE_PROVIDER_FILE 0x00000000 // Base data source is a file +#define BASE_PROVIDER_MAP 0x00000001 // Base data source is memory-mapped file +#define BASE_PROVIDER_HTTP 0x00000002 // Base data source is a file on web server +#define BASE_PROVIDER_MASK 0x0000000F // Mask for base provider value + +#define STREAM_PROVIDER_LINEAR 0x00000000 // Stream is linear with no offset mapping +#define STREAM_PROVIDER_PARTIAL 0x00000010 // Stream is partial file (.part) +#define STREAM_PROVIDER_ENCRYPTED 0x00000020 // Stream is an encrypted MPQ +#define STREAM_PROVIDER_MASK 0x000000F0 // Mask for stream provider value + +#define STREAM_FLAG_READ_ONLY 0x00000100 // Stream is read only +#define STREAM_FLAG_WRITE_SHARE 0x00000200 // Allow write sharing when open for write +#define STREAM_FLAG_MASK 0x0000FF00 // Mask for stream flags +#define STREAM_OPTIONS_MASK 0x0000FFFF // Mask for all stream options + +#define MPQ_OPEN_NO_LISTFILE 0x00010000 // Don't load the internal listfile +#define MPQ_OPEN_NO_ATTRIBUTES 0x00020000 // Don't open the attributes +#define MPQ_OPEN_FORCE_MPQ_V1 0x00040000 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header +#define MPQ_OPEN_CHECK_SECTOR_CRC 0x00080000 // On files with MPQ_FILE_SECTOR_CRC, the CRC will be checked when reading file + +// Deprecated +#define MPQ_OPEN_READ_ONLY STREAM_FLAG_READ_ONLY +#define MPQ_OPEN_ENCRYPTED STREAM_PROVIDER_ENCRYPTED // Flags for SFileCreateArchive -#define MPQ_CREATE_ATTRIBUTES 0x00000001 // Also add the (attributes) file -#define MPQ_CREATE_ARCHIVE_V1 0x00000000 // Creates archive of version 1 (size up to 4GB) -#define MPQ_CREATE_ARCHIVE_V2 0x00010000 // Creates archive of version 2 (larger than 4 GB) -#define MPQ_CREATE_ARCHIVE_V3 0x00020000 // Creates archive of version 3 -#define MPQ_CREATE_ARCHIVE_V4 0x00030000 // Creates archive of version 4 -#define MPQ_CREATE_ARCHIVE_VMASK 0x000F0000 // Mask for archive version +#define MPQ_CREATE_ATTRIBUTES 0x00100000 // Also add the (attributes) file +#define MPQ_CREATE_ARCHIVE_V1 0x00000000 // Creates archive of version 1 (size up to 4GB) +#define MPQ_CREATE_ARCHIVE_V2 0x01000000 // Creates archive of version 2 (larger than 4 GB) +#define MPQ_CREATE_ARCHIVE_V3 0x02000000 // Creates archive of version 3 +#define MPQ_CREATE_ARCHIVE_V4 0x03000000 // Creates archive of version 4 +#define MPQ_CREATE_ARCHIVE_VMASK 0x0F000000 // Mask for archive version + +#define FLAGS_TO_FORMAT_SHIFT 24 // (MPQ_CREATE_ARCHIVE_V4 >> FLAGS_TO_FORMAT_SHIFT) => MPQ_FORMAT_VERSION_4 // Flags for SFileVerifyFile -#define SFILE_VERIFY_SECTOR_CRC 0x0001 // Verify sector checksum for the file, if available -#define SFILE_VERIFY_FILE_CRC 0x0002 // Verify file CRC, if available -#define SFILE_VERIFY_FILE_MD5 0x0004 // Verify file MD5, if available -#define SFILE_VERIFY_RAW_MD5 0x0008 // Verify raw file MD5, if available -#define SFILE_VERIFY_ALL 0x000F // Verify every checksum possible +#define SFILE_VERIFY_SECTOR_CRC 0x00000001 // Verify sector checksum for the file, if available +#define SFILE_VERIFY_FILE_CRC 0x00000002 // Verify file CRC, if available +#define SFILE_VERIFY_FILE_MD5 0x00000004 // Verify file MD5, if available +#define SFILE_VERIFY_RAW_MD5 0x00000008 // Verify raw file MD5, if available +#define SFILE_VERIFY_ALL 0x0000000F // Verify every checksum possible // Return values for SFileVerifyFile -#define VERIFY_OPEN_ERROR 0x0001 // Failed to open the file -#define VERIFY_READ_ERROR 0x0002 // Failed to read all data from the file -#define VERIFY_FILE_HAS_SECTOR_CRC 0x0004 // File has sector CRC -#define VERIFY_FILE_SECTOR_CRC_ERROR 0x0008 // Sector CRC check failed -#define VERIFY_FILE_HAS_CHECKSUM 0x0010 // File has CRC32 -#define VERIFY_FILE_CHECKSUM_ERROR 0x0020 // CRC32 check failed -#define VERIFY_FILE_HAS_MD5 0x0040 // File has data MD5 -#define VERIFY_FILE_MD5_ERROR 0x0080 // MD5 check failed -#define VERIFY_FILE_HAS_RAW_MD5 0x0100 // File has raw data MD5 -#define VERIFY_FILE_RAW_MD5_ERROR 0x0200 // Raw MD5 check failed +#define VERIFY_OPEN_ERROR 0x0001 // Failed to open the file +#define VERIFY_READ_ERROR 0x0002 // Failed to read all data from the file +#define VERIFY_FILE_HAS_SECTOR_CRC 0x0004 // File has sector CRC +#define VERIFY_FILE_SECTOR_CRC_ERROR 0x0008 // Sector CRC check failed +#define VERIFY_FILE_HAS_CHECKSUM 0x0010 // File has CRC32 +#define VERIFY_FILE_CHECKSUM_ERROR 0x0020 // CRC32 check failed +#define VERIFY_FILE_HAS_MD5 0x0040 // File has data MD5 +#define VERIFY_FILE_MD5_ERROR 0x0080 // MD5 check failed +#define VERIFY_FILE_HAS_RAW_MD5 0x0100 // File has raw data MD5 +#define VERIFY_FILE_RAW_MD5_ERROR 0x0200 // Raw MD5 check failed #define VERIFY_FILE_ERROR_MASK (VERIFY_OPEN_ERROR | VERIFY_READ_ERROR | VERIFY_FILE_SECTOR_CRC_ERROR | VERIFY_FILE_CHECKSUM_ERROR | VERIFY_FILE_MD5_ERROR | VERIFY_FILE_RAW_MD5_ERROR) // Flags for SFileVerifyRawData (for MPQs version 4.0 or higher) -#define SFILE_VERIFY_MPQ_HEADER 0x0001 // Verify raw MPQ header -#define SFILE_VERIFY_HET_TABLE 0x0002 // Verify raw data of the HET table -#define SFILE_VERIFY_BET_TABLE 0x0003 // Verify raw data of the BET table -#define SFILE_VERIFY_HASH_TABLE 0x0004 // Verify raw data of the hash table -#define SFILE_VERIFY_BLOCK_TABLE 0x0005 // Verify raw data of the block table -#define SFILE_VERIFY_HIBLOCK_TABLE 0x0006 // Verify raw data of the hi-block table -#define SFILE_VERIFY_FILE 0x0007 // Verify raw data of a file +#define SFILE_VERIFY_MPQ_HEADER 0x0001 // Verify raw MPQ header +#define SFILE_VERIFY_HET_TABLE 0x0002 // Verify raw data of the HET table +#define SFILE_VERIFY_BET_TABLE 0x0003 // Verify raw data of the BET table +#define SFILE_VERIFY_HASH_TABLE 0x0004 // Verify raw data of the hash table +#define SFILE_VERIFY_BLOCK_TABLE 0x0005 // Verify raw data of the block table +#define SFILE_VERIFY_HIBLOCK_TABLE 0x0006 // Verify raw data of the hi-block table +#define SFILE_VERIFY_FILE 0x0007 // Verify raw data of a file // Return values for SFileVerifyArchive -#define ERROR_NO_SIGNATURE 0 // There is no signature in the MPQ -#define ERROR_VERIFY_FAILED 1 // There was an error during verifying signature (like no memory) -#define ERROR_WEAK_SIGNATURE_OK 2 // There is a weak signature and sign check passed -#define ERROR_WEAK_SIGNATURE_ERROR 3 // There is a weak signature but sign check failed -#define ERROR_STRONG_SIGNATURE_OK 4 // There is a strong signature and sign check passed -#define ERROR_STRONG_SIGNATURE_ERROR 5 // There is a strong signature but sign check failed - +#define ERROR_NO_SIGNATURE 0 // There is no signature in the MPQ +#define ERROR_VERIFY_FAILED 1 // There was an error during verifying signature (like no memory) +#define ERROR_WEAK_SIGNATURE_OK 2 // There is a weak signature and sign check passed +#define ERROR_WEAK_SIGNATURE_ERROR 3 // There is a weak signature but sign check failed +#define ERROR_STRONG_SIGNATURE_OK 4 // There is a strong signature and sign check passed +#define ERROR_STRONG_SIGNATURE_ERROR 5 // There is a strong signature but sign check failed + #ifndef MD5_DIGEST_SIZE -#define MD5_DIGEST_SIZE 0x10 +#define MD5_DIGEST_SIZE 0x10 #endif #ifndef SHA1_DIGEST_SIZE -#define SHA1_DIGEST_SIZE 0x14 // 160 bits +#define SHA1_DIGEST_SIZE 0x14 // 160 bits #endif #ifndef LANG_NEUTRAL -#define LANG_NEUTRAL 0x00 // Neutral locale +#define LANG_NEUTRAL 0x00 // Neutral locale #endif //----------------------------------------------------------------------------- // Callback functions // Values for compact callback -#define CCB_CHECKING_FILES 1 // Checking archive (dwParam1 = current, dwParam2 = total) -#define CCB_CHECKING_HASH_TABLE 2 // Checking hash table (dwParam1 = current, dwParam2 = total) -#define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used -#define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total) -#define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used - +#define CCB_CHECKING_FILES 1 // Checking archive (dwParam1 = current, dwParam2 = total) +#define CCB_CHECKING_HASH_TABLE 2 // Checking hash table (dwParam1 = current, dwParam2 = total) +#define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used +#define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total) +#define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used + typedef void (WINAPI * SFILE_ADDFILE_CALLBACK)(void * pvUserData, DWORD dwBytesWritten, DWORD dwTotalBytes, bool bFinalCall); typedef void (WINAPI * SFILE_COMPACT_CALLBACK)(void * pvUserData, DWORD dwWorkType, ULONGLONG BytesProcessed, ULONGLONG TotalBytes); -//----------------------------------------------------------------------------- -// Stream support - structures - struct TFileStream; -typedef bool (*STREAM_GETPOS)( - struct TFileStream * pStream, // Pointer to an open stream - ULONGLONG & ByteOffset // Pointer to store current file position - ); - -typedef bool (*STREAM_READ)( - struct TFileStream * pStream, // Pointer to an open stream - ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position - void * pvBuffer, // Pointer to data to be read - DWORD dwBytesToRead // Number of bytes to read from the file - ); - -typedef bool (*STREAM_WRITE)( - struct TFileStream * pStream, // Pointer to an open stream - ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it writes to the current position - const void * pvBuffer, // Pointer to data to be written - DWORD dwBytesToWrite // Number of bytes to read from the file - ); - -typedef bool (*STREAM_GETSIZE)( - struct TFileStream * pStream, // Pointer to an open stream - ULONGLONG & FileSize // Receives the file size, in bytes - ); - -typedef bool (*STREAM_SETSIZE)( - struct TFileStream * pStream, // Pointer to an open stream - ULONGLONG FileSize // New size for the file, in bytes - ); - -// Common stream structure. Can be variable length -struct TFileStream -{ - ULONGLONG RawFilePos; // Current position in raw file - HANDLE hFile; // File handle. Do not use directly. - TCHAR szFileName[MAX_PATH];// Name of the file - BYTE StreamFlags; // See STREAM_FLAG_XXXX - - STREAM_GETPOS StreamGetPos; // Pointer to function that returns current file position - STREAM_READ StreamRead; // Pointer to stream read function for this archive. Do not use directly. - STREAM_WRITE StreamWrite; // Pointer to stream write function for this archive. Do not use directly. - STREAM_GETSIZE StreamGetSize; // Pointer to function returning file size - STREAM_SETSIZE StreamSetSize; // Pointer to function changing file size - - // Extra members may follow -}; - //----------------------------------------------------------------------------- // Structure for bit arrays used for HET and BET tables @@ -422,8 +385,21 @@ struct TBitArray void GetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize); void SetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultSize); - DWORD NumberOfBits; // Total number of bits that are available - BYTE Elements[1]; // Array of elements (variable length) + DWORD NumberOfBits; // Total number of bits that are available + BYTE Elements[1]; // Array of elements (variable length) +}; + +// Structure for file bitmap. Used by SFileGetArchiveBitmap +struct TFileBitmap +{ + ULONGLONG StartOffset; // Starting offset of the file, covered by bitmap + ULONGLONG EndOffset; // Ending offset of the file, covered by bitmap + DWORD IsComplete; // If nonzero, no blocks are missing + DWORD BitmapSize; // Size of the file bitmap (in bytes) + DWORD BlockSize; // Size of one block, in bytes + DWORD Reserved; // Alignment + + // Followed by file bitmap (variable length), array of BYTEs) }; //----------------------------------------------------------------------------- @@ -465,10 +441,10 @@ struct TMPQUserData struct TMPQHeader { // The ID_MPQ ('MPQ\x1A') signature - DWORD dwID; + DWORD dwID; // Size of the archive header - DWORD dwHeaderSize; + DWORD dwHeaderSize; // 32-bit size of MPQ archive // This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive @@ -488,14 +464,14 @@ struct TMPQHeader // Offset to the beginning of the hash table, relative to the beginning of the archive. DWORD dwHashTablePos; - + // Offset to the beginning of the block table, relative to the beginning of the archive. DWORD dwBlockTablePos; - + // Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for // the original MoPaQ format, or less than 2^20 for the Burning Crusade format. DWORD dwHashTableSize; - + // Number of entries in the block table DWORD dwBlockTableSize; @@ -540,7 +516,7 @@ struct TMPQHeader // Size of raw data chunk to calculate MD5. // MD5 of each data chunk follows the raw file data. - DWORD dwRawChunkSize; + DWORD dwRawChunkSize; // MD5 of MPQ tables unsigned char MD5_BlockTable[MD5_DIGEST_SIZE]; // MD5 of the block table before decryption @@ -558,7 +534,7 @@ struct TMPQHash { // The hash of the file path, using method A. DWORD dwName1; - + // The hash of the file path, using method B. DWORD dwName2; @@ -595,30 +571,30 @@ struct TMPQBlock { // Offset of the beginning of the file, relative to the beginning of the archive. DWORD dwFilePos; - + // Compressed file size DWORD dwCSize; - + // Only valid if the block is a file; otherwise meaningless, and should be 0. // If the file is compressed, this is the size of the uncompressed file data. - DWORD dwFSize; - + DWORD dwFSize; + // Flags for the file. See MPQ_FILE_XXXX constants - DWORD dwFlags; + DWORD dwFlags; }; // Patch file information, preceding the sector offset table struct TPatchInfo { - DWORD dwLength; // Length of patch info header, in bytes - DWORD dwFlags; // Flags. 0x80000000 = MD5 (?) - DWORD dwDataSize; // Uncompressed size of the patch file - BYTE md5[0x10]; // MD5 of the entire patch file after decompression + DWORD dwLength; // Length of patch info header, in bytes + DWORD dwFlags; // Flags. 0x80000000 = MD5 (?) + DWORD dwDataSize; // Uncompressed size of the patch file + BYTE md5[0x10]; // MD5 of the entire patch file after decompression // Followed by the sector table (variable length) }; -// Header for PTCH files +// Header for PTCH files struct TPatchHeader { //-- PATCH header ----------------------------------- @@ -626,7 +602,7 @@ struct TPatchHeader DWORD dwSizeOfPatchData; // Size of the entire patch (decompressed) DWORD dwSizeBeforePatch; // Size of the file before patch DWORD dwSizeAfterPatch; // Size of file after patch - + //-- MD5 block -------------------------------------- DWORD dwMD5; // 'MD5_' DWORD dwMd5BlockSize; // Size of the MD5 block, including the signature and size itself @@ -666,54 +642,70 @@ struct TFileEntry // Common header for HET and BET tables struct TMPQExtTable { - DWORD dwSignature; // 'HET\x1A' or 'BET\x1A' - DWORD dwVersion; // Version. Seems to be always 1 - DWORD dwDataSize; // Size of the contained table + DWORD dwSignature; // 'HET\x1A' or 'BET\x1A' + DWORD dwVersion; // Version. Seems to be always 1 + DWORD dwDataSize; // Size of the contained table // Followed by the table header // Followed by the table data }; +// +// MPQ data bitmap, can be found at (FileSize - sizeof(TMPQBlockMap)) +// +// There is bit map of the entire MPQ before TMPQBitmap. Each 0x4000-byte +// block is represented by one bit (including the last, eventually incomplete block). +// +struct TMPQBitmap +{ + DWORD dwSignature; // 'ptv3' (MPQ_BLOCK_MAP_SIGNATURE) + DWORD dwAlways3; // Unknown, seems to always have value of 3 + DWORD dwBuildNumber; // Game build number for that MPQ + DWORD dwMapOffsetLo; // Low 32-bits of the offset of the bit map + DWORD dwMapOffsetHi; // High 32-bits of the offset of the bit map + DWORD dwBlockSize; // Size of one block (usually 0x4000 bytes) +}; + // Structure for parsed HET table struct TMPQHetTable { - TBitArray * pBetIndexes; // Bit array of indexes to BET tables - LPBYTE pHetHashes; // Array of HET hashes. Each entry has size of 1 byte - ULONGLONG AndMask64; // AND mask used for calculating file name hash - ULONGLONG OrMask64; // OR mask used for setting the highest bit of the file name hash - - DWORD dwIndexSizeTotal; // Total size of one entry in pBetIndexes (in bits) - DWORD dwIndexSizeExtra; // Extra bits in the entry in pBetIndexes - DWORD dwIndexSize; // Effective size of one entry in pBetIndexes (in bits) - DWORD dwMaxFileCount; // Maximum number of files in the MPQ - DWORD dwHashTableSize; // Number of entries in pBetHashes - DWORD dwHashBitSize; // Effective number of bits in the hash + TBitArray * pBetIndexes; // Bit array of indexes to BET tables + LPBYTE pHetHashes; // Array of HET hashes. Each entry has size of 1 byte + ULONGLONG AndMask64; // AND mask used for calculating file name hash + ULONGLONG OrMask64; // OR mask used for setting the highest bit of the file name hash + + DWORD dwIndexSizeTotal; // Total size of one entry in pBetIndexes (in bits) + DWORD dwIndexSizeExtra; // Extra bits in the entry in pBetIndexes + DWORD dwIndexSize; // Effective size of one entry in pBetIndexes (in bits) + DWORD dwMaxFileCount; // Maximum number of files in the MPQ + DWORD dwHashTableSize; // Number of entries in pBetHashes + DWORD dwHashBitSize; // Effective number of bits in the hash }; // Structure for parsed BET table struct TMPQBetTable { - TBitArray * pBetHashes; // Array of BET hashes - TBitArray * pFileTable; // Bit-based file table - LPDWORD pFileFlags; // Array of file flags - - DWORD dwTableEntrySize; // Size of one table entry, in bits - DWORD dwBitIndex_FilePos; // Bit index of the file position in the table entry - DWORD dwBitIndex_FileSize; // Bit index of the file size in the table entry - DWORD dwBitIndex_CmpSize; // Bit index of the compressed size in the table entry - DWORD dwBitIndex_FlagIndex; // Bit index of the flag index in the table entry - DWORD dwBitIndex_Unknown; // Bit index of ??? in the table entry - DWORD dwBitCount_FilePos; // Size of file offset (in bits) within table entry - DWORD dwBitCount_FileSize; // Size of file size (in bits) within table entry - DWORD dwBitCount_CmpSize; // Size of compressed file size (in bits) within table entry - DWORD dwBitCount_FlagIndex; // Size of flag index (in bits) within table entry - DWORD dwBitCount_Unknown; // Size of ??? (in bits) within table entry - DWORD dwBetHashSizeTotal; // Total size of bet hash - DWORD dwBetHashSizeExtra; // Extra bits in the bet hash - DWORD dwBetHashSize; // Effective size of the bet hash - DWORD dwFileCount; // Number of files (usually equal to maximum number of files) - DWORD dwFlagCount; // Number of entries in pFileFlags + TBitArray * pBetHashes; // Array of BET hashes + TBitArray * pFileTable; // Bit-based file table + LPDWORD pFileFlags; // Array of file flags + + DWORD dwTableEntrySize; // Size of one table entry, in bits + DWORD dwBitIndex_FilePos; // Bit index of the file position in the table entry + DWORD dwBitIndex_FileSize; // Bit index of the file size in the table entry + DWORD dwBitIndex_CmpSize; // Bit index of the compressed size in the table entry + DWORD dwBitIndex_FlagIndex; // Bit index of the flag index in the table entry + DWORD dwBitIndex_Unknown; // Bit index of ??? in the table entry + DWORD dwBitCount_FilePos; // Size of file offset (in bits) within table entry + DWORD dwBitCount_FileSize; // Size of file size (in bits) within table entry + DWORD dwBitCount_CmpSize; // Size of compressed file size (in bits) within table entry + DWORD dwBitCount_FlagIndex; // Size of flag index (in bits) within table entry + DWORD dwBitCount_Unknown; // Size of ??? (in bits) within table entry + DWORD dwBetHashSizeTotal; // Total size of bet hash + DWORD dwBetHashSizeExtra; // Extra bits in the bet hash + DWORD dwBetHashSize; // Effective size of the bet hash + DWORD dwFileCount; // Number of files (usually equal to maximum number of files) + DWORD dwFlagCount; // Number of entries in pFileFlags }; // Archive handle structure @@ -731,10 +723,11 @@ struct TMPQArchive TMPQUserData * pUserData; // MPQ user data (NULL if not present in the file) TMPQHeader * pHeader; // MPQ file header + TMPQBitmap * pBitmap; // MPQ bitmap TMPQHash * pHashTable; // Hash table TMPQHetTable * pHetTable; // Het table TFileEntry * pFileTable; // File table - + TMPQUserData UserData; // MPQ user data. Valid only when ID_MPQ_USERDATA has been found BYTE HeaderData[MPQ_HEADER_SIZE_V4]; // Storage for MPQ header @@ -747,7 +740,7 @@ struct TMPQArchive DWORD dwFileFlags2; // Flags for (attributes) DWORD dwAttrFlags; // Flags for the (attributes) file, see MPQ_ATTRIBUTE_XXX DWORD dwFlags; // See MPQ_FLAG_XXXXX -}; +}; // File handle structure struct TMPQFile @@ -767,7 +760,7 @@ struct TMPQFile DWORD cbFileData; // Size of loaded patched data TPatchInfo * pPatchInfo; // Patch info block, preceding the sector table - DWORD * SectorOffsets; // Position of each file sector, relative to the begin of the file. Only for compressed files. + DWORD * SectorOffsets; // Position of each file sector, relative to the begin of the file. Only for compressed files. DWORD * SectorChksums; // Array of sector checksums (either ADLER32 or MD5) values for each file sector DWORD dwSectorCount; // Number of sectors in the file DWORD dwPatchedFileSize; // Size of patched file. Used when saving patch file to the MPQ @@ -779,7 +772,6 @@ struct TMPQFile unsigned char hctx[HASH_STATE_SIZE];// Hash state for MD5. Used when saving file to MPQ DWORD dwCrc32; // CRC32 value, used when saving file to MPQ - BYTE PreviousCompression; // Compression of previous sector bool bLoadedSectorCRCs; // If true, we already tried to load sector CRCs bool bCheckSectorCRCs; // If true, then SFileReadFile will check sector CRCs when reading the file @@ -803,19 +795,39 @@ typedef struct _SFILE_FIND_DATA } SFILE_FIND_DATA, *PSFILE_FIND_DATA; +typedef struct _SFILE_CREATE_MPQ +{ + DWORD cbSize; // Size of this structure, in bytes + DWORD dwMpqVersion; // Version of the MPQ to be created + void *pvUserData; // Reserved, must be NULL + DWORD cbUserData; // Reserved, must be 0 + DWORD dwStreamFlags; // Stream flags for creating the MPQ + DWORD dwFileFlags1; // File flags for (listfile). 0 = default + DWORD dwFileFlags2; // File flags for (attributes). 0 = default + DWORD dwAttrFlags; // Flags for the (attributes) file. If 0, no attributes will be created + DWORD dwSectorSize; // Sector size for compressed files + DWORD dwRawChunkSize; // Size of raw data chunk + DWORD dwMaxFileCount; // File limit for the MPQ + +} SFILE_CREATE_MPQ, *PSFILE_CREATE_MPQ; + //----------------------------------------------------------------------------- // Stream support - functions -TFileStream * FileStream_CreateFile(const TCHAR * szFileName); -TFileStream * FileStream_OpenFile(const TCHAR * szFileName, bool bWriteAccess); -TFileStream * FileStream_OpenEncrypted(const TCHAR * szFileName); -bool FileStream_GetPos(TFileStream * pStream, ULONGLONG & ByteOffset); +TFileStream * FileStream_CreateFile(const TCHAR * szFileName, DWORD dwStreamFlags); +TFileStream * FileStream_OpenFile(const TCHAR * szFileName, DWORD dwStreamFlags); +TCHAR * FileStream_GetFileName(TFileStream * pStream); +bool FileStream_IsReadOnly(TFileStream * pStream); bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead); bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite); -bool FileStream_GetLastWriteTime(TFileStream * pStream, ULONGLONG * pFT); +bool FileStream_GetPos(TFileStream * pStream, ULONGLONG & ByteOffset); +bool FileStream_SetPos(TFileStream * pStream, ULONGLONG ByteOffset); bool FileStream_GetSize(TFileStream * pStream, ULONGLONG & FileSize); bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize); -bool FileStream_MoveFile(TFileStream * pStream, TFileStream * pTempStream); +bool FileStream_GetTime(TFileStream * pStream, ULONGLONG * pFT); +bool FileStream_Switch(TFileStream * pStream, TFileStream * pTempStream); +bool FileStream_SetBitmap(TFileStream * pStream, TFileBitmap * pBitmap); +bool FileStream_GetBitmap(TFileStream * pStream, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded); void FileStream_Close(TFileStream * pStream); //----------------------------------------------------------------------------- @@ -834,12 +846,6 @@ typedef bool (WINAPI * SFILEREADFILE)(HANDLE, void *, DWORD, LPDWORD, LPOVERLAP //----------------------------------------------------------------------------- // Functions for manipulation with StormLib global flags -#define SFILE_FLAG_ALLOW_WRITE_SHARE 0x00000001 // When a MPQ is open for write by StormLib, - // it is allowed to open it for write with another application. - -DWORD WINAPI SFileGetGlobalFlags(); -DWORD WINAPI SFileSetGlobalFlags(DWORD dwNewFlags); - LCID WINAPI SFileGetLocale(); LCID WINAPI SFileSetLocale(LCID lcNewLocale); @@ -848,7 +854,9 @@ LCID WINAPI SFileSetLocale(LCID lcNewLocale); bool WINAPI SFileOpenArchive(const TCHAR * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMpq); bool WINAPI SFileCreateArchive(const TCHAR * szMpqName, DWORD dwFlags, DWORD dwMaxFileCount, HANDLE * phMpq); +bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCreateInfo, HANDLE * phMpq); +bool WINAPI SFileGetArchiveBitmap(HANDLE hMpq, TFileBitmap * pBitmap, DWORD Length, LPDWORD LengthNeeded); bool WINAPI SFileFlushArchive(HANDLE hMpq); bool WINAPI SFileCloseArchive(HANDLE hMpq); @@ -931,9 +939,9 @@ bool WINAPI SFileCreateFile(HANDLE hMpq, const char * szArchivedName, ULONGLON bool WINAPI SFileWriteFile(HANDLE hFile, const void * pvData, DWORD dwSize, DWORD dwCompression); bool WINAPI SFileFinishFile(HANDLE hFile); -bool WINAPI SFileAddFileEx(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwCompression, DWORD dwCompressionNext = 0xFFFFFFFF); -bool WINAPI SFileAddFile(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags); -bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality); +bool WINAPI SFileAddFileEx(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwCompression, DWORD dwCompressionNext = MPQ_COMPRESSION_NEXT_SAME); +bool WINAPI SFileAddFile(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags); +bool WINAPI SFileAddWave(HANDLE hMpq, const TCHAR * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality); bool WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope = SFILE_OPEN_FROM_MPQ); bool WINAPI SFileRenameFile(HANDLE hMpq, const char * szOldFileName, const char * szNewFileName); bool WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale); @@ -948,6 +956,7 @@ int WINAPI SCompImplode (char * pbOutBuffer, int * pcbOutBuffer, char * pb int WINAPI SCompExplode (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer); int WINAPI SCompCompress (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer, unsigned uCompressionMask, int nCmpType, int nCmpLevel); int WINAPI SCompDecompress (char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer); +int WINAPI SCompDecompress2(char * pbOutBuffer, int * pcbOutBuffer, char * pbInBuffer, int cbInBuffer); //----------------------------------------------------------------------------- // Non-Windows support for SetLastError/GetLastError diff --git a/dep/StormLib/src/StormPort.h b/dep/StormLib/src/StormPort.h index a8f5835bdfb..0914654b9af 100644 --- a/dep/StormLib/src/StormPort.h +++ b/dep/StormLib/src/StormPort.h @@ -46,6 +46,7 @@ #include <ctype.h> #include <stdio.h> #include <windows.h> + #include <wininet.h> #define PLATFORM_LITTLE_ENDIAN #ifdef WIN64 @@ -59,20 +60,26 @@ #endif -// Defines for Mac Carbon -#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac Carbon API +// Defines for Mac +#if !defined(PLATFORM_DEFINED) && defined(__APPLE__) // Mac BSD API - // Macintosh using Carbon - #include <Carbon/Carbon.h> // Mac OS X + // Macintosh + #include <sys/types.h> + #include <sys/stat.h> + #include <sys/mman.h> + #include <unistd.h> + #include <fcntl.h> + #include <stdlib.h> + #include <errno.h> #define PKEXPORT #define __SYS_ZLIB #define __SYS_BZLIB #ifndef __BIG_ENDIAN__ - #define PLATFORM_LITTLE_ENDIAN // Apple is now making Macs with Intel CPUs + #define PLATFORM_LITTLE_ENDIAN #endif - + #define PLATFORM_MAC #define PLATFORM_DEFINED // The platform is known now @@ -83,6 +90,7 @@ #include <sys/types.h> #include <sys/stat.h> + #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <stdint.h> @@ -152,29 +160,21 @@ #define _stricmp strcasecmp #define _strnicmp strncasecmp + #define _tcsnicmp strncasecmp #endif // !WIN32 -// Platform-specific error codes -#ifdef PLATFORM_MAC - #define ERROR_SUCCESS noErr - #define ERROR_FILE_NOT_FOUND fnfErr - #define ERROR_ACCESS_DENIED permErr - #define ERROR_INVALID_HANDLE rfNumErr - #define ERROR_NOT_ENOUGH_MEMORY mFulErr - #define ERROR_BAD_FORMAT 200 // Returned when the opened file is in format that is not recognized by StormLib - #define ERROR_NO_MORE_FILES errFSNoMoreItems - #define ERROR_HANDLE_EOF eofErr - #define ERROR_NOT_SUPPORTED 201 - #define ERROR_INVALID_PARAMETER paramErr - #define ERROR_DISK_FULL dskFulErr - #define ERROR_ALREADY_EXISTS dupFNErr - #define ERROR_CAN_NOT_COMPLETE 202 // A generic error, when any operation fails from an unknown reason - #define ERROR_FILE_CORRUPT 203 // At any point when there is bad data format in the file - #define ERROR_INSUFFICIENT_BUFFER errFSBadBuffer +// 64-bit calls are supplied by "normal" calls on Mac +#if defined(PLATFORM_MAC) + #define stat64 stat + #define fstat64 fstat + #define lseek64 lseek + #define off64_t off_t + #define O_LARGEFILE 0 #endif -#ifdef PLATFORM_LINUX +// Platform-specific error codes for UNIX-based platforms +#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX) #define ERROR_SUCCESS 0 #define ERROR_FILE_NOT_FOUND ENOENT #define ERROR_ACCESS_DENIED EPERM diff --git a/dep/StormLib/src/adpcm/adpcm.cpp b/dep/StormLib/src/adpcm/adpcm.cpp index c43d2234c18..916fa3811a8 100644 --- a/dep/StormLib/src/adpcm/adpcm.cpp +++ b/dep/StormLib/src/adpcm/adpcm.cpp @@ -17,17 +17,17 @@ //------------------------------------------------------------------------------ // Structures -union TByteAndWordPtr +typedef union _BYTE_AND_WORD_PTR { short * pw; unsigned char * pb; -}; +} BYTE_AND_WORD_PTR; -union TWordAndByteArray +typedef union _WORD_AND_BYTE_ARRAY { short w; unsigned char b[2]; -}; +} WORD_AND_BYTE_ARRAY; //----------------------------------------------------------------------------- // Tables necessary dor decompression @@ -63,8 +63,8 @@ static long step_table[] = int CompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuffer, int dwInLength, int nChannels, int nCmpLevel) // ECX EDX { - TWordAndByteArray Wcmp; - TByteAndWordPtr out; // Pointer to the output buffer + WORD_AND_BYTE_ARRAY Wcmp; + BYTE_AND_WORD_PTR out; // Pointer to the output buffer long SInt32Array1[2]; long SInt32Array2[2]; long SInt32Array3[2]; @@ -83,6 +83,7 @@ int CompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuff int nLength; int nIndex; int nValue; + int i, chnl; // If less than 2 bytes remain, don't decompress anything // pbSaveOutBuffer = pbOutBuffer; @@ -99,7 +100,7 @@ int CompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuff SInt32Array1[0] = SInt32Array1[1] = 0x2C; - for(int i = 0; i < nChannels; i++) + for(i = 0; i < nChannels; i++) { nOneWord = BSWAP_INT16_SIGNED(*pwInBuffer++); *out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord); @@ -119,7 +120,7 @@ int CompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuff // ebx - nChannels // ecx - pwOutPos - for(int chnl = nChannels; chnl < nWordsRemains; chnl++) + for(chnl = nChannels; chnl < nWordsRemains; chnl++) { // 1500F030 if((out.pb - pbOutBuffer + 2) > nBytesRemains) @@ -223,14 +224,14 @@ int CompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, short * pwInBuff // 1500F230 int DecompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, unsigned char * pbInBuffer, int dwInLength, int nChannels) { - TByteAndWordPtr out; // Output buffer - TByteAndWordPtr in; + BYTE_AND_WORD_PTR out; // Output buffer + BYTE_AND_WORD_PTR in; unsigned char * pbInBufferEnd = (pbInBuffer + dwInLength); long SInt32Array1[2]; long SInt32Array2[2]; long nOneWord; - int dwOutLengthCopy = dwOutLength; int nIndex; + int i; SInt32Array1[0] = SInt32Array1[1] = 0x2C; out.pb = pbOutBuffer; @@ -238,15 +239,15 @@ int DecompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, unsigned char in.pw++; // Fill the Uint32Array2 array by channel values. - for(int i = 0; i < nChannels; i++) + for(i = 0; i < nChannels; i++) { nOneWord = BSWAP_INT16_SIGNED(*in.pw++); SInt32Array2[i] = nOneWord; - if(dwOutLengthCopy < 2) + if(dwOutLength < 2) return (int)(out.pb - pbOutBuffer); *out.pw++ = BSWAP_INT16_SIGNED((short)nOneWord); - dwOutLengthCopy -= sizeof(short); + dwOutLength -= sizeof(short); } // Get the initial index @@ -270,7 +271,7 @@ int DecompressADPCM(unsigned char * pbOutBuffer, int dwOutLength, unsigned char if(SInt32Array1[nIndex] != 0) SInt32Array1[nIndex]--; - if(dwOutLengthCopy < 2) + if(dwOutLength < 2) return (int)(out.pb - pbOutBuffer); *out.pw++ = BSWAP_INT16_SIGNED((unsigned short)SInt32Array2[nIndex]); diff --git a/dep/StormLib/src/huffman/huff.cpp b/dep/StormLib/src/huffman/huff.cpp index 34203a8108f..66a46b3fa55 100644 --- a/dep/StormLib/src/huffman/huff.cpp +++ b/dep/StormLib/src/huffman/huff.cpp @@ -263,10 +263,15 @@ static void InsertItem(THTreeItem ** itemPtr, THTreeItem * item, unsigned long n if(PTR_INVALID(prev2)) { - prev2 = PTR_NOT(prev); - - prev2->next = item; - item2->prev = item; // Next after last item + if(prev != NULL) + { + prev2 = PTR_NOT(prev); + if(prev2 != NULL) + { + prev2->next = item; + item2->prev = item; // Next after last item + } + } return; } @@ -1009,8 +1014,8 @@ unsigned int THuffmannTree::DoDecompression(unsigned char * pbOutBuffer, unsigne for(;;) { // Security check: If we are at the end of the input buffer, - // it means that the data are corrupt. - if(is->pbInBuffer > is->pbInBufferEnd) + // it means that the data is corrupt + if(is->BitCount == 0 && is->pbInBuffer >= is->pbInBufferEnd) return 0; // Get 7 bits from input stream @@ -1046,6 +1051,9 @@ _1500E549: do { + if(pItem1 == NULL) + return 0; + pItem1 = pItem1->child; // Move down by one level if(is->GetBit()) // If current bit is set, move to previous pItem1 = pItem1->prev; diff --git a/dep/StormLib/src/huffman/huff.h b/dep/StormLib/src/huffman/huff.h index 6af4ac638bb..83e9b2cdad0 100644 --- a/dep/StormLib/src/huffman/huff.h +++ b/dep/StormLib/src/huffman/huff.h @@ -65,8 +65,6 @@ class TOutputStream // Huffmann tree item (?) struct THTreeItem { - public: - THTreeItem * Call1501DB70(THTreeItem * pLast); THTreeItem * GetPrevItem(LONG_PTR value); void ClearItemLinks(); diff --git a/dep/StormLib/src/lzma/info.txt b/dep/StormLib/src/lzma/info.txt new file mode 100644 index 00000000000..4cee86e3542 --- /dev/null +++ b/dep/StormLib/src/lzma/info.txt @@ -0,0 +1 @@ +Taken from LZMA SDK v 9.11
\ No newline at end of file diff --git a/dep/StormLib/src/sparse/sparse.cpp b/dep/StormLib/src/sparse/sparse.cpp index 5b37f6d0f8e..6df7021fc8a 100644 --- a/dep/StormLib/src/sparse/sparse.cpp +++ b/dep/StormLib/src/sparse/sparse.cpp @@ -255,6 +255,10 @@ int DecompressSparse(unsigned char * pbOutBuffer, int * pcbOutBuffer, unsigned c OneByte = *pbInBuffer++; cbOutBuffer |= (OneByte << 0x00); + // Verify the size of the stream against the output buffer size + if(cbOutBuffer > *pcbOutBuffer) + return 0; + // Put the output size to the buffer *pcbOutBuffer = cbOutBuffer; diff --git a/dep/StormLib/stormlib_dll/StormLib.def b/dep/StormLib/stormlib_dll/StormLib.def index 2b00766ef9d..0ba91884313 100644 --- a/dep/StormLib/stormlib_dll/StormLib.def +++ b/dep/StormLib/stormlib_dll/StormLib.def @@ -8,13 +8,12 @@ LIBRARY StormLib.dll EXPORTS - SFileGetGlobalFlags - SFileSetGlobalFlags SFileSetLocale SFileGetLocale SFileOpenArchive SFileCreateArchive + SFileGetArchiveBitmap SFileFlushArchive SFileCloseArchive diff --git a/dep/StormLib/stormlib_dll/StormLib.exp b/dep/StormLib/stormlib_dll/StormLib.exp index aa2b71db1f1..aa18edb7aab 100644 --- a/dep/StormLib/stormlib_dll/StormLib.exp +++ b/dep/StormLib/stormlib_dll/StormLib.exp @@ -4,13 +4,12 @@ # swilkins1337@gmail.com # -_SFileGetGlobalFlags -_SFileSetGlobalFlags _SFileSetLocale _SFileGetLocale _SFileOpenArchive _SFileCreateArchive +_SFileGetArchiveBitmap _SFileFlushArchive _SFileCloseArchive diff --git a/dep/StormLib/test/Test.cpp b/dep/StormLib/test/Test.cpp index c061b34936f..e31c15fee29 100644 --- a/dep/StormLib/test/Test.cpp +++ b/dep/StormLib/test/Test.cpp @@ -36,7 +36,7 @@ #endif #ifdef PLATFORM_MAC -#define WORK_PATH_ROOT "/Users/sam/Downloads/" +#define WORK_PATH_ROOT "/Users/sam/StormLib/test" #endif #ifndef LANG_CZECH @@ -472,6 +472,29 @@ static int TestPartFileRead(const TCHAR * szFileName) } //----------------------------------------------------------------------------- +// Compare PKLIB decompression + +BYTE pbCompressed1[] = {0x00, 0x04, 0x00, 0x00, 0x04, 0xF0, 0x1F, 0x7B, 0x01, 0xFF}; +BYTE pbCompressed2[] = {0x00, 0x04, 0x00, 0x00, 0x04, 0xF0, 0x1F, 0x00, 0x00, 0x04, 0xFC, 0x03}; + +static int ComparePklibCompressions() +{ + char Decompressed[0x1000]; + char Compressed[0x1000]; + int cbDecompressed = 0x208; + int cbCompressed = sizeof(Compressed); + + memset(Decompressed, 0, cbDecompressed); + SCompImplode(Compressed, &cbCompressed, Decompressed, cbDecompressed); + + cbDecompressed = sizeof(Decompressed); + SCompExplode(Decompressed, &cbDecompressed, Compressed, cbCompressed); + + + return ERROR_SUCCESS; +} + +//----------------------------------------------------------------------------- // Compare LZMA decompression #ifdef PLATFORM_WINDOWS @@ -713,7 +736,7 @@ __TryAgain: static int TestArchiveOpenAndClose(const TCHAR * szMpqName) { - const char * szFileName1 = "world\\maps\\AhnQiraj\\AhnQiraj_27_51_tex1.adt"; + const char * szFileName1 = "DBFilesClient\\Item.dbc"; // const char * szFileName2 = "items\\map\\mapz_deleted.cel"; TMPQArchive * ha = NULL; HANDLE hFile1 = NULL; @@ -724,7 +747,7 @@ static int TestArchiveOpenAndClose(const TCHAR * szMpqName) if(nError == ERROR_SUCCESS) { _tprintf(_T("Opening archive %s ...\n"), szMpqName); - if(!SFileOpenArchive(szMpqName, 0, 0, /* MPQ_OPEN_ENCRYPTED,*/ &hMpq)) + if(!SFileOpenArchive(szMpqName, 0, STREAM_PROVIDER_ENCRYPTED | BASE_PROVIDER_FILE, &hMpq)) nError = GetLastError(); ha = (TMPQArchive *)hMpq; } @@ -866,7 +889,7 @@ static int TestMpqCompacting(const TCHAR * szMpqName) if(nError == ERROR_SUCCESS) { - char * szFileName = "Shaders\\Effects\\shadowmap.wfx"; + const char * szFileName = "Shaders\\Effects\\shadowmap.wfx"; printf("Deleting file %s ...\r", szFileName); if(!SFileRemoveFile(hMpq, szFileName)) @@ -904,7 +927,7 @@ static int TestCreateArchive(const TCHAR * szMpqName) // Create the new file _tprintf(_T("Creating %s ...\n"), szMpqName); - pStream = FileStream_CreateFile(szMpqName); + pStream = FileStream_CreateFile(szMpqName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); if(pStream == NULL) nError = GetLastError(); @@ -1305,7 +1328,7 @@ static int TestCreateArchiveCopy(const TCHAR * szMpqName, const TCHAR * szMpqCop szListFile = NULL; // Create the new file - pStream = FileStream_CreateFile(szMpqCopyName); + pStream = FileStream_CreateFile(szMpqCopyName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); if(pStream == NULL) nError = GetLastError(); @@ -1396,6 +1419,131 @@ static int TestCreateArchiveCopy(const TCHAR * szMpqName, const TCHAR * szMpqCop return nError; } +static int TestOpenPatchedArchive(const TCHAR * szMpqName, ...) +{ + TFileStream * pStream; + HANDLE hFile = NULL; + HANDLE hMpq = NULL; + va_list argList; + const char * szFileName = "World\\Minimaps\\Azeroth\\noLiquid_map20_44.blp"; + TCHAR szLocFileName[MAX_PATH]; + LPBYTE pbFullFile = NULL; + DWORD dwFileSize; + int nError = ERROR_SUCCESS; + + // Open the primary MPQ + _tprintf(_T("Opening %s ...\n"), szMpqName); + if(!SFileOpenArchive(szMpqName, 0, MPQ_OPEN_READ_ONLY, &hMpq)) + { + nError = GetLastError(); + _tprintf(_T("Failed to open the archive %s ...\n"), szMpqName); + } + + // Add all patches + if(nError == ERROR_SUCCESS) + { + va_start(argList, szMpqName); + while((szMpqName = va_arg(argList, const TCHAR *)) != NULL) + { + _tprintf(_T("Adding patch %s ...\n"), szMpqName); + if(!SFileOpenPatchArchive(hMpq, szMpqName, NULL, 0)) + { + nError = GetLastError(); + printf("Failed to add patch %s ...\n", szMpqName); + } + } + va_end(argList); + } + + // Now search all files + if(nError == ERROR_SUCCESS) + { + SFILE_FIND_DATA sf; + HANDLE hFind; + bool bResult = true; + + hFind = SFileFindFirstFile(hMpq, "World\\Minimaps\\Azeroth\\noLiquid_map20_44.*", &sf, NULL); + while(hFind && bResult) + { + printf("%s\n", sf.cFileName); + bResult = SFileFindNextFile(hFind, &sf); + } + } + + // Now try to open patched version of a file + if(nError == ERROR_SUCCESS) + { + SFileExtractFile(hMpq, szFileName, _T("E:\\noLiquid_map20_44.blp")); + } + + // Now try to open patched version of "Achievement.dbc" + if(nError == ERROR_SUCCESS) + { + printf("Opening patched file \"%s\" ...\n", szFileName); + SFileVerifyFile(hMpq, szFileName, SFILE_VERIFY_RAW_MD5); + if(!SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_PATCHED_FILE, &hFile)) + { + nError = GetLastError(); + printf("Failed to open patched file \"%s\"\n", szFileName); + } + } + + // Verify of the patched version is correct + if(nError == ERROR_SUCCESS) + { + TCHAR * szPatchChain = NULL; + DWORD cbPatchChain = 0; + + // Get the patch chain + SFileGetFileInfo(hFile, SFILE_INFO_PATCH_CHAIN, szPatchChain, cbPatchChain, &cbPatchChain); + szPatchChain = (TCHAR *)(new BYTE[cbPatchChain]); + SFileGetFileInfo(hFile, SFILE_INFO_PATCH_CHAIN, szPatchChain, cbPatchChain, &cbPatchChain); + delete [] szPatchChain; + + // Get the size of the full patched file + dwFileSize = SFileGetFileSize(hFile, NULL); + if(dwFileSize != 0) + { + DWORD dwBytesRead = 0; + BYTE TempData[0x100]; + + SFileReadFile(hFile, TempData, sizeof(TempData), &dwBytesRead); + SFileSetFilePointer(hFile, 0, NULL, FILE_BEGIN); + + // Allocate space for the full file + pbFullFile = new BYTE[dwFileSize]; + if(pbFullFile != NULL) + { + if(!SFileReadFile(hFile, pbFullFile, dwFileSize)) + { + nError = GetLastError(); + printf("Failed to read full patched file data \"%s\"\n", szFileName); + } + + if(nError == ERROR_SUCCESS) + { + MergeLocalPath(szLocFileName, MAKE_PATH("Work//"), GetPlainFileNameA(szFileName)); + pStream = FileStream_CreateFile(szLocFileName, STREAM_PROVIDER_LINEAR | BASE_PROVIDER_FILE); + if(pStream != NULL) + { + FileStream_Write(pStream, NULL, pbFullFile, dwFileSize); + FileStream_Close(pStream); + } + } + + delete [] pbFullFile; + } + } + } + + // Close handles + if(hFile != NULL) + SFileCloseFile(hFile); + if(hMpq != NULL) + SFileCloseArchive(hMpq); + return nError; +} + static int TestCompareTwoArchives( const TCHAR * szMpqName1, const TCHAR * szMpqName2, @@ -1404,8 +1552,6 @@ static int TestCompareTwoArchives( { TMPQArchive * ha1 = NULL; TMPQArchive * ha2 = NULL; - LPBYTE pbBuffer1 = NULL; - LPBYTE pbBuffer2 = NULL; HANDLE hMpq1 = NULL; // Handle of the first archive HANDLE hMpq2 = NULL; // Handle of the second archive HANDLE hFile1 = NULL; @@ -1416,12 +1562,6 @@ static int TestCompareTwoArchives( if(szListFile == NULL || *szListFile == 0) szListFile = NULL; - // Allocate both buffers - pbBuffer1 = new BYTE[dwBlockSize]; - pbBuffer2 = new BYTE[dwBlockSize]; - if(pbBuffer1 == NULL || pbBuffer2 == NULL) - nError = ERROR_NOT_ENOUGH_MEMORY; - _tprintf(_T("=============== Comparing MPQ archives ===============\n")); // Open the first MPQ archive @@ -1465,67 +1605,58 @@ static int TestCompareTwoArchives( if(nError == ERROR_SUCCESS) { SFILE_FIND_DATA sf; + TMPQFile * hf1; + TMPQFile * hf2; HANDLE hFind = SFileFindFirstFile(hMpq1, "*", &sf, szListFile); - DWORD dwSearchScope1 = SFILE_OPEN_FROM_MPQ; - DWORD dwSearchScope2 = SFILE_OPEN_FROM_MPQ; bool bResult = true; - if(hMpq1 == NULL) - dwSearchScope1 = SFILE_OPEN_LOCAL_FILE; - if(hMpq2 == NULL) - dwSearchScope2 = SFILE_OPEN_LOCAL_FILE; - while(hFind != NULL && bResult == true) { - printf("%s\n", sf.cFileName); +// printf("%s \r", sf.cFileName); SFileSetLocale(sf.lcLocale); // Open the first file - if(!SFileOpenFileEx(hMpq1, sf.cFileName, dwSearchScope1, &hFile1)) - { + if(!SFileOpenFileEx(hMpq1, sf.cFileName, 0, &hFile1)) printf("Failed to open the file %s in the first archive\n", sf.cFileName); - continue; - } - if(!SFileOpenFileEx(hMpq2, sf.cFileName, dwSearchScope2, &hFile2)) - { + if(!SFileOpenFileEx(hMpq2, sf.cFileName, 0, &hFile2)) printf("Failed to open the file %s in the second archive\n", sf.cFileName); - continue; - } - if(dwSearchScope1 == SFILE_OPEN_FROM_MPQ && dwSearchScope2 == SFILE_OPEN_FROM_MPQ) + if(hFile1 != NULL && hFile2 != NULL) { - TMPQFile * hf1 = (TMPQFile *)hFile1; - TMPQFile * hf2 = (TMPQFile *)hFile2; + // Get the TMPQFile pointers + hf1 = (TMPQFile *)hFile1; + hf2 = (TMPQFile *)hFile2; // Compare the file sizes if(hf1->pFileEntry->dwFileSize != hf2->pFileEntry->dwFileSize) - printf(" - %s different size (%u x %u)\n", sf.cFileName, hf1->pFileEntry->dwFileSize, hf2->pFileEntry->dwFileSize); + printf("Different file size: %s (%u x %u)\n", sf.cFileName, hf1->pFileEntry->dwFileSize, hf2->pFileEntry->dwFileSize); + + if(hf1->pFileEntry->dwCmpSize != hf2->pFileEntry->dwCmpSize) + printf("Different cmpr size: %s (%u x %u)\n", sf.cFileName, hf1->pFileEntry->dwCmpSize, hf2->pFileEntry->dwCmpSize); if(hf1->pFileEntry->dwFlags != hf2->pFileEntry->dwFlags) - printf(" - %s different flags (%08X x %08X)\n", sf.cFileName, hf1->pFileEntry->dwFlags, hf2->pFileEntry->dwFlags); - } + printf("Different mpq flags: %s (%08X x %08X)\n", sf.cFileName, hf1->pFileEntry->dwFlags, hf2->pFileEntry->dwFlags); - if(!CompareArchivedFiles(sf.cFileName, hFile1, hFile2, 0x1001)) - printf(" - %s different content\n", sf.cFileName); + if(!CompareArchivedFiles(sf.cFileName, hFile1, hFile2, dwBlockSize)) + printf("Different file data: %s\n", sf.cFileName); - if(!CompareArchivedFilesRR(sf.cFileName, hFile1, hFile2, 0x100000)) - printf(" - %s different content\n", sf.cFileName); +// if(!CompareArchivedFilesRR(sf.cFileName, hFile1, hFile2, dwBlockSize)) +// printf("Different file data: %s\n", sf.cFileName); + } // Close both files - SFileCloseFile(hFile2); - SFileCloseFile(hFile1); + if(hFile2 != NULL) + SFileCloseFile(hFile2); + if(hFile1 != NULL) + SFileCloseFile(hFile1); hFile2 = hFile1 = NULL; // Find the next file bResult = SFileFindNextFile(hFind, &sf); } - // Close all handles - if(hFile2 != NULL) - SFileCloseFile(hFile2); - if(hFile1 != NULL) - SFileCloseFile(hFile1); + // Close the find handle if(hFind != NULL) SFileFindClose(hFind); } @@ -1537,137 +1668,97 @@ static int TestCompareTwoArchives( SFileCloseArchive(hMpq2); if(hMpq1 != NULL) SFileCloseArchive(hMpq1); - if(pbBuffer2 != NULL) - delete [] pbBuffer2; - if(pbBuffer1 != NULL) - delete [] pbBuffer1; return nError; } -static int TestOpenPatchedArchive(const TCHAR * szMpqName, ...) +//----------------------------------------------------------------------------- +// Searching all known MPQs + +#ifdef _WIN32 +static int TestSearchOneArchive(const TCHAR * szMpqName) { - TFileStream * pStream; - HANDLE hFile = NULL; - HANDLE hMpq = NULL; - va_list argList; - const char * szFileName = "World\\Minimaps\\Azeroth\\noLiquid_map20_44.blp"; - TCHAR szLocFileName[MAX_PATH]; - LPBYTE pbFullFile = NULL; - DWORD dwFileSize; - int nError = ERROR_SUCCESS; + SFILE_FIND_DATA sf; + HANDLE hFind; + HANDLE hMpq; + const TCHAR * szExtension; + bool bFound = true; - // Open the primary MPQ - _tprintf(_T("Opening %s ...\n"), szMpqName); - if(!SFileOpenArchive(szMpqName, 0, MPQ_OPEN_READ_ONLY, &hMpq)) - { - nError = GetLastError(); - _tprintf(_T("Failed to open the archive %s ...\n"), szMpqName); - } + // Get the file extension + szExtension = _tcsrchr(szMpqName, _T('.')); + if(szExtension == NULL) + return ERROR_SUCCESS; - // Add all patches - if(nError == ERROR_SUCCESS) + // Only search defined extensions + if(_tcsicmp(szExtension, _T(".mpq")) && _tcsnicmp(szExtension, _T(".SC2"), 4)) + return ERROR_SUCCESS; + + _tprintf(_T("Searching %s ...\n"), szMpqName); + + // Try to open the MPQ + if(SFileOpenArchive(szMpqName, 0, MPQ_OPEN_READ_ONLY, &hMpq)) { - va_start(argList, szMpqName); - while((szMpqName = va_arg(argList, const TCHAR *)) != NULL) + hFind = SFileFindFirstFile(hMpq, "*", &sf, NULL); + if(hFind != NULL) { - _tprintf(_T("Adding patch %s ...\n"), szMpqName); - if(!SFileOpenPatchArchive(hMpq, szMpqName, NULL, 0)) + while(bFound) { - nError = GetLastError(); - printf("Failed to add patch %s ...\n", szMpqName); - } - } - va_end(argList); - } - - // Now search all files - if(nError == ERROR_SUCCESS) - { - SFILE_FIND_DATA sf; - HANDLE hFind; - bool bResult = true; + if(sf.dwFileFlags & MPQ_FILE_DELETE_MARKER) + _tprintf(_T("Delete marker: %s:%hs\n"), szMpqName, sf.cFileName); - hFind = SFileFindFirstFile(hMpq, "World\\Minimaps\\Azeroth\\noLiquid_map20_44.*", &sf, NULL); - while(hFind && bResult) - { - printf("%s\n", sf.cFileName); - bResult = SFileFindNextFile(hFind, &sf); + bFound = SFileFindNextFile(hFind, &sf); + } } - } - // Now try to open patched version of a file - if(nError == ERROR_SUCCESS) - { - SFileExtractFile(hMpq, szFileName, _T("E:\\noLiquid_map20_44.blp")); + SFileCloseArchive(hMpq); } - // Now try to open patched version of "Achievement.dbc" - if(nError == ERROR_SUCCESS) - { - printf("Opening patched file \"%s\" ...\n", szFileName); - SFileVerifyFile(hMpq, szFileName, SFILE_VERIFY_RAW_MD5); - if(!SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_PATCHED_FILE, &hFile)) - { - nError = GetLastError(); - printf("Failed to open patched file \"%s\"\n", szFileName); - } - } + return ERROR_SUCCESS; +} - // Verify of the patched version is correct - if(nError == ERROR_SUCCESS) +static int TestSearchAllArchives(const TCHAR * szSearchMask) +{ + WIN32_FIND_DATA wf; + LPTSTR szFilePart; + HANDLE hFind; + TCHAR szFullPath[MAX_PATH]; + BOOL bFound = TRUE; + + // Initiate search + _tcscpy(szFullPath, szSearchMask); + szFilePart = _tcschr(szFullPath, _T('*')); + assert(szFilePart != NULL); + + // Begin search + hFind = FindFirstFile(szSearchMask, &wf); + if(hFind != INVALID_HANDLE_VALUE) { - TCHAR * szPatchChain = NULL; - DWORD cbPatchChain = 0; - - // Get the patch chain - SFileGetFileInfo(hFile, SFILE_INFO_PATCH_CHAIN, szPatchChain, cbPatchChain, &cbPatchChain); - szPatchChain = (TCHAR *)(new BYTE[cbPatchChain]); - SFileGetFileInfo(hFile, SFILE_INFO_PATCH_CHAIN, szPatchChain, cbPatchChain, &cbPatchChain); - delete [] szPatchChain; - - // Get the size of the full patched file - dwFileSize = SFileGetFileSize(hFile, NULL); - if(dwFileSize != 0) + while(bFound) { - DWORD dwBytesRead = 0; - BYTE TempData[0x100]; - - SFileReadFile(hFile, TempData, sizeof(TempData), &dwBytesRead); - SFileSetFilePointer(hFile, 0, NULL, FILE_BEGIN); - - // Allocate space for the full file - pbFullFile = new BYTE[dwFileSize]; - if(pbFullFile != NULL) + // Eliminate "." and ".." + if(wf.cFileName[0] != _T('.')) { - if(!SFileReadFile(hFile, pbFullFile, dwFileSize)) - { - nError = GetLastError(); - printf("Failed to read full patched file data \"%s\"\n", szFileName); + // Construct the full path + _tcscpy(szFilePart, wf.cFileName); + + // If it a directory? + if(wf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + _tcscat(szFullPath, _T("\\*")); + TestSearchAllArchives(szFullPath); } - - if(nError == ERROR_SUCCESS) + else { - MergeLocalPath(szLocFileName, MAKE_PATH("Work//"), GetPlainFileNameA(szFileName)); - pStream = FileStream_CreateFile(szLocFileName); - if(pStream != NULL) - { - FileStream_Write(pStream, NULL, pbFullFile, dwFileSize); - FileStream_Close(pStream); - } + TestSearchOneArchive(szFullPath); } - - delete [] pbFullFile; } + bFound = FindNextFile(hFind, &wf); } + FindClose(hFind); } - // Close handles - if(hFile != NULL) - SFileCloseFile(hFile); - if(hMpq != NULL) - SFileCloseArchive(hMpq); - return nError; + return ERROR_SUCCESS; } +#endif //----------------------------------------------------------------------------- // Main @@ -1697,6 +1788,9 @@ int main(void) // if(nError == ERROR_SUCCESS) // nError = TestPartFileRead(MAKE_PATH("2009 - PartialMPQs/patch.MPQ.part")); +// if(nError == ERROR_SUCCESS) +// nError = ComparePklibCompressions(); + // Test LZMA compression method against the code ripped from Starcraft II // if(nError == ERROR_SUCCESS) // nError = CompareLzmaCompressions(MPQ_SECTOR_SIZE); @@ -1706,8 +1800,8 @@ int main(void) // nError = TestSectorCompress(MPQ_SECTOR_SIZE); // Test the archive open and close - if(nError == ERROR_SUCCESS) - nError = TestArchiveOpenAndClose(MAKE_PATH("2011 - WoW/15050/world.MPQ")); +// if(nError == ERROR_SUCCESS) +// nError = TestArchiveOpenAndClose(_T("d:\\Install\\Blizzard\\Diablo III\\Diablo-III-8370-enGB-Installer\\Installer Tome 1.MPQE")); // nError = TestArchiveOpenAndClose(MAKE_PATH("2011 - WoW BETA/wow-update-13202.MPQ")); // nError = TestArchiveOpenAndClose(MAKE_PATH("2002 - Warcraft III/ProtectedMap_HashTable_FakeValid.w3x")); // nError = TestArchiveOpenAndClose(MAKE_PATH("2010 - Starcraft II/Installer Tome 1 enGB.MPQE")); @@ -1763,22 +1857,10 @@ int main(void) // Create copy of the archive, appending some bytes before the MPQ header // if(nError == ERROR_SUCCESS) // nError = TestCreateArchiveCopy(MAKE_PATH("PartialMPQs/interface.MPQ.part"), MAKE_PATH("PartialMPQs/interface-copy.MPQ.part"), NULL); -/* - if(nError == ERROR_SUCCESS) - { - nError = TestCompareTwoArchives(MAKE_PATH("2011 - WoW-Cataclysm/wow-update-13189.MPQ"), - MAKE_PATH("wow-update-13189.MPQ"), - NULL, - 0x1001); - } -*/ +/* if(nError == ERROR_SUCCESS) { - nError = TestOpenPatchedArchive(MAKE_PATH("2004 - Wow 3.x/lichking.MPQ"), - MAKE_PATH("2011 - WoW 4.x/wow-update-13287.MPQ"), - NULL); -/* nError = TestOpenPatchedArchive(MAKE_PATH("2011 - WoW 4.x/locale-enGB.MPQ"), MAKE_PATH("2011 - WoW 4.x/wow-update-13164.MPQ"), MAKE_PATH("2011 - WoW 4.x/wow-update-13205.MPQ"), @@ -1791,14 +1873,20 @@ int main(void) MAKE_PATH("2011 - WoW 4.x/wow-update-enGB-14333.MPQ"), MAKE_PATH("2011 - WoW 4.x/wow-update-enGB-14480.MPQ"), NULL); + } */ + + if(nError == ERROR_SUCCESS) + { + nError = TestCompareTwoArchives(MAKE_PATH("Sound-copy.mpq"), + MAKE_PATH("Sound.mpq"), + NULL, + 0x1001); } - // Remove the working directory - clreol(); - if(nError != ERROR_SUCCESS) - printf("One or more errors occurred when testing StormLib\n"); - printf("Work complete.\n"); +// if(nError == ERROR_SUCCESS) +// nError = TestSearchAllArchives(MAKE_PATH("*")); + return nError; } diff --git a/doc/EventAI.txt b/doc/EventAI.txt deleted file mode 100644 index c1db7dc6bf1..00000000000 --- a/doc/EventAI.txt +++ /dev/null @@ -1,873 +0,0 @@ -===================================================== -EventAI documentation: (last changed August 16, 2010) -===================================================== - -EventAI allows users to create new creature scripts entirely within the database. - -For the AI to be used, you must first make sure to set AIname for each creature that should use this AI. -UPDATE creature_template SET AIName = 'EventAI' WHERE entry IN (...); - -========================================================= -WARNING: THIS DOCUMENTATION IS NOT ALWAYS UP TO DATE. -FOR MORE UP-TO-DATE INFORMATION, CHECK THE TRINITY WIKI. -========================================================= - -========================================= -Basic structure of EventAI -========================================= - -EventAI follows a basic if (Event) then do (Action) format. -Below is the list of current fields of the creature_ai_scripts table. - -(Field_Name) (Description) -id This value is merely an incrementing counter of the current Event number. Required for sql queries. -creature_id Creature id which should trigger this event. - -event_type The type of event (see "Event types" below) -event_inverse_phase_mask Mask with phases this event should NOT trigger in* -event_chance Percentage chance of triggering the event (1 - 100) -event_flags Event flags (repeatable, ... (see below)) -event_param1 Variables for the event (depends on event_type) -event_param2 -event_param3 -event_param4 - -action1_type An action to take when the event occurs (see "Action types" below) -action1_param1 Variables used by Action1 (depends on action_type) -action1_param2 -action1_param3 - -action2_type -action2_param1 -action2_param2 -action2_param3 - -action3_type -action3_param1 -action3_param2 -action3_param3 - -All params are signed 32-bit values (+/- 2147483647). Time values are always in milliseconds. -In case of a percentage value, use value/100 (ie. param = 500 then that means 500%, -50 = -50%) - -[*] Phase mask is a bitmask of phases which shouldn't trigger this event. (ie. Phase mask of value 12 (binary 1100) results in triggering this event in phases 0, 1 and all others with exception for phases 2 and 3 (counting from 0). - - -========================================= -Event types -========================================= - -A list of event types EventAI is able to handle. -Each event type has its own specific interpretation of the params that accompany it. -Params are always read in the ascending order (from Param1 to Param3). -Events will not repeat until the creature exits combat or unless EFLAG_REPEATABLE is set. -Some events such as EVENT_T_AGGRO, EVENT_T_DEATH, EVENT_T_SPAWNED, and EVENT_T_EVADE cannot repeat. - -# Internal name Param usage Description -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -0 EVENT_T_TIMER InitialMin, InitialMax, RepeatMin, RepeatMax Expires at first between (Param1) and (Param2) and then between every (Param3) and (Param4), but only in combat. -1 EVENT_T_TIMER_OOC InitialMin, InitialMax, RepeatMin, RepeatMax Expires at first between (Param1) and (Param2) and then between every (Param3) and (Param4), but only out of combat. -2 EVENT_T_HP HPMax%, HPMin%, RepeatMin, RepeatMax Expires when HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). -3 EVENT_T_MANA ManaMax%,ManaMin% RepeatMin, RepeatMax Expires once Mana% is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). -4 EVENT_T_AGGRO NONE Expires upon initial aggro (does not repeat). -5 EVENT_T_KILL RepeatMin, RepeatMax Expires upon killing a player. Will repeat between (Param1) and (Param2). -6 EVENT_T_DEATH NONE Expires upon creature death. -7 EVENT_T_EVADE NONE Expires upon creature EnterEvadeMode(). -8 EVENT_T_SPELLHIT SpellID, Schoolmask, RepeatMin, RepeatMax Expires upon a spell hit. When (param1) is set, it will be used as a trigger. With (param2) specified, the expiration is limited to specific spell schools (-1 for all). Will repeat every (Param3) and (Param4). -9 EVENT_T_RANGE MinDist, MaxDist, RepeatMin, RepeatMax Expires when the highest threat target distance is greater than (Param1) and less than (Param2). Will repeat every (Param3) and (Param4). -10 EVENT_T_OOC_LOS Hostile-or-Not, MaxAllowedRange, RepeatMin, RepeatMax Expires when a unit moves within distance (MaxAllowedRange) of a creature. If (Param1) is zero it will expire only when unit is hostile, friendly otherwise (Param1 = 1), depends generally on faction. Will repeat every (Param3) and (Param4). Does not expire when the creature is in combat. -11 EVENT_T_SPAWNED NONE Expires on initial spawn and on creature respawn (useful for setting ranged movement type). -12 EVENT_T_TARGET_HP HPMax%, HPMin%, RepeatMin, RepeatMax Expires when current target's HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). -13 EVENT_T_TARGET_CASTING RepeatMin, RepeatatMax Expires when the current target is casting a spell. Will repeat every (Param1) and (Param2). -14 EVENT_T_FRIENDLY_HP HPDeficit, Radius, RepeatMin, RepeatMax Expires when a friendly unit in radius has at least (Param1) HP missing. Will repeat every (Param3) and (Param4). -15 EVENT_T_FRIENDLY_IS_CC DispelType, Radius, RepeatMin, RepeatMax Expires when a friendly unit is crowd controlled within the given radius (Param2). Will repeat every (Param3) and (Param4). -16 EVENT_T_MISSING_BUFF SpellId, Radius, RepeatMin, RepeatMax Expires when a friendly unit is missing aura(s) given by a spell (Param1) within radius (Param2). Will repeat every (Param3) and (Param4). -17 EVENT_T_SUMMONED_UNIT CreatureId, RepeatMin, RepeatMax Expires after creature with entry = (Param1) is spawned (Param1 = 0 means all spawns). Will repeat every (Param2) and (Param3). -18 EVENT_T_TARGET_MANA ManaMax%, ManaMin%, RepeatMin, RepeatMax -21 EVENT_T_REACHED_HOME NONE Expires when a creature reach it's home(spawn) location after evade. -22 EVENT_T_RECEIVE_EMOTE EmoteId, Condition, CondValue1, CondValue2 Expires when a creature receives an emote with emote text id (enum TextEmotes) in (Param1). Conditions can be defined (Param2) with optional values (Param3,Param4), see enum ConditionType. -23 EVENT_T_BUFFED SpellID, AmmountInStack, RepeatMin, RepeatMax Expires when a creature has spell (Param1) auras applied in a stack greater or equal to value provided in (Param2). Will repeat every (Param3) and (Param4). -24 EVENT_T_TARGET_BUFFED SpellID, AmmountInStack, RepeatMin, RepeatMax Expires when a target unit has spell (Param1) auras applied in a stack greater or equal to value provided in (Param2). Will repeat every (Param3) and (Param4). -35 EVENT_T_RESET NONE Expires when creature leaves combat, spawns or respawns. - -========================================= -Action Types -========================================= - -A list of action types that EventAI can handle. -Each event type has its own specific interpretation of it's params, like every event type. - -# Internal name Param usage Description -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -0 ACTION_T_NONE No Action Does nothing. -1 ACTION_T_TEXT -TextId1, -TextId2, -TextId3 Simply displays the specified -TextId. When -TextId2 and -TextId3 are specified, the selection will be randomized. Text types are defined, along with other options for the text, in a table below. All values needs to be negative. -2 ACTION_T_SET_FACTION FactionId Changes faction for a creature. When param1 is zero, creature will revert to it's default faction. -3 ACTION_T_MORPH_TO_ENTRY_OR_MODEL CreatureEntry, ModelId Set either model from creature_template.entry (Param1) OR explicit modelId (Param2). If (Param1) AND (Param2) are both 0, demorph and revert to the default model. -4 ACTION_T_SOUND SoundId Plays a sound -5 ACTION_T_EMOTE EmoteId Does an emote -6 ACTION_T_RANDOM_SAY UNUSED -7 ACTION_T_RANDOM_YELL UNUSED -8 ACTION_T_RANDOM_TEXTEMOTE UNUSED -9 ACTION_T_RANDOM_SOUND SoundId1, SoundId2, SoundId3 Plays a random sound * -10 ACTION_T_RANDOM_EMOTE EmoteId1, EmoteId2, EmoteId3 Emotes a random emote -11 ACTION_T_CAST SpellId, Target, CastFlags Casts spell (Param1) on a target (Param2) using cast flags (specified below). -12 ACTION_T_SUMMON CreatureID, Target, Duration Summons a creature (Param1) for (Param3) duration and orders it to attach (Param2) target. Spawns on top of current creature. -13 ACTION_T_THREAT_SINGLE_PCT Threat%, Target Modifies a threat by (Param1) percent on a target (Param2). -14 ACTION_T_THREAT_ALL_PCT Threat% Modifies a threat by (Param1) on all targets in the threat list (using -100% here will result in full aggro dump). -15 ACTION_T_QUEST_EVENT QuestID, Target Calls AreaExploredOrEventHappens with (Param1) for a target in (Param2). -16 ACTION_T_QUEST_CASTCREATUREGO CreatureID, SpellId, Target Sends CastCreatureOrGo for a creature specified by CreatureId (Param1) with provided spell id (Param2) for a target in (Param3). -17 ACTION_T_SET_UNIT_FIELD Field_Number, Value, Target Sets a unit field (Param1) to provided value (Param2) on a target in (Param3). -18 ACTION_T_SET_UNIT_FLAG Flags, Target Sets flag (flags can be used together to modify multiple flags at once) on a target (Param2). -19 ACTION_T_REMOVE_UNIT_FLAG Flags, Target Removes flag on a target (Param2). -20 ACTION_T_AUTO_ATTACK AllowAutoAttack Stop melee attack when (Param1) is zero, otherwise continue attacking / allow melee attack. -21 ACTION_T_COMBAT_MOVEMENT AllowCombatMovement Stop combat based movement when (Param1) is zero, otherwise continue/allow combat based movement (targeted movement generator). -22 ACTION_T_SET_PHASE Phase Sets the current phase to (Param1). -23 ACTION_T_INC_PHASE Value Increments the phase by (Param1). May be negative to decrement, but should not be zero. -24 ACTION_T_EVADE No Params Forces the creature to evade, wiping all threat and dropping combat. -25 ACTION_T_FLEE_FOR_ASSIST No Params Causes the creature to flee for assistence (often at low health). -26 ACTION_T_QUEST_EVENT_ALL QuestId Calls GroupEventHappens with (Param1). Only used if it's _expected_ event should call quest completion for all players in a current party. -27 ACTION_T_CASTCREATUREGO_ALL QuestId, SpellId Calls CastedCreatureOrGo for all players on the threat list with quest id specified in (Param1) and spell id in (Param2). -28 ACTION_T_REMOVEAURASFROMSPELL Target, Spellid Removes all auras on a target (Param1) caused by a spell (Param2). -29 ACTION_T_RANGED_MOVEMENT Distance, Angle Changes the movement generator to a ranged type. (note: default melee type can still be set by using 0 as angle and 0 as distance). -30 ACTION_T_RANDOM_PHASE PhaseId1, PhaseId2, PhaseId3 Sets a phase to a specified id(s)* -31 ACTION_T_RANDOM_PHASE_RANGE PhaseMin, PhaseMax Sets a phase to a random id (Phase = PhaseMin + rnd % PhaseMin-PhaseMax). PhaseMax must be greater than PhaseMin. -32 ACTION_T_SUMMON CreatureID, Target, SummonID Summons a creature (Param1) to attack target (Param2) at location specified by EventAI_Summons (Param3). -33 ACTION_T_KILLED_MONSTER CreatureID, Target Calls KilledMonster (Param1) for a target (Param2). -34 ACTION_T_SET_INST_DATA Field, Data Calls ScriptedInstance::SetData with field (Param1) and data (Param2). -35 ACTION_T_SET_INST_DATA64 Field, Target Calls ScriptedInstance::SetData64 with field (Param1) and target's GUID (Param2). -36 ACTION_T_UPDATE_TEMPLATE TemplateId, Team Changes a creature's template to (Param1) with team = Alliance or Horde when (Param2) is either false or true respectively. -37 ACTION_T_DIE No Params Kills the creature -38 ACTION_T_ZONE_COMBAT_PULSE No Params Puts all players within an instance into combat with the creature. Only works when a creature is already in combat. Doesn't work outside instances. -39 ACTION_T_CALL_FOR_HELP Radius Call any friendly out-of-combat creatures in a radius (Param1) to attack current creature's target. -40 ACTION_T_SET_SHEATH Sheath Sets sheath state for a creature (0 = no weapon, 1 = melee weapon, 2 = ranged weapon). -41 ACTION_T_FORCE_DESPAWN No Params Despawns the creature -42 ACTION_T_SET_INVINCIBILITY_HP_LEVEL hp_level, is_percent Set min. health level for creature that can be set at damage as flat value or percent from max health -43 ACTION_T_MOUNT_TO_ENTRY_OR_MODEL CreatureEntry, ModelId Set mount model from creature_template.entry (Param1) OR explicit modelId (Param2). If (Param1) AND (Param2) are both 0, unmount. - -* = Use -1 where the param is expected to do nothing. Random constant is generated for each event, so if you have a random yell and a random sound, they will be linked up with each other (ie. param2 with param2). - - -========================================= -Event Types -========================================= -Note: -COMBAT ONLY - Means that this event will only trigger durring combat. -OUT OF COMBAT ONLY - Means that this event will only trigger while out of combat. -BOTH - This event can trigger both in and out of combat. - -Events that do not have lables on them are events that are directly involved with the in and out of combat state. - ------------------- -0 = EVENT_T_TIMER: ------------------- -Parameter 1: InitialMin - Minumum Time used to calculate Random Initial Expire -Parameter 2: InitialMax - Maximum Time used to calculate Random Initial Expire -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -COMBAT ONLY! - Expires first between (Param1) and (Param2) and then between every (Param3) and (Param4) from then on. -This is commonly used for spells that repeat cast during combat (Simulate Spell Cooldown). - ----------------------- -1 = EVENT_T_TIMER_OOC: ----------------------- -Parameter 1: InitialMin - Minumum Time used to calculate Random Initial Expire -Parameter 2: InitialMax - Maximum Time used to calculate Random Initial Expire -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -OUT OF COMBAT ONLY! - Expires first between (Param1) and (Param2) and then between every (Param3) and (Param4) from then on. -This is commonly used for events that occur and repeat outside of combat. - ---------------- -2 = EVENT_T_HP: ---------------- -Parameter 1: HPMax% - Maximum HP% That this Event will Expire -Parameter 2: HPMin% - Minimum HP% That this Event will Expire -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -BOTH - Expires when HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). -This is commonly used for events that trigger at a specific HP% (Such as Heal/Enrage Spells or NPC's that Flee). - ------------------ -3 = EVENT_T_MANA: ------------------ -Parameter 1: ManaMax% - Maximum Mana% That this Event will Expire -Parameter 2: ManaMin% - Minimum Mana% That this Event will Expire -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -BOTH - Expires once Mana% is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). -This is commonly used for events where an NPC low on Mana will do something (Such as stop casting spells and switch to melee). - ------------------- -4 = EVENT_T_AGGRO: ------------------- -This Event Expires upon initial aggro (does not repeat). - ------------------ -5 = EVENT_T_KILL: ------------------ -Parameter 1: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 2: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -COMBAT ONLY! - Expires upon killing a player. Will repeat every (Param1) and (Param2). -This Event Expires upon killing a player. It is commonly used for NPC's who yell or do something after killing a player. - ------------------- -6 = EVENT_T_DEATH: ------------------- -This Event Expires upon Death of the Scripted NPC. -This is commonly used for NPC's who have a yell on death or cast some kind if summon spell when they die. - ------------------- -7 = EVENT_T_EVADE: ------------------- -This Event Expires upon the creature EnterEvadeMode(). -This is commonly used for NPC's who use phases, allows you to reset their phase to 0 upon evade to prevent possible strange behavior. - ---------------------- -8 = EVENT_T_SPELLHIT: ---------------------- -Parameter 1: SpellID - The Spell ID that will trigger the event to occur (NOTE: If you use Spell School as the trigger set this value to 0) -Parameter 2: School - Spell School to trigger the event (NOTE: If you use a SpellID then set this value to -1) - *See Below for Spell School Bitmask Values* -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -BOTH - Expires upon Spell hit. If (param1) is set will only expire on that spell OR If (param2) is set it will only expire on spells of that school. Will repeat every (Param3) and (Param4). -This Event is commonly used for NPC's who can do special things when you cast a spell (Or specific spell) on them. - -(name, school, schoolmask) -SPELL_SCHOOL_NORMAL = 0, ==> 1 -SPELL_SCHOOL_HOLY = 1, ==> 2 -SPELL_SCHOOL_FIRE = 2, ==> 4 -SPELL_SCHOOL_NATURE = 3, ==> 8 -SPELL_SCHOOL_FROST = 4, ==> 16 -SPELL_SCHOOL_SHADOW = 5, ==> 32 -SPELL_SCHOOL_ARCANE = 6, ==> 64 -Use These Values For Schoolmask (Param2) or Any Combinations Of These Schoolmasks for Multiple Schools. - ------------------- -9 = EVENT_T_RANGE: ------------------- -Parameter 1: MinDist - This Distance is the Minimum Distance between the NPC and it's target to allow this Event to Expire -Parameter 2: MaxDist - This Distance is the Maximum Distance between the NPC and it's target to allow this Event to Expire -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -COMBAT ONLY! - Expires when the highest threat target distance is greater than (Param1) and less than (Param2). Will repeat every (Param3) and (Param4). -This Event is commonly used for NPC's who have Ranged Combat and will Throw/Shoot between a certian distance. - ---------------------- -10 = EVENT_T_OOC_LOS: ---------------------- -Parameter 1: Hostile-or-Not - This will expire if Unit are hostile. If Param1=1 it will only expire if Unit are not Hostile(generally determined by faction) -Parameter 2: MaxAllowedRange - Expires when a Unit moves within this distance to creature -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -OUT OF COMBAT! -This Event is commonly used for NPC's who do something or say something to you when you walk past them Out of Combat. - ---------------------- -11 = EVENT_T_SPAWNED: ---------------------- -Expires at initial spawn and at creature respawn. -This Event is commonly used for setting ranged movement type or Summoning a Pet on Spawn -Parameter 1: 0: works always, 1: works on map in Parameter 2, 2: works on zone/subzone in Parameter 2 -Parameter 2: depends on Parameter 1: for 1 it is map ID, for 2 it is area ID to check - ------------------------ -12 = EVENT_T_TARGET_HP: ------------------------ -Parameter 1: HPMax% - Maximum HP% That this Event will Expire -Parameter 2: HPMin% - Minimum HP% That this Event will Expire -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -COMBAT ONLY! - Expires when Current NPC's Target's HP is between (Param1) and (Param2). Will repeat every (Param3) and (Param4). -This Event is commonly used for NPC's who have a special ability (Like Execute) that only casts when a Player HP is low. - ----------------------------- -13 = EVENT_T_TARGET_CASTING: ----------------------------- -Parameter 1: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 2: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -COMBAT ONLY! - Expires when the current target is casting a spell. Will repeat every (Param1) and (Param2). -This event is commonly used for NPC's who will cast a counter spell when their target starts to cast a spell. - -------------------------- -14 = EVENT_T_FRIENDLY_HP: -------------------------- -Parameter 1: HPDeficit - This is the Amount of HP Missing from Full HP to trigger this event (You would need to calculate the amount of HP the event happens and subtract that from Full HP Value to get this number) -Parameter 2: Radius - This is the Range in Yards the NPC will scan for nearby Friendlies (Faction is Friendly To) for the missing amount of HP in Param1. -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -COMBAT ONLY! - Expires when a friendly unit in radius(param2) has at least (param1) hp missing. Will repeat every (Param3) and (Param4). -This is commonly used when an NPC in Combat will heal a nearby Friendly NPC in Combat with a Heal/Renew Spell. - ----------------------------- -15 = EVENT_T_FRIENDLY_IS_CC: ----------------------------- -Parameter 1: DispelType - Dispel Type to trigger the event - *See Below for Dispel Bitmask Values* -Parameter 2: Radius - This is the Range in Yards the NPC will scan for nearby Friendlies being Crowd Controlled -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -COMBAT ONLY! - Expires when a friendly unit is Crowd controlled within the given radius (param2). Will repeat every (Param3) and (Param4). -This is commonly used for NPC's who can come to the resule of other Friendly NPC's if being Crowd Controlled - --------------------------- -16 = EVENT_T_MISSING_BUFF: --------------------------- -Parameter 1: SpellId - This is the SpellID That the Aura Check will look for (If it is missing this Aura) -Parameter 2: Radius - This is the Range in Yards the NPC will scan for nearby Friendlies (Faction is Friendly To) for the missing Aura. -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -BOTH - Expires when a friendly unit is missing aura's given by spell (param1) within radius (param2). Will repeat every (Param3) and (Param4). -This is commonly used for NPC's who watch friendly units for a debuff to end so they can recast it on them again. - ---------------------------- -17 = EVENT_T_SUMMONED_UNIT: ---------------------------- -Parameter 1: CreatureId - The CreatureID that the NPC is watching to spawn to trigger this event -Parameter 2: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 3: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -BOTH - Expires after creature with entry(Param1) is spawned or for all spawns if param1 = 0. Will repeat every (Param2) and (Param3) . -This is commonly used for NPC's who will do something special once another NPC is summoned. Usually used is Complex Scripts or Special Events. - ---------------------------- -21 = EVENT_T_REACHED_HOME: ---------------------------- -Expires only when creature has returned to it's home location after Evade. Out of combat event. -Most commonly used to cast spells that can not be casted in EVENT_T_EVADE and other effects that does not fit in while still running back to spawn/home location. - ---------------------------- -22 = EVENT_T_RECEIVE_EMOTE: ---------------------------- -Expires only when creature receive emote from player. Valid text emote id's are in Mangos source (enum TextEmotes) -Event does not require any conditions to process, however many are ecpected to have condition. - ---------------------------- -23 = EVENT_T_BUFFED : ---------------------------- -Parameter 1: SpellId - This is the SpellID That the Aura Check will look for -Parameter 2: Amount - This is the amount of SpellID's auras at creature required for event expire. -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - ---------------------------- -24 = EVENT_T_TARGET_BUFFED: ---------------------------- -Parameter 1: SpellId - This is the SpellID That the Aura Check will look for -Parameter 2: Amount - This is the amount of SpellID's auras at target unit required for event expire. -Parameter 3: RepeatMin - Minimum Time used to calculate Random Repeat Expire -Parameter 4: RepeatMax - Maximum Time used to calculate Random Repeat Expire - -EventAI use conditions from available in Mangos (enum ConditionType) -Current implemented conditions: -CONDITION_NONE (0) 0 0 -CONDITION_AURA (1) spell_id effindex -CONDITION_ITEM (2) item_id count -CONDITION_ITEM_EQUIPPED (3) item_id count -CONDITION_ZONEID (4) zone_id 0 -CONDITION_REPUTATION_RANK (5) faction_id min_rank -CONDITION_TEAM (6) player_team 0 (469-Alliance / 67-Horde) -CONDITION_SKILL (7) skill_id min_skill_value -CONDITION_QUESTREWARDED (8) quest_id 0, if quest are rewarded -CONDITION_QUESTTAKEN (9) quest_id 0, while quest active(incomplete) -CONDITION_ACTIVE_EVENT (12) event_id 0, note this is id from dbc, also defined in Mangos source(enum HolidayIds) NOT id of game_event in database - -========================================= -Action Types -========================================= - ------------------ -1 = ACTION_T_TEXT: ------------------ -Parameter 1: The entry of the text that the NPC should use from eventai_texts table. Optionally a entry from other tables can be used (such as custom_texts). - Entry are required to be negative and exist in a *_texts-table. The type text to be displayed are defined in the texts-table itself (Say, Yell, Whisper, Emote Text, Boss Whisper, Boss Emote) - Other options are also to be defined in the texts-table, such as a sound to be heard with the text and the language used in output (common, dwarvish, etc). - In case this entry has a localized version of the text, the localized text will be displayed in client that support this locale. - -Parameter 2: Optional. TextId can be defined in addition. The same apply to this as explained above, however eventAI will randomize between the two. -Parameter 3: Optional, if Parameter 2 exist. In this case, eventAI will randomize between three. - -Read at bottom for documentation of creature_ai_texts-table. - ------------------- -2 = ACTION_T_SET_FACTION: ------------------- -Parameter 1: FactionId from Faction.dbc OR 0. Changes faction for creature. If 0, creature will revert to it's default faction if previously changed. - ------------------------ -3 = ACTION_T_MORPH_TO_ENTRY_OR_MODEL: ------------------------ -Parameter 1: Creature entry from creature_template. Action will then change to the model this creature are using. -Parameter 2: If parameter 1 is 0, then this modelId will be used (in case parameter 1 exist, parameter 2 will not be used) - -If both parameter 1 and 2 is 0, the creature will DeMorph, and use it's default model. - -------------------- -4 = ACTION_T_SOUND: -------------------- -Parameter 1: The Sound ID to be played. (Sound IDs are contained in the DBC files.) - -The creature will play the specified sound. -This is commonly used for Bosses who Yell and then also have a Voice for the same thing. - -------------------- -5 = ACTION_T_EMOTE: -------------------- -Parameter 1: The Emote ID that the creature should perform. (Emote IDs are also contained in the DBC but they can be found in the mangos source as well). - -The creature will perform a visual emote. Unlike a text emote, a visual emote is one where the creature will actually move or perform a gesture. -This is commonly used for NPC's who may perform a special action (Salute, Roar, ect...). Not all player emotes work for creature models. - ------------------------- -6 = ACTION_T_RANDOM_SAY: ------------------------- -UNUSED Can be reused to create new action type - -------------------------- -7 = ACTION_T_RANDOM_YELL: -------------------------- -UNUSED Can be reused to create new action type - ------------------------------- -8 = ACTION_T_RANDOM_TEXTEMOTE: ------------------------------- -UNUSED Can be reused to create new action type - --------------------------- -9 = ACTION_T_RANDOM_SOUND: --------------------------- -Parameter 1: The Sound ID to be played as Random Choice #1. -Parameter 2: The Sound ID to be played as Random Choice #2. -Parameter 3: The Sound ID to be played as Random Choice #3. - -Similar to the ACTION_T_SOUND action, it will choose at random a sound to play. - ---------------------------- -10 = ACTION_T_RANDOM_EMOTE: ---------------------------- -Parameter 1: The Emote ID to be played as Random Choice #1. -Parameter 2: The Emote ID to be played as Random Choice #2. -Parameter 3: The Emote ID to be played as Random Choice #3. - -Similar to the ACTION_T_EMOTE action, it will choose at random an Emote to Visually Perform. - -------------------- -11 = ACTION_T_CAST: -------------------- -Parameter 1: SpellId - The Spell ID to use for the NPC to cast. The value used in this field needs to be a valid Spell ID. -Parameter 2: Target - The Target Type defining who the creature should cast the spell at. The value in this field needs to be a valid Target Type as specified in the reference tables below. -Parameter 3: CastFlags - See Table Below for Cast Flag Bitmask Values. If you are unsure what to set this value at leave it at 0. - -The creature will cast a spell specified by a spell ID on a target specified by the target type. -This is commonly used for NPC's who cast spells. - ---------------------- -12 = ACTION_T_SUMMON: ---------------------- -Parameter 1: CreatureID - The Creature Template ID to be Summoned. The value here needs to be a valid Creature Template ID. -Parameter 2: Target - The Target Type defining who the Summoned creature will attack once spawned. The value in this field needs to be a valid Target Type as specified in the reference tables below. -Parameter 3: Duration - The duration until the summoned creature should be unsummoned AFTER Combat ends. The value in this field is in milliseconds or 0. - -The NPC will Summon another creature at the same spot as itself that will attack the specified target. -NOTE: Almost all Creature Summons have proper Summon Spells that should be used when possible. This Action is a powerful last resort option only to be used if nothing else works. -NOTE: Using Target Type 0 will cause the Summoned creature to not attack anyone. -NOTE: If Duration is set at 0, then the summoned creature will not despawn until it has died. -This is used as a manual way to force an NPC to Summon. --------------------------------- -13 = ACTION_T_THREAT_SINGLE_PCT: --------------------------------- -Parameter 1: Threat% - Threat percent that should be modified. The value in this field can range from -100 to +100. If it is negative, threat will be taken away and if positive, threat will be added. -Parameter 2: Target - The Target Type defining on whom the threat change should occur. The value in this field needs to be a valid target type as specified in the reference tables below. - -This action will modify the threat of a target in the creature's threat list by the specified percent. -This is commonly used to allow an NPC to adjust the Threat to a single player. - ------------------------------ -14 = ACTION_T_THREAT_ALL_PCT: ------------------------------ -Parameter 1: Threat% - The percent that should be used in modifying everyone's threat in the creature's threat list. The value here can range from -100 to +100. - -This action will modify the threat for everyone in the creature's threat list by the specified percent. -NOTE: Using -100 will cause the creature to reset everyone's threat to 0 so that everyone has the same amount of threat. It will NOT remove anyone from the threat list. -This is commonly used to allow an NPC to drop threat for all players to zero. - --------------------------- -15 = ACTION_T_QUEST_EVENT: --------------------------- -Parameter 1: QuestID - The Quest Template ID. The value here must be a valid quest template ID. Furthermore, the quest should have SpecialFlags | 2 as it would need to be completed by an external event which is the activation of this action. -Parameter 2: Target - The Target Type defining whom the quest should be completed for. The value in this field needs to be a valid target type as specified in the reference tables below. - -This action will satisfy the external completion requirement for the quest for the specified target defined by the target type. -NOTE: This action can only be used with player targets so it must be ensured that the target type will point to a player. -This is commonly used for Quests where only ONE player will gain credit for the quest. - ------------------------------ -16 = ACTION_T_CASTCREATUREGO: ------------------------------ -Parameter 1: CreatureID - The Creature Template ID to be Summoned. The value here needs to be a valid Creature Template ID. -Parameter 2: SpellId - The Spell ID to use to simulate the cast. The value used in this field needs to be a valid Spell ID. -Parameter 3: Target - The Target Type defining whom the quest credit should be given to. The value in this field needs to be a valid target type as specified in the reference tables below. - -This action will call CastedCreatureOrGO() function for the player. It can be used to give quest credit for casting a spell on the creature. -This is commonly used for NPC's who have a special requirement to have a Spell cast on them to complete a quest. - ------------------------------ -17 = ACTION_T_SET_UNIT_FIELD: ------------------------------ -Parameter 1: Field_Number - The index of the Field Number to be changed. Use (http://wiki.udbforums.org/index.php/Character_data) for a list of indeces and what they control. Creatures only contain the OBJECT_FIELD_* and UNIT_FIELD_* fields. They do not contain the PLAYER_FIELD_* fields. -Parameter 2: Value - The new value to be put in the field. -Parameter 3: Target - The Target Type defining for whom the unit field should be changed. The value in this field needs to be a valid target type as specified in the reference tables below. - -When activated, this action can change the target's unit field values. More information on the field value indeces can be found at (http://wiki.udbforums.org/index.php/Character_data) - ----------------------------- -18 = ACTION_T_SET_UNIT_FLAG: ----------------------------- -Parameter 1: Flags - The flag(s) to be set. Multiple flags can be set by using bitwise-OR on them (adding them together). -Parameter 2: Target - The Target Type defining for whom the flags should be changed. The value in this field needs to be a valid Target Type as specified in the reference tables below. - -When activated, this action changes the target's flags by adding (turning on) more flags. For example, this action can make the creature unattackable/unselectable if the right flags are used. - -------------------------------- -19 = ACTION_T_REMOVE_UNIT_FLAG: -------------------------------- -Parameter 1: Flags - The flag(s) to be removed. Multiple flags can be set by using bitwise-OR on them (adding them together). -Parameter 2: Target - The target type defining for whom the flags should be changed. The value in this field needs to be a valid Target Type as specified in the reference tables below. - -When activated, this action changes the target's flags by removing (turning off) flags. For example, this action can make the creature normal after it was unattackable/unselectable if the right flags are used. - --------------------------- -20 = ACTION_T_AUTO_ATTACK: --------------------------- -Parameter 1: AllowAutoAttack - If zero, then the creature will stop its melee attacks. If non-zero, then the creature will either continue its melee attacks (the action would then have no effect) or it will start its melee attacks on the target with the top threat if its melee attacks were previously stopped. - -This action controls whether or not the creature should stop or start the auto melee attack. -NOTE: The ACID Dev Team has conformed to using either 0 or 1 for the Param values (0 = Stop Melee, 1 = Start Melee). -This is commonly used in combination with EVENT_T_RANGE and ACTION_T_COMBAT_MOVEMENT for Ranged Combat for Mages and Spell Casters. - ------------------------------- -21 = ACTION_T_COMBAT_MOVEMENT: ------------------------------- -Parameter 1: If zero, then the creature will stop moving towards its victim (if its victim gets out of melee range) and will be stationary. If non-zero, then the creature will either continue to follow its victim (the action would have no effect) or it will start to follow the target with the top threat if its movement was disabled before. -Parameter 2: If non-zero, then stop melee combat state (if param1=0) or start melee combat state (if param1!=0) and creature in combat with selected target. - -This action controls whether or not the creature will always move towards its target. -NOTE: The ACID Dev Team has conformed to using either 0 or 1 for the Param values. (0 = Stop Movement, 1 = Start Movement) -This is commonly used with EVENT_T_RANGE and ACTION_T_AUTO_ATTACK for NPC's who engage in Ranged Comabt (Either Spells or Ranged Attacks) -Parameter 2 specialy used for ranged combat proper client side visual show ranged weapon in proper state. - ------------------------- -22 = ACTION_T_SET_PHASE: ------------------------- -Parameter 1: The new phase to set the creature in. This number must be an integer between 0 and 31. Numbers outside of that range will result in an error. - -When activated, this action sets the creature's event to the specified value. -NOTE: The creature's current Phase is NOT reset at creature evade. You must manually set the phase back to 0 at EVENT_T_RESET. -NOTE: The value used for the Param is the actual Phase Number (Not The Event_Inverse_Phase_Mask) -This is commonly used for complex scripts with several phases and you need to switch to a different phase. - ------------------------- -23 = ACTION_T_INC_PHASE: ------------------------- -Parameter 1: Value - The number of phases to increase or decrease. Use negative values to decrease the current phase. - -When activated, this action will increase (or decrease) the current creature's phase. -NOTE: After increasing or decreasing the phase by this action, the current phase must NOT be lower than 0 or exceed 31. -This can be used instead of ACTION_T_SET_PHASE to change phases in scripts. Just a user friendly option for changing phases. - --------------------- -24 = ACTION_T_EVADE: --------------------- -When activated, the creature will immediately exit out of combat, clear its threat list, and move back to its spawn point. Basically, this action will reset the whole encounter. -NOTE: All Param Values Are 0 for this Action. - -------------------- -25 = ACTION_T_FLEE: -------------------- -When activated, the creature will try to flee from combat. Currently this is done by it casting a fear-like spell on itself called "Run Away". -A Better Flee system is in Development. -NOTE: All Param Values Are 0 for this Action. - ------------------------------- -26 = ACTION_T_QUEST_EVENT_ALL: ------------------------------- -Parameter 1: QuestId - The quest ID to finish for everyone. - -This action does the same thing as the ACTION_T_QUEST_EVENT does but it does it for all players in the creature's threat list. -NOTE: If a player is not in the NPC's threat list for whatever reason, he/she won't get the quest completed. - ---------------------------------- -27 = ACTION_T_CASTCREATUREGO_ALL: ---------------------------------- -Parameter 1: QuestId - The quest template ID. -Parameter 2: SpellId - The spell ID used to simulate the cast. - -This action does the same thing as the ACTION_T_CASTCREATUREGO does but it does it for all players in the creature's threat list. -NOTE: If a player is not in its threat list for whatever reason, he/she won't receive the cast emulation. - ------------------------------------ -28 = ACTION_T_REMOVEAURASFROMSPELL: ------------------------------------ -Parameter 1: Target - The target type defining for whom the unit field should be changed. The value in this field needs to be a valid target type as specified in the reference tables below. -Parameter 2: SpellId - The spell ID whose auras will be removed. - -This action will remove all auras from a specific spell from the target. -This is commonly used for NPC's who have an OOC Aura that is removed at combat start or a similar idea (Like Stealth or Shape Shift) - ------------------------------- -29 = ACTION_T_RANGED_MOVEMENT: ------------------------------- -Parameter 1: Distance - The distance the mob should keep between it and its target. -Parameter 2: Angle - The angle the mob should use. - -This action changes the movement type generator to ranged type using the specified values for angle and distance. -NOTE: Specifying zero angle and distance will make it just melee instead. -This is commonly used for NPC's who always attack at range and you can specify the distance they will maintain from the target. - ---------------------------- -30 = ACTION_T_RANDOM_PHASE: ---------------------------- -Parameter 1: PhaseId1 - A possible random phase choice. -Parameter 2: PhaseId2 - A possible random phase choice. -Parameter 3: PhaseId3 - A possible random phase choice. - -Randomly sets the phase to one from the three parameter choices. -NOTE: Use -1 to specify that if this param is picked to do nothing. Random is constant between actions within an event. So if you have a random Yell and a random Sound they will match up (ex: param2 with param2) -NOTE 2: PLEASE NOTE THAT EACH OF THE PARAM VALUES ARE ACTUAL PHASE NUMBERS NOT THE INVERSE PHASE MASK VALUE. -This is commonly used for Spellcasting NPC's who on Aggro may select at random a school of spells to use for the fight. Use this if you have up to 3 phases used, otherwise use Action 31 for more then 3 phases. - ---------------------------------- -31 = ACTION_T_RANDOM_PHASE_RANGE: ---------------------------------- -Parameter 1: PhaseMin - The minimum of the phase range. -Parameter 2: PhaseMax - The maximum of the phase range. The number here must be greater than PhaseMin. - -Randomly sets the phase between a range of phases controlled by the parameters. Sets the phase to a random id (Phase = PhaseMin + rnd % PhaseMin-PhaseMax). -NOTE: PhaseMax must be greater than PhaseMin. -NOTE 2: PLEASE NOTE THAT EACH OF THE PARAM VALUES ARE ACTUAL PHASE NUMBERS NOT THE INVERSE PHASE MASK VALUE. -This is commonly used for Spellcasting NPC's who on Aggro may select at random a school of spells to use for the fight. Use this if you have MORE then 3 phases used, otherwise use Action 30. - ---------------------- -32 = ACTION_T_SUMMON: ---------------------- -Parameter 1: CreatureID - The creature template ID to be summoned. The value here needs to be a valid creature template ID. -Parameter 2: Target - The target type defining who the summoned creature will attack. The value in this field needs to be a valid target type as specified in the reference tables below. NOTE: Using target type 0 will cause the summoned creature to not attack anyone. -Parameter 3: SummonID - The summon ID from the creature_ai_summons table controlling the position (and spawntime) where the summoned mob should be spawned at. - -Summons creature (param1) to attack target (param2) at location specified by creature_ai_summons (param3). -NOTE: Param3 Value is the ID Value used for the entry used in creature_ai_summons for this action. You MUST have an creature_ai_summons entry to use this action. -This is commonly used for NPC's who need to Summon a creature at a specific location. (Normally used for complex events) - ------------------------------ -33 = ACTION_T_KILLED_MONSTER: ------------------------------ -Parameter 1: CreatureID - The creature template ID. The value here must be a valid creature template ID. -Parameter 2: Target - The target type defining whom the quest kill count should be given to. The value in this field needs to be a valid target type as specified in the reference tables below. - -When activated, this action will call KilledMonster() function for the player. It can be used to give creature credit for killing a creature. In general if the quest is set to be accompished on different creatures (e.g. "Credit" templates). -NOTE: It can be ANY creature including certain quest specific triggers -This is commonly used for giving the player Quest Credits for NPC kills (Many NPC's may use the same CreatureID for the Kill Credit) - ----------------------------- -34 = ACTION_T_SET_INST_DATA: ----------------------------- -Parameter 1: Field - The field to change in the instance script. Again, this field needs to be a valid field that has been already defined in the instance's script. -Parameter 2: Data - The value to put at that field index. - -Sets data for the instance. Note that this will only work when the creature is inside an instantiable zone that has a valid script (ScriptedInstance) assigned. -This is commonly used to link an EventAI script with a existing Script Library C++ Script. You make make things happen like opening doors on specific events that happen. - ------------------------------- -35 = ACTION_T_SET_INST_DATA64: ------------------------------- -Parameter 1: Field - The field to change in the instance script. Again, this field needs to be a valid field that has been already defined in the instance's script. -Parameter 2: Target - The target type to use to get the GUID that will be stored at the field index. The value in this field needs to be a valid target type as specified in the reference tables below. - -Sets GUID (64 bits) data for the instance based on the target. Note that this will only work when the creature is inside an instantiable zone that has a valid script (ScriptedInstance) assigned. -Calls ScriptedInstance::SetData64 with field (param1) and data (param2) target's GUID. - ------------------------------- -36 = ACTION_T_UPDATE_TEMPLATE: ------------------------------- -Parameter 1: TemplateId - The creature template ID. The value here must be a valid creature template ID. -Parameter 2: Team - Use model_id from team : Alliance(0) or Horde (1). - -This function temporarily changes creature entry to new entry, display is changed, loot is changed, but AI is not changed. At respawn creature will be reverted to original entry. -Changes the creature to a new creature template of (param1) with team = Alliance if (param2) = false or Horde if (param2) = true - ------------------- -37 = ACTION_T_DIE: ------------------- -Kills the creature -This is commonly used if you need to Instakill the creature for one reason or another. - --------------------------------- -38 = ACTION_T_ZONE_COMBAT_PULSE: --------------------------------- -Places all players within the instance into combat with the creature. Only works in combat and only works inside of instances. - ----------------------------- -39 = ACTION_T_CALL_FOR_HELP: ----------------------------- -Parameter 1: Radius - All friendly (not only same faction) creatures will go to help - -Call any friendly creatures (if its not in combat/etc) in radius attack creature target. -Mostly used when call to help more wide that normal aggro radius or auto-used call for assistance, and need apply at some event. - -------------------------- -40 ACTION_T_SET_SHEATH: -------------------------- -Parameter 1: Sheath state -0 SHEATH_STATE_UNARMED not prepared weapon show (not used mostly by creatures) -1 SHEATH_STATE_MELEE melee weapon prepared show -2 SHEATH_STATE_RANGED ranged weapon prepared show - -Let set sheath state for creature. -Note: SHEATH_STATE_RANGED case work in combat state only if combat not start as melee commands. -This possible setup by set ar event AI start (single used EVENT_T_TIMER_OOC set ACTION_T_COMBAT_MOVEMENT 0 for creature that prefered ranged attack) - -------------------------- -41 ACTION_T_FORCE_DESPAWN -------------------------- -Despawns the creature (in or out of combat) -No parameters - -------------------------- -42 ACTION_T_SET_INVINCIBILITY_HP_LEVEL -------------------------- -Parameter 1: min. health level for creature that can be set at damage, 0 used as absent min. health value for apply damage. -Parameter 2: format of paramater 1 value -0 paramater 1 used as flat value -1 paramater 1 used as percent (0..100) from creature max health - -========================================= -Target Types -========================================= -Below is the list of current Target types that EventAI can handle. -Target types are used by certain actions and may effect actions differently - -(# Internal Name Discription) -0 TARGET_T_SELF Self cast -1 TARGET_T_HOSTILE Our current target (ie: highest aggro) -2 TARGET_T_HOSTILE_SECOND_AGGRO Second highest aggro (generaly used for cleaves and some special attacks) -3 TARGET_T_HOSTILE_LAST_AGGRO Dead last on aggro (no idea what this could be used for) -4 TARGET_T_HOSTILE_RANDOM Just any random target on our threat list -5 TARGET_T_HOSTILE_RANDOM_NOT_TOP Any random target except top threat -6 TARGET_T_ACTION_INVOKER Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP) - -========================================= -Cast Flags -========================================= -Below is the list of current Cast Flags that EventAI's spell casting can handle. -Cast flags are handled bitwise. Bit 0 is Interrupt Previous, bit 1 is triggered, etc. -So for example the number "3" (11 in Binary, selecting first 2 options) would mean that this cast has both CAST_INTURRUPT_PREVIOUS and CAST_TRIGGERED. -Another example: the number "5" (101 in Binary, selecting first and third options) would mean that this cast has CAST_INTURRUPT_PREVIOUS and CAST_FORCE_CAST. - -(bit# Decimal Internal Name Discription) -0 1 CAST_INTURRUPT_PREVIOUS Interrupts any previous spell casting (basicaly makes sure that this spell goes off) -1 2 CAST_TRIGGERED Forces the spell to be instant cast and require no mana/reagents. -2 4 CAST_FORCE_CAST Forces spell to cast even if the target is possibly out of range or the creature is possibly out of mana -3 8 CAST_NO_MELEE_IF_OOM Prevents creature from entering melee if out of mana or out of range -4 16 CAST_FORCE_TARGET_SELF Forces the target to cast this spell on itself -5 32 CAST_AURA_NOT_PRESENT Only casts the spell on the target if the target does not have the aura from that spell on itself already. - -NOTE: You can add the numbers in the decimal column to combine flags. - For example if you wanted to use CAST_NO_MELEE_IF_OOM(8) and CAST_TRIGGERED(2) you would simply use 10 in the cast flags field (8 + 2 = 10). - -========================================= -Event Flags -========================================= -Below is the list of current Event Flags that EventAI can handle. Event flags are handled bitwise. - -(bit# Decimal Internal Name Discription) -0 1 EFLAG_REPEATABLE Event repeats (Does not repeat if this flag is not set) -1 2 EFLAG_NORMAL Event occurs in Normal instance difficulty (will not occur in Normal if not set) -2 4 EFLAG_HEROIC Event occurs in Heroic instance difficulty (will not occur in Heroic if not set) -3 8 -4 16 -5 32 -6 64 -7 128 EFLAG_DEBUG_ONLY Prevents events from occuring on Release builds. Useful for testing new features. - -NOTE: You can add the numbers in the decimal column to combine flags. - - -========================================= -Basic Structure of creature_ai_texts -========================================= -Below is a the list of current fields within the texts tables. - -Field_Name Description ------------------------------------------------------------ -entry This value is mearly an NEGATIVE identifier of the current text number. Required for sql queries. Valid range are -1 to -999999 -content_default This is the actual text presented in the default language (English). - -content_loc1 This is the actual text presented in the Localization #1 Clients (Korean) -content_loc2 This is the actual text presented in the Localization #2 Clients (French) -content_loc3 This is the actual text presented in the Localization #3 Clients (German) -content_loc4 This is the actual text presented in the Localization #4 Clients (Chinese) -content_loc5 This is the actual text presented in the Localization #5 Clients (Taiwanese) -content_loc6 This is the actual text presented in the Localization #6 Clients (Spanish) -content_loc7 This is the actual text presented in the Localization #7 Clients (Spanish Mexico) -content_loc8 This is the actual text presented in the Localization #8 Clients (Russian) - -sound This value is the Sound ID that corresponds to the actual text used. -type Variables used to define type of text (Say/Yell/Textemote/Whisper). -language This value is the Language that the text is native in. -emote Value from enum Emote. Only source of text will play this emote (not target, if target are defined in DoScriptText) -comment This is a comment regarding the text entry - -Note: Fields `content_loc1` to `content_loc8` are NULL values by default and are normally handled by seperate localization projects. - -========================================= -Text Types (type) -========================================= -Below is the list of current Text types that texts tables can handle. These were previously seperate Actions in ACID. - -# Internal Name Description ------------------------------------------------------------ -0 CHAT_TYPE_SAY This type sets the text to be displayed as a Say (Speech Bubble). -1 CHAT_TYPE_YELL This type sets the text to be displayed as a Yell (Red Speech Bubble) and usually has a matching Sound ID. -2 CHAT_TYPE_TEXT_EMOTE This type sets the text to be displayed as a text emote in orange in the chat log. -3 CHAT_TYPE_BOSS_EMOTE This type sets the text to be displayed as a text emote in orange in the chat log (Used only for specific Bosses). -4 CHAT_TYPE_WHISPER This type sets the text to be displayed as a whisper to the player in the chat log. -5 CHAT_TYPE_BOSS_WHISPER This type sets the text to be displayed as a whisper to the player in the chat log (Used only for specific Bosses). -6 CHAT_TYPE_ZONE_YELL Same as CHAT_TYPE_YELL but will display to all players in current zone. - -========================================= -Language Types (language) -========================================= -Below is the list of current Language types that are allowed. -This is the Race Language that the text is native to (So it will display properly) - -# Internal Name Description ------------------------------------------------------------ -0 UNIVERSAL Text in this language is understood by ALL Races. -1 ORCISH Text in this language is understood ONLY by Horde Races. -2 DARNASSIAN Text in this language is understood ONLY by the Night Elf Race. -3 TAURAHE Text in this language is understood ONLY by the Tauren Race. -6 DWARVISH Text in this language is understood ONLY by the Dwarf Race. -7 COMMON Text in this language is understood ONLY by Alliance Races. -8 DEMONIC Text in this language is understood ONLY by the Demon Race (Not Implimented). -9 TITAN This language was used by Sargeras to speak with other Titians (Not Implemented). -10 THALASSIAN Text in this language is understood ONLY by the Blood Elf Race. -11 DRACONIC Text in this language is understood ONLY by the Dragon Race. -12 KALIMAG Text will display as Kalimag (not readable by players, language of all elementals) -13 GNOMISH Text in this language is understood ONLY by the Gnome Race. -14 TROLL Text in this language is understood ONLY by the Troll Race. -33 GUTTERSPEAK Text in this language is understood ONLY by the Undead Race. -35 DRAENEI Text in this language is understood ONLY by the Draenai Race. -36 ZOMBIE (not currently used?) -37 GNOMISH BINARY Binary language used by Alliance when drinking Binary Brew -38 GOBLIN BINARY Binary language used by Horce when drinking Binary Brew diff --git a/doc/UnixInstall.txt b/doc/UnixInstall.txt index 71ee4282a7c..6293a4305c2 100644 --- a/doc/UnixInstall.txt +++ b/doc/UnixInstall.txt @@ -6,7 +6,10 @@ WARNING: THIS DOCUMENTATION IS NOT ALWAYS UP TO DATE. FOR MORE UP-TO-DATE INFORMATION, CHECK THE TRINITY WIKI. ========================================================= -CHECK http://www.trinitycore.org/w/How-to:Linux FOR FURTHER HELP +CHECK http://www.trinitycore.info/How-to:Linux FOR FURTHER HELP + +These are instructions for installation in a Linux environment, if you are +using Windows refer to http://www.trinitycore.info/How-to:Win Installing TrinityCore is fairly simple on a Linux machine, assuming you have all required applications @@ -14,11 +17,11 @@ have all required applications The most important ones are: g++ - gcc + gcc version 4.3.x or greater make cmake version 2.6.x or greater libmysql++-dev - mercurial (for checking out the core and database) + git (for checking out the core and database) openssl libssl-dev zlib1g-dev @@ -37,7 +40,7 @@ you created a dir named build ad want to have your finalcompiled product installed in /home/trinity/server, an example sequence of commands can be : - cmake ../ -DPREFIX=/home/trinity/server + cmake ../ -DPREFIX=/home/trinity/server -DTOOLS=1 -DWITH_WARNINGS=1 make make install @@ -51,21 +54,20 @@ flags like TOOLS Build map/vmap extraction/assembler tools USE_SCRIPTPCH Use precompiled headers when compiling scripts USE_COREPCH Use precompiled headers when compiling servers - USE_SFMT Use SFMT as random numbergenerator WITH_WARNINGS Show all warnings during compile WITH_COREDEBUG Include additional debug-code in core PREFIX Set installation directory - CONF_DIR Set configuration directory - LIBSDIR Set library directory + NOJEM Do not build with jemalloc (advanced users only) + CONF_DIR Set path as default configuration directory + LIBSDIR Set path as default library directory CMAKE_C_FLAGS Set C_FLAGS for compile (advanced users only) CMAKE_CXX_FLAGS Set CXX_FLAGS for compile (advanced users only) - CMAKE_BUILD_TYPE Set buildtype - the supported modes are : Release, MinSizeRel, RelWithDebInfo, Debug -Of course, replace the paths in prefix, conf_dir with the directories -you wish to install TrinityCore to. The datadir is where maps, DBCs, and -SQLs are stored. The sysconfdir is where configuration files are stored. +Of course, replace the paths in PREFIX, CONF_DIR and LIBSDIR with the +directories you wish to install TrinityCore to. The datadir is where maps, +DBCs, and SQLs are stored. The sysconfdir is where configuration files are stored. Once TrinityCore is installed you will need to apply database updates where necessary. Furthermore, you must configure your installation by diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index 2d024e552c2..ae7cdb07405 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.13 Distrib 5.5.21, for Win64 (x86) +-- MySQL dump 10.13 Distrib 5.5.22, for Win64 (x86) -- -- Host: localhost Database: auth_4x -- ------------------------------------------------------ --- Server version 5.5.21 +-- Server version 5.5.22 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -191,14 +191,14 @@ DROP TABLE IF EXISTS `realmlist`; CREATE TABLE `realmlist` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL DEFAULT '', - `address` varchar(64) NOT NULL DEFAULT '127.0.0.1', + `address` varchar(255) NOT NULL DEFAULT '127.0.0.1', `port` smallint(5) unsigned NOT NULL DEFAULT '8085', `icon` tinyint(3) unsigned NOT NULL DEFAULT '0', `flag` tinyint(3) unsigned NOT NULL DEFAULT '2', `timezone` tinyint(3) unsigned NOT NULL DEFAULT '0', `allowedSecurityLevel` tinyint(3) unsigned NOT NULL DEFAULT '0', `population` float unsigned NOT NULL DEFAULT '0', - `gamebuild` int(10) unsigned NOT NULL DEFAULT '14545', + `gamebuild` int(10) unsigned NOT NULL DEFAULT '15595', PRIMARY KEY (`id`), UNIQUE KEY `idx_name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='Realm System'; diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index ada0f0d3ab4..bbbc799a6af 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -1258,6 +1258,7 @@ DROP TABLE IF EXISTS `creature_respawn`; CREATE TABLE `creature_respawn` ( `guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier', `respawnTime` int(10) unsigned NOT NULL DEFAULT '0', + `mapId` smallint(10) unsigned NOT NULL DEFAULT '0', `instanceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Instance Identifier', PRIMARY KEY (`guid`,`instanceId`), KEY `idx_instance` (`instanceId`) @@ -1331,6 +1332,7 @@ DROP TABLE IF EXISTS `gameobject_respawn`; CREATE TABLE `gameobject_respawn` ( `guid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier', `respawnTime` int(10) unsigned NOT NULL DEFAULT '0', + `mapId` smallint(10) unsigned NOT NULL DEFAULT '0', `instanceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Instance Identifier', PRIMARY KEY (`guid`,`instanceId`), KEY `idx_instance` (`instanceId`) diff --git a/sql/updates/characters/2012_06_07_00_characters_respawn.sql b/sql/updates/characters/2012_06_07_00_characters_respawn.sql new file mode 100644 index 00000000000..168aa312713 --- /dev/null +++ b/sql/updates/characters/2012_06_07_00_characters_respawn.sql @@ -0,0 +1,2 @@ +ALTER TABLE `creature_respawn` ADD `mapId` SMALLINT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `respawnTime`; +ALTER TABLE `gameobject_respawn` ADD `mapId` SMALLINT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `respawnTime`; diff --git a/sql/updates/world/2012_05_09_02_achievement_criteria_data.sql b/sql/updates/world/2012_05_09_02_achievement_criteria_data.sql new file mode 100644 index 00000000000..e1c0529fffe --- /dev/null +++ b/sql/updates/world/2012_05_09_02_achievement_criteria_data.sql @@ -0,0 +1,6 @@ +DELETE FROM `disables` WHERE `entry` IN (7626,7634) AND `sourceType`=4; + +DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (7626,7634); +INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES +(7626, 11, 0, 0, 'achievement_not_even_a_scratch'), +(7634, 11, 0, 0, 'achievement_not_even_a_scratch'); diff --git a/sql/updates/world/2012_05_19_04_world_creature_loot_template.sql b/sql/updates/world/2012_05_19_04_world_creature_loot_template.sql new file mode 100644 index 00000000000..ae996e01956 --- /dev/null +++ b/sql/updates/world/2012_05_19_04_world_creature_loot_template.sql @@ -0,0 +1 @@ +DELETE FROM `creature_loot_template` WHERE `entry`=31813 AND `item`=36912; -- Saronite Ore diff --git a/sql/updates/world/2012_05_19_05_world_gameobject_loot_template.sql b/sql/updates/world/2012_05_19_05_world_gameobject_loot_template.sql new file mode 100644 index 00000000000..f95cb45efe4 --- /dev/null +++ b/sql/updates/world/2012_05_19_05_world_gameobject_loot_template.sql @@ -0,0 +1,93 @@ +-- Set Variables +SET @Gunship10N := 28057; -- Data1 for 201872 & 202177 +SET @Gunship10H := 28045; -- Data1 for 201873 & 202178 +SET @Gunship25N := 28072; -- Data1 for 201874 & 202179 +SET @Gunship25H := 28090; -- Data1 for 201875 & 202180 +SET @emblem := 49426; -- Emblem of Frost +SET @SfShard := 50274; -- Shadowfrost Shard +SET @PriSar := 49908; -- Primordial Saronite +-- Dug up the old references i created for UP34: +SET @Ref10J := 34329; +SET @Ref25J := 34251; +SET @RefJ10H := 34263; +SET @RefJ25H := 34275; +-- Gunship_Armory10N_reference +DELETE FROM `reference_loot_template` WHERE `entry` IN (@Ref10J,@Ref25J,@RefJ10H,@RefJ25H); +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +(@Ref10J,50791,0,1,1,1,1), -- Saronite Gargoyle Cloak +(@Ref10J,50795,0,1,1,1,1), -- Cord of Dark Suffering +(@Ref10J,50794,0,1,1,1,1), -- Neverending Winter +(@Ref10J,50787,0,1,1,1,1), -- Frost Giant's Cleaver +(@Ref10J,50793,0,1,1,1,1), -- Midnight Sun +(@Ref10J,50788,0,1,1,1,1), -- Bone Drake's Enameled Boots +(@Ref10J,50792,0,1,1,1,1), -- Pauldrons of Lost Hope +(@Ref10J,50340,0,1,1,1,1), -- Muradin's Spyglass +(@Ref10J,50797,0,1,1,1,1), -- Ice-Reinforced Vrykul Helm +(@Ref10J,50790,0,1,1,1,1), -- Abomination's Bloody Ring +(@Ref10J,50789,0,1,1,1,1), -- Icecrown Rampart Bracers +(@Ref10J,50796,0,1,1,1,1), -- Bracers of Pale Illumination +-- Gunship_Armory25N_reference +(@Ref25J,50011,0,1,1,1,1), -- Gunship Captain's Mittens +(@Ref25J,50002,0,1,1,1,1), -- Polar Bear Claw Bracers +(@Ref25J,50006,0,1,1,1,1), -- Corp'rethar Ceremonial Crown +(@Ref25J,50010,0,1,1,1,1), -- Waistband of Righteous Fury +(@Ref25J,50003,0,1,1,1,1), -- Boneguard Commander's Pauldrons +(@Ref25J,50000,0,1,1,1,1), -- Scourge Hunter's Vambraces +(@Ref25J,50359,0,1,1,1,1), -- Althor's Abacus +(@Ref25J,50352,0,1,1,1,1), -- Corpse Tongue Coin +(@Ref25J,49999,0,1,1,1,1), -- Skeleton Lord's Circle +(@Ref25J,50009,0,1,1,1,1), -- Boots of Unnatural Growth +(@Ref25J,50008,0,1,1,1,1), -- Ring of Rapid Ascent +(@Ref25J,49998,0,1,1,1,1), -- Shadowvault Slayer's Cloak +(@Ref25J,50005,0,1,1,1,1), -- Amulet of the Silent Eulogy +(@Ref25J,50411,0,1,1,1,1), -- Scourgeborne Waraxe +(@Ref25J,50001,0,1,1,1,1), -- Ikfirus's Sack of Wonder +-- Gunship_Armory10H_reference +(@RefJ10H,51912,0,1,1,1,1), -- Saronite Gargoyle Cloak (heroic) +(@RefJ10H,51908,0,1,1,1,1), -- Cord of Dark Suffering (heroic) +(@RefJ10H,51909,0,1,1,1,1), -- Neverending Winter (heroic) +(@RefJ10H,51916,0,1,1,1,1), -- Frost Giant's Cleaver (heroic) +(@RefJ10H,51910,0,1,1,1,1), -- Midnight Sun (heroic) +(@RefJ10H,51915,0,1,1,1,1), -- Bone Drake's Enameled Boots (heroic) +(@RefJ10H,51911,0,1,1,1,1), -- Pauldrons of Lost Hope (heroic) +(@RefJ10H,50345,0,1,1,1,1), -- Muradin's Spyglass (heroic) +(@RefJ10H,51906,0,1,1,1,1), -- Ice-Reinforced Vrykul Helm (heroic) +(@RefJ10H,51913,0,1,1,1,1), -- Abomination's Bloody Ring (heroic) +(@RefJ10H,51914,0,1,1,1,1), -- Icecrown Rampart Bracers (heroic) +(@RefJ10H,51907,0,1,1,1,1), -- Bracers of Pale Illumination (heroic) +-- Gunship_Armory25H_reference +(@RefJ25H,50663,0,1,1,1,1), -- Gunship Captain's Mittens (heroic) +(@RefJ25H,50659,0,1,1,1,1), -- Polar Bear Claw Bracers (heroic) +(@RefJ25H,50661,0,1,1,1,1), -- Corp'rethar Ceremonial Crown (heroic) +(@RefJ25H,50667,0,1,1,1,1), -- Waistband of Righteous Fury (heroic) +(@RefJ25H,50660,0,1,1,1,1), -- Boneguard Commander's Pauldrons (heroic) +(@RefJ25H,50655,0,1,1,1,1), -- Scourge Hunter's Vambraces (heroic) +(@RefJ25H,50366,0,1,1,1,1), -- Althor's Abacus (heroic) +(@RefJ25H,50349,0,1,1,1,1), -- Corpse Tongue Coin (heroic) +(@RefJ25H,50657,0,1,1,1,1), -- Skeleton Lord's Circle (heroic) +(@RefJ25H,50665,0,1,1,1,1), -- Boots of Unnatural Growth (heroic) +(@RefJ25H,50664,0,1,1,1,1), -- Ring of Rapid Ascent (heroic) +(@RefJ25H,50653,0,1,1,1,1), -- Shadowvault Slayer's Cloak (heroic) +(@RefJ25H,50658,0,1,1,1,1), -- Amulet of the Silent Eulogy (heroic) +(@RefJ25H,50654,0,1,1,1,1), -- Scourgeborne Waraxe (heroic) +(@RefJ25H,50656,0,1,1,1,1); -- Ikfirus's Sack of Wonder (heroic) +-- Bind the refs to the objects +DELETE FROM `gameobject_loot_template` WHERE `entry` IN (@Gunship10N,@Gunship10H,@Gunship25N,@Gunship25H); +INSERT INTO `gameobject_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- Gunship10N +(@Gunship10N,@emblem,100,1,0,2,2), -- Gunship Armory 2xemblems 10N +(@Gunship10N,1,100,1,0,-@Ref10J,2), -- 2 from reference 10Normal +-- Gunship25N +(@Gunship25N,@emblem,100,1,0,2,2), -- Gunship Armory 2xemblems 25N +(@Gunship25N,1,100,1,0,-@Ref25J,2), -- 3 from reference 25Normal +(@Gunship25N,@SfShard,-35,1,0,1,1), -- Shadowfrost Shard @ 38% chance +(@Gunship25N,@PriSar,38,1,0,1,1), -- Primordial Saronite @ 10% chance +-- Gunship10H +(@Gunship10H,@emblem,100,1,0,2,2), -- Gunship Armory 2xemblems 10H +(@Gunship10H,1,100,1,0,-@RefJ10H,2), -- 2 from reference 10Heroic +(@Gunship10H,@PriSar,38,1,0,1,1), -- Primordial Saronite @ 38% chance +-- Gunship25H +(@Gunship25H,@emblem,100,1,0,2,2), -- Gunship Armory 2xemblems 25H +(@Gunship25H,1,100,1,0,-@RefJ25H,2), -- 3 from reference 25Heroic +(@Gunship25H,@SfShard,-75,1,0,1,1), -- Shadowfrost Shard @ 75% chance +(@Gunship25H,@PriSar,50,1,0,1,1); -- Primordial Saronite @ 50% chance diff --git a/sql/updates/world/2012_05_19_06_world_gameobject_loot_template.sql b/sql/updates/world/2012_05_19_06_world_gameobject_loot_template.sql new file mode 100644 index 00000000000..9b2dcbb9363 --- /dev/null +++ b/sql/updates/world/2012_05_19_06_world_gameobject_loot_template.sql @@ -0,0 +1,13 @@ +DELETE FROM `reference_loot_template` WHERE `entry`=34172; +DELETE FROM `creature_loot_template` WHERE `entry`=38013; +DELETE FROM `gameobject_loot_template` WHERE `entry`=28683; +INSERT INTO `gameobject_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +(28683,35498,3,1,0,1,1), -- Formula: Enchant Weapon - Deathfrost +(28683,35557,28,1,0,1,2), -- Huge Snowball +(28683,35720,3,1,0,5,6), -- Lord of Frost's Private Label +(28683,35723,12,1,0,1,1), -- Shards of Ahune +(28683,54801,0,1,1,1,1), -- Icebound Cloak +(28683,54802,0,1,1,1,1), -- The Frost Lord's War Cloak +(28683,54803,0,1,1,1,1), -- The Frost Lord's Battle Shroud +(28683,54804,0,1,1,1,1), -- Shroud of Winter's Chill +(28683,54805,0,1,1,1,1); -- Cloak of the Frigid Winds diff --git a/sql/updates/world/2012_05_28_03_world_waypoint_data.sql b/sql/updates/world/2012_05_28_03_world_waypoint_data.sql new file mode 100644 index 00000000000..aa0e0ddd5ef --- /dev/null +++ b/sql/updates/world/2012_05_28_03_world_waypoint_data.sql @@ -0,0 +1,3 @@ +-- correct waypointid to guid*10 +UPDATE `waypoint_data` SET `id`=2026020 WHERE `id`=2026060; +UPDATE `creature_addon` SET `path_id`=2026020 WHERE `guid`=202602; diff --git a/sql/updates/world/2012_05_30_00_world_reference_loot_template.sql b/sql/updates/world/2012_05_30_00_world_reference_loot_template.sql new file mode 100644 index 00000000000..c2cab663d4a --- /dev/null +++ b/sql/updates/world/2012_05_30_00_world_reference_loot_template.sql @@ -0,0 +1,37 @@ +SET @Twins := 34329; +SET @emblem := 49426; +DELETE FROM `reference_loot_template` WHERE `entry`=@Twins; +INSERT INTO `reference_loot_template` (`entry`, `item`, `ChanceOrQuestChance`, `lootmode`, `groupid`, `mincountOrRef`, `maxcount`) VALUES +(@Twins,47296,0,1,1,1,1), -- Greaves of Ruthless Judgment +(@Twins,47297,0,1,1,1,1), -- The Executioner's Vice +(@Twins,47298,0,1,1,1,1), -- Armguards of the Shieldmaiden +(@Twins,47299,0,1,1,1,1), -- Belt of the Pitiless Killer +(@Twins,47300,0,1,1,1,1), -- Gouge of the Frigid Heart +(@Twins,47301,0,1,1,1,1), -- Skyweaver Vestments +(@Twins,47302,0,1,1,1,1), -- Twin's Pact +(@Twins,47303,0,1,1,1,1), -- Death's Choice +(@Twins,47304,0,1,1,1,1), -- Legplates of Ascension +(@Twins,47305,0,1,1,1,1); -- Legionnaire's Gorget +SET @Gunship10N := 28057; -- Data1 for 201872 & 202177 +SET @Ref10J := 12036; +-- Gunship_Armory10N_reference +DELETE FROM `reference_loot_template` WHERE `entry`=@Ref10J; +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +(@Ref10J,50791,0,1,1,1,1), -- Saronite Gargoyle Cloak +(@Ref10J,50795,0,1,1,1,1), -- Cord of Dark Suffering +(@Ref10J,50794,0,1,1,1,1), -- Neverending Winter +(@Ref10J,50787,0,1,1,1,1), -- Frost Giant's Cleaver +(@Ref10J,50793,0,1,1,1,1), -- Midnight Sun +(@Ref10J,50788,0,1,1,1,1), -- Bone Drake's Enameled Boots +(@Ref10J,50792,0,1,1,1,1), -- Pauldrons of Lost Hope +(@Ref10J,50340,0,1,1,1,1), -- Muradin's Spyglass +(@Ref10J,50797,0,1,1,1,1), -- Ice-Reinforced Vrykul Helm +(@Ref10J,50790,0,1,1,1,1), -- Abomination's Bloody Ring +(@Ref10J,50789,0,1,1,1,1), -- Icecrown Rampart Bracers +(@Ref10J,50796,0,1,1,1,1); -- Bracers of Pale Illumination +-- Bind the refs to the objects +DELETE FROM `gameobject_loot_template` WHERE `entry`=@Gunship10N; +INSERT INTO `gameobject_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- Gunship10N +(@Gunship10N,@emblem,100,1,0,2,2), -- Gunship Armory 2xemblems 10N +(@Gunship10N,1,100,1,0,-@Ref10J,2); -- 2 from reference 10Normal diff --git a/sql/updates/world/2012_05_30_01_world_creature_template.sql b/sql/updates/world/2012_05_30_01_world_creature_template.sql new file mode 100644 index 00000000000..4b469a13891 --- /dev/null +++ b/sql/updates/world/2012_05_30_01_world_creature_template.sql @@ -0,0 +1,76 @@ +-- Missing Vehicle_Id's from UDB +UPDATE `creature_template` SET `VehicleId`=22 WHERE `entry`=24806; +UPDATE `creature_template` SET `VehicleId`=22 WHERE `entry`=24821; +UPDATE `creature_template` SET `VehicleId`=22 WHERE `entry`=24823; +UPDATE `creature_template` SET `VehicleId`=22 WHERE `entry`=24825; +UPDATE `creature_template` SET `VehicleId`=35 WHERE `entry`=26586; +UPDATE `creature_template` SET `VehicleId`=35 WHERE `entry`=26590; +UPDATE `creature_template` SET `VehicleId`=42 WHERE `entry`=27061; +UPDATE `creature_template` SET `VehicleId`=80 WHERE `entry`=27886; +UPDATE `creature_template` SET `VehicleId`=88 WHERE `entry`=27923; +UPDATE `creature_template` SET `VehicleId`=90 WHERE `entry`=27932; +UPDATE `creature_template` SET `VehicleId`=134 WHERE `entry`=28115; +UPDATE `creature_template` SET `VehicleId`=152 WHERE `entry`=28182; +UPDATE `creature_template` SET `VehicleId`=118 WHERE `entry`=28399; +UPDATE `creature_template` SET `VehicleId`=121 WHERE `entry`=28468; +UPDATE `creature_template` SET `VehicleId`=126 WHERE `entry`=28665; +UPDATE `creature_template` SET `VehicleId`=138 WHERE `entry`=28817; +UPDATE `creature_template` SET `VehicleId`=146 WHERE `entry`=28875; +UPDATE `creature_template` SET `VehicleId`=148 WHERE `entry`=28985; +UPDATE `creature_template` SET `VehicleId`=148 WHERE `entry`=28999; +UPDATE `creature_template` SET `VehicleId`=149 WHERE `entry`=29005; +UPDATE `creature_template` SET `VehicleId`=179 WHERE `entry`=29579; +UPDATE `creature_template` SET `VehicleId`=186 WHERE `entry`=29677; +UPDATE `creature_template` SET `VehicleId`=197 WHERE `entry`=29754; +UPDATE `creature_template` SET `VehicleId`=203 WHERE `entry`=29863; +UPDATE `creature_template` SET `VehicleId`=216 WHERE `entry`=30108; +UPDATE `creature_template` SET `VehicleId`=231 WHERE `entry`=30331; +UPDATE `creature_template` SET `VehicleId`=240 WHERE `entry`=30487; +UPDATE `creature_template` SET `VehicleId`=257 WHERE `entry`=30895; +UPDATE `creature_template` SET `VehicleId`=258 WHERE `entry`=31050; +UPDATE `creature_template` SET `VehicleId`=259 WHERE `entry`=31110; +UPDATE `creature_template` SET `VehicleId`=262 WHERE `entry`=31125; +UPDATE `creature_template` SET `VehicleId`=264 WHERE `entry`=31157; +UPDATE `creature_template` SET `VehicleId`=287 WHERE `entry`=31838; +UPDATE `creature_template` SET `VehicleId`=315 WHERE `entry`=31857; +UPDATE `creature_template` SET `VehicleId`=315 WHERE `entry`=31858; +UPDATE `creature_template` SET `VehicleId`=315 WHERE `entry`=31861; +UPDATE `creature_template` SET `VehicleId`=315 WHERE `entry`=31862; +UPDATE `creature_template` SET `VehicleId`=296 WHERE `entry`=32198; +UPDATE `creature_template` SET `VehicleId`=296 WHERE `entry`=32208; +UPDATE `creature_template` SET `VehicleId`=302 WHERE `entry`=32348; +UPDATE `creature_template` SET `VehicleId`=305 WHERE `entry`=32483; +UPDATE `creature_template` SET `VehicleId`=295 WHERE `entry`=32511; +UPDATE `creature_template` SET `VehicleId`=287 WHERE `entry`=32513; +UPDATE `creature_template` SET `VehicleId`=308 WHERE `entry`=32535; +UPDATE `creature_template` SET `VehicleId`=313 WHERE `entry`=32640; +UPDATE `creature_template` SET `VehicleId`=90 WHERE `entry`=32682; +UPDATE `creature_template` SET `VehicleId`=347 WHERE `entry`=33108; +UPDATE `creature_template` SET `VehicleId`=356 WHERE `entry`=33364; +UPDATE `creature_template` SET `VehicleId`=357 WHERE `entry`=33366; +UPDATE `creature_template` SET `VehicleId`=358 WHERE `entry`=33369; +UPDATE `creature_template` SET `VehicleId`=370 WHERE `entry`=33432; +UPDATE `creature_template` SET `VehicleId`=371 WHERE `entry`=33651; +UPDATE `creature_template` SET `VehicleId`=373 WHERE `entry`=33670; +UPDATE `creature_template` SET `VehicleId`=392 WHERE `entry`=34146; +UPDATE `creature_template` SET `VehicleId`=395 WHERE `entry`=34150; +UPDATE `creature_template` SET `VehicleId`=396 WHERE `entry`=34151; +UPDATE `creature_template` SET `VehicleId`=399 WHERE `entry`=34183; +UPDATE `creature_template` SET `VehicleId`=435 WHERE `entry`=34776; +UPDATE `creature_template` SET `VehicleId`=514 WHERE `entry`=35069; +UPDATE `creature_template` SET `VehicleId`=548 WHERE `entry`=36812; +UPDATE `creature_template` SET `VehicleId`=615 WHERE `entry`=37980; +UPDATE `creature_template` SET `VehicleId`=647 WHERE `entry`=38711; +UPDATE `creature_template` SET `VehicleId`=648 WHERE `entry`=38712; +UPDATE `creature_template` SET `VehicleId`=700 WHERE `entry`=39682; +UPDATE `creature_template` SET `VehicleId`=753 WHERE `entry`=39759; +UPDATE `creature_template` SET `VehicleId`=763 WHERE `entry`=39819; +UPDATE `creature_template` SET `VehicleId`=711 WHERE `entry`=39860; +UPDATE `creature_template` SET `VehicleId`=747 WHERE `entry`=40479; +UPDATE `creature_template` SET `VehicleId`=604 WHERE `entry`=37827; +UPDATE `creature_template` SET `VehicleId`=610 WHERE `entry`=37952; +-- From PitCrawler +UPDATE `creature_template` SET `vehicleId`=202 WHERE `entry`=29903; -- Frostbite +UPDATE `creature_template` SET `vehicleId`=241 WHERE `entry`=30388; -- Stormhoof +UPDATE `creature_template` SET `vehicleId`=25 WHERE `entry`=25194; -- Kor'kron Riding Wolf +UPDATE `creature_template` SET `vehicleId`=108 WHERE `entry`=28639; -- Heb'Jin's Bat diff --git a/sql/updates/world/2012_05_30_02_world_quest_template.sql b/sql/updates/world/2012_05_30_02_world_quest_template.sql new file mode 100644 index 00000000000..2b829aa0875 --- /dev/null +++ b/sql/updates/world/2012_05_30_02_world_quest_template.sql @@ -0,0 +1,5 @@ +-- Fixing Required Races on Quests 8553 and 8554 to allow for Alliance completion +UPDATE `quest_template` SET `RequiredRaces`=0 WHERE `id`=8554; +UPDATE `quest_template` SET `RequiredRaces`=0 WHERE `id`=8553; +-- Fixing Next Quest for Quest 8552 +UPDATE `quest_template` SET `NextQuestIDChain`=8553 WHERE `id`=8552; diff --git a/sql/updates/world/2012_05_30_03_world_creature_formation.sql b/sql/updates/world/2012_05_30_03_world_creature_formation.sql new file mode 100644 index 00000000000..2964415e85b --- /dev/null +++ b/sql/updates/world/2012_05_30_03_world_creature_formation.sql @@ -0,0 +1,6 @@ +-- Set Fel Steed Formation/Group Combat Assistance +DELETE FROM `creature_formations` WHERE `leaderGUID`=16441; +INSERT INTO `creature_formations` (`leaderGUID`,`memberGUID`,`dist`,`angle`,`groupAI`) VALUES +(16441,16441,0,0,2), +(16441,16442,10,225,2), +(16441,16440,10,120,2); diff --git a/sql/updates/world/2012_05_30_04_world_gossip.sql b/sql/updates/world/2012_05_30_04_world_gossip.sql new file mode 100644 index 00000000000..0abbea7b964 --- /dev/null +++ b/sql/updates/world/2012_05_30_04_world_gossip.sql @@ -0,0 +1,3 @@ +-- Add missing gossip for Book "Soothsaying for Dummies" +DELETE FROM `gossip_menu` WHERE `entry`=7058; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (7058,8321); diff --git a/sql/updates/world/2012_05_30_05_world_gossip.sql b/sql/updates/world/2012_05_30_05_world_gossip.sql new file mode 100644 index 00000000000..5e7f1375320 --- /dev/null +++ b/sql/updates/world/2012_05_30_05_world_gossip.sql @@ -0,0 +1,430 @@ +-- Creature Gossip_menu_id Update from sniff +UPDATE `creature_template` SET `gossip_menu_id`=8388 WHERE `entry`=21118; -- Razak Ironsides +UPDATE `creature_template` SET `gossip_menu_id`=8306 WHERE `entry`=21494; -- Smiles O'Byron +UPDATE `creature_template` SET `gossip_menu_id`=8385 WHERE `entry`=21824; -- Dizzy Dina +UPDATE `creature_template` SET `gossip_menu_id`=8303 WHERE `entry`=21460; -- Tally Zapnabber +UPDATE `creature_template` SET `gossip_menu_id`=8304 WHERE `entry`=21461; -- Rally Zapnabber +UPDATE `creature_template` SET `gossip_menu_id`=8351 WHERE `entry`=21690; -- R-3D0 +UPDATE `creature_template` SET `gossip_menu_id`=8370 WHERE `entry`=21755; -- Nickwinkle the Metro-Gnome +UPDATE `creature_template` SET `gossip_menu_id`=8429 WHERE `entry`=21981; -- Overseer Nuaar +UPDATE `creature_template` SET `gossip_menu_id`=8432 WHERE `entry`=21983; -- Samia Inkling +UPDATE `creature_template` SET `gossip_menu_id`=8431 WHERE `entry`=22007; -- Tree Warden Chawn +UPDATE `creature_template` SET `gossip_menu_id`=8436 WHERE `entry`=22019; -- Kolphis Darkscale +UPDATE `creature_template` SET `gossip_menu_id`=8447 WHERE `entry`=22020; -- O'Mally Zapnabber +UPDATE `creature_template` SET `gossip_menu_id`=8508 WHERE `entry`=22053; -- Mosswood the Ancient +UPDATE `creature_template` SET `gossip_menu_id`=8490 WHERE `entry`=22099; -- Wyrmcult Provisioner +UPDATE `creature_template` SET `gossip_menu_id`=8491 WHERE `entry`=22103; -- Baron Sablemane +UPDATE `creature_template` SET `gossip_menu_id`=8523 WHERE `entry`=22127; -- Wildlord Antelarion +UPDATE `creature_template` SET `gossip_menu_id`=8496 WHERE `entry`=22149; -- Commander Haephus Stonewall +UPDATE `creature_template` SET `gossip_menu_id`=8506 WHERE `entry`=22215; -- Treebole +UPDATE `creature_template` SET `gossip_menu_id`=8723 WHERE `entry`=22264; -- Ogri'la Steelshaper +UPDATE `creature_template` SET `gossip_menu_id`=8717, `npcflag`=`npcflag`|1 WHERE `entry`=22266; -- Food Vendor +UPDATE `creature_template` SET `gossip_menu_id`=8716, `npcflag`=`npcflag`|1 WHERE `entry`=22270; -- Ogri'la Merchant +UPDATE `creature_template` SET `gossip_menu_id`=8722, `npcflag`=`npcflag`|1 WHERE `entry`=22271; -- Ogri'la Trader +UPDATE `creature_template` SET `gossip_menu_id`=8529 WHERE `entry`=22386; -- Watcher Moonshade +UPDATE `creature_template` SET `gossip_menu_id`=8615 WHERE `entry`=22924; -- Arthorn Windsong +UPDATE `creature_template` SET `gossip_menu_id`=8620 WHERE `entry`=22941; -- Mog'dorg the Wizened +UPDATE `creature_template` SET `gossip_menu_id`=8657 WHERE `entry`=22995; -- Chort +UPDATE `creature_template` SET `gossip_menu_id`=8753 WHERE `entry`=23038; -- Sky Commander Adaris +UPDATE `creature_template` SET `gossip_menu_id`=8630 WHERE `entry`=23048; -- Sky Sergeant Doryn +UPDATE `creature_template` SET `gossip_menu_id`=8640, `npcflag`=`npcflag`|1 WHERE `entry`=23052; -- Bloodmaul Supplicant +UPDATE `creature_template` SET `gossip_menu_id`=8640, `npcflag`=`npcflag`|1 WHERE `entry`=23053; -- Bladespire Supplicant +UPDATE `creature_template` SET `gossip_menu_id`=8721, `npcflag`=`npcflag`|1 WHERE `entry`=23110; -- Ogri'la Keg King +UPDATE `creature_template` SET `gossip_menu_id`=8724 WHERE `entry`=23112; -- Mingo +UPDATE `creature_template` SET `gossip_menu_id`=8642, `npcflag`=`npcflag`|1 WHERE `entry`=23120; -- Sky Sergeant Vanderlip +UPDATE `creature_template` SET `gossip_menu_id`=8737 WHERE `entry`=23208; -- Skyguard Pyrotechnician +UPDATE `creature_template` SET `gossip_menu_id`=8679 WHERE `entry`=23253; -- Kronk +UPDATE `creature_template` SET `gossip_menu_id`=8667 WHERE `entry`=23306; -- Hazzik +UPDATE `creature_template` SET `gossip_menu_id`=8670 WHERE `entry`=23335; -- Skyguard Khatie +UPDATE `creature_template` SET `gossip_menu_id`=8683 WHERE `entry`=23363; -- Sahaak +UPDATE `creature_template` SET `gossip_menu_id`=8718 WHERE `entry`=23413; -- Skyguard Handler Irena +UPDATE `creature_template` SET `gossip_menu_id`=8719 WHERE `entry`=23415; -- Skyguard Handler Deesak +UPDATE `creature_template` SET `gossip_menu_id`=8726 WHERE `entry`=23428; -- Jho'nass +UPDATE `creature_template` SET `gossip_menu_id`=8736 WHERE `entry`=23473; -- Aether-tech Apprentice + +-- Gossip Menu insert from sniff +DELETE FROM `gossip_menu` WHERE `entry`=8303 AND `text_id` IN (10359,10569); +DELETE FROM `gossip_menu` WHERE `entry`=8304 AND `text_id` IN (10360,10537); +DELETE FROM `gossip_menu` WHERE `entry`=8306 AND `text_id`=10410; +DELETE FROM `gossip_menu` WHERE `entry`=8343 AND `text_id`=10363; +DELETE FROM `gossip_menu` WHERE `entry`=8351 AND `text_id`=10422; +DELETE FROM `gossip_menu` WHERE `entry`=8370 AND `text_id`=10444; +DELETE FROM `gossip_menu` WHERE `entry`=8385 AND `text_id`=10466; +DELETE FROM `gossip_menu` WHERE `entry`=8388 AND `text_id`=10469; +DELETE FROM `gossip_menu` WHERE `entry`=8429 AND `text_id`=10532; +DELETE FROM `gossip_menu` WHERE `entry`=8430 AND `text_id`=10533; +DELETE FROM `gossip_menu` WHERE `entry`=8431 AND `text_id`=10534; +DELETE FROM `gossip_menu` WHERE `entry`=8432 AND `text_id`=10538; +DELETE FROM `gossip_menu` WHERE `entry`=8435 AND `text_id`=10541; +DELETE FROM `gossip_menu` WHERE `entry`=8436 AND `text_id`=10539; +DELETE FROM `gossip_menu` WHERE `entry`=8437 AND `text_id`=10542; +DELETE FROM `gossip_menu` WHERE `entry`=8438 AND `text_id`=10543; +DELETE FROM `gossip_menu` WHERE `entry`=8439 AND `text_id`=10544; +DELETE FROM `gossip_menu` WHERE `entry`=8440 AND `text_id`=10545; +DELETE FROM `gossip_menu` WHERE `entry`=8447 AND `text_id`=10554; +DELETE FROM `gossip_menu` WHERE `entry`=8454 AND `text_id`=10561; +DELETE FROM `gossip_menu` WHERE `entry`=8455 AND `text_id`=10562; +DELETE FROM `gossip_menu` WHERE `entry`=8490 AND `text_id`=10602; +DELETE FROM `gossip_menu` WHERE `entry`=8491 AND `text_id`=10603; +DELETE FROM `gossip_menu` WHERE `entry`=8496 AND `text_id`=10612; +DELETE FROM `gossip_menu` WHERE `entry`=8506 AND `text_id`=10637; +DELETE FROM `gossip_menu` WHERE `entry`=8508 AND `text_id`=10640; +DELETE FROM `gossip_menu` WHERE `entry`=8523 AND `text_id`=10657; +DELETE FROM `gossip_menu` WHERE `entry`=8529 AND `text_id`=10667; +DELETE FROM `gossip_menu` WHERE `entry`=8615 AND `text_id`=10793; +DELETE FROM `gossip_menu` WHERE `entry`=8620 AND `text_id` IN (10800,10860); +DELETE FROM `gossip_menu` WHERE `entry`=8630 AND `text_id`=10819; +DELETE FROM `gossip_menu` WHERE `entry`=8640 AND `text_id`=10838; +DELETE FROM `gossip_menu` WHERE `entry`=8642 AND `text_id` IN (10841,10992,10994,10995); +DELETE FROM `gossip_menu` WHERE `entry`=8657 AND `text_id` IN (10877,10878); +DELETE FROM `gossip_menu` WHERE `entry`=8660 AND `text_id` IN (10888,11057); +DELETE FROM `gossip_menu` WHERE `entry`=8667 AND `text_id`=10903; +DELETE FROM `gossip_menu` WHERE `entry`=8669 AND `text_id` IN (10906,10938,10988,10989,10990,10991); +DELETE FROM `gossip_menu` WHERE `entry`=8670 AND `text_id` IN (10907,10997,11001,11002,11004); +DELETE FROM `gossip_menu` WHERE `entry`=8671 AND `text_id` IN (10909,10951); +DELETE FROM `gossip_menu` WHERE `entry`=8672 AND `text_id` IN (10910,10922); +DELETE FROM `gossip_menu` WHERE `entry`=8674 AND `text_id`=10912; +DELETE FROM `gossip_menu` WHERE `entry`=8675 AND `text_id`=10915; +DELETE FROM `gossip_menu` WHERE `entry`=8678 AND `text_id` IN (10916,10917,10918,11013,11015,11018); +DELETE FROM `gossip_menu` WHERE `entry`=8679 AND `text_id` IN (10919,10920,11027,11028); +DELETE FROM `gossip_menu` WHERE `entry`=8680 AND `text_id` IN (10923,10924,10925,11019,11020,11021); +DELETE FROM `gossip_menu` WHERE `entry`=8681 AND `text_id` IN (10926,10927,11007,11009,11010,11011); +DELETE FROM `gossip_menu` WHERE `entry`=8683 AND `text_id`=10953; +DELETE FROM `gossip_menu` WHERE `entry`=8685 AND `text_id` IN (10931,10932); +DELETE FROM `gossip_menu` WHERE `entry`=8687 AND `text_id`=11058; +DELETE FROM `gossip_menu` WHERE `entry`=8689 AND `text_id` IN (10931,10932); +DELETE FROM `gossip_menu` WHERE `entry`=8690 AND `text_id` IN (10931,10932); +DELETE FROM `gossip_menu` WHERE `entry`=8691 AND `text_id` IN (10931,10932); +DELETE FROM `gossip_menu` WHERE `entry`=8716 AND `text_id` IN (10965,10966,10967,10968,10969); +DELETE FROM `gossip_menu` WHERE `entry`=8717 AND `text_id` IN (10972,10973,10974,10975,10976); +DELETE FROM `gossip_menu` WHERE `entry`=8718 AND `text_id` IN (10977,10978); +DELETE FROM `gossip_menu` WHERE `entry`=8719 AND `text_id` IN (10979,10980); +DELETE FROM `gossip_menu` WHERE `entry`=8721 AND `text_id` IN (10983,10984,10985,10986,10987); +DELETE FROM `gossip_menu` WHERE `entry`=8722 AND `text_id` IN (10993,10996,10998,10999,11000); +DELETE FROM `gossip_menu` WHERE `entry`=8723 AND `text_id` IN (11008,11012,11014,11016,11017); +DELETE FROM `gossip_menu` WHERE `entry`=8724 AND `text_id` IN (11022,11023,11024,11025,11026); +DELETE FROM `gossip_menu` WHERE `entry`=8726 AND `text_id` IN (11029,11036,11037,11038); +DELETE FROM `gossip_menu` WHERE `entry`=8736 AND `text_id`=11066; +DELETE FROM `gossip_menu` WHERE `entry`=8737 AND `text_id` IN (11059,11060,11061,11063); +DELETE FROM `gossip_menu` WHERE `entry`=8753 AND `text_id`=11089; +DELETE FROM `gossip_menu` WHERE `entry`=8757 AND `text_id` IN (11094,11095); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(8303,10359),(8303,10569), +(8304,10537),(8304,10360), +(8306,10410), +(8343,10363), +(8351,10422), +(8370,10444), +(8385,10466), +(8388,10469), +(8429,10532), +(8430,10533), +(8431,10534), +(8435,10541), +(8436,10539), +(8437,10542), +(8438,10543), +(8439,10544), +(8440,10545), +(8447,10554), +(8454,10561), +(8455,10562), +(8490,10602), +(8491,10603), +(8496,10612), +(8506,10637), +(8508,10640), +(8523,10657), +(8529,10667), +(8615,10793), +(8620,10800),(8620,10860), +(8630,10819), +(8640,10838), +(8642,10841),(8642,10992),(8642,10994),(8642,10995), +(8657,10877),(8657,10878), +(8660,10888),(8660,11057), +(8667,10903), +(8669,10906),(8669,10938),(8669,10988),(8669,10989),(8669,10990),(8669,10991), +(8670,10907),(8670,10997),(8670,11001),(8670,11002),(8670,11004), +(8671,10909),(8671,10951), +(8672,10910),(8672,10922), +(8674,10912), +(8675,10915), +(8678,10916),(8678,10917),(8678,10918),(8678,11013),(8678,11015),(8678,11018), +(8679,10919),(8679,10920),(8679,11027),(8679,11028), +(8680,10923),(8680,10924),(8680,10925),(8680,11019),(8680,11020),(8680,11021), +(8681,10926),(8681,10927),(8681,11007),(8681,11009),(8681,11010),(8681,11011), +(8683,10953), +(8685,10931),(8685,10932), +(8687,11058), +(8689,10931),(8689,10932), +(8690,10931),(8690,10932), +(8691,10931),(8691,10932), +(8716,10965),(8716,10966),(8716,10967),(8716,10968),(8716,10969), +(8717,10976),(8717,10975),(8717,10974),(8717,10973),(8717,10972), +(8718,10977),(8718,10978), +(8719,10979),(8719,10980), +(8721,10983),(8721,10984),(8721,10985),(8721,10986),(8721,10987), +(8722,10993),(8722,10996),(8722,10998),(8722,10999),(8722,11000), +(8723,11008),(8723,11012),(8723,11014),(8723,11016),(8723,11017), +(8724,11022),(8724,11023),(8724,11024),(8724,11025),(8724,11026), +(8726,11029),(8726,11036),(8726,11037),(8726,11038), +(8736,11066), +(8737,11059),(8737,11060),(8737,11061),(8737,11063), +(8753,11089), +(8757,11094),(8757,11095); + +-- Creature Gossip_menu_option insert from sniff +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (8303,8429,8435,8436,8437,8438,8439,8454,8490,8660,8661,8671,8672,8673,8674,8675,8676,8677,8679,8683,8685,8687,8689,8690,8691,8716,8717,8718,8719,8721,8722,8723,8724,8726,8737) AND `id`=0; +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (8672,8677,8718,8719) AND `id` IN (1); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=8304 AND `id` IN (0,1,2,3,4,5); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=8306 AND `id` IN (0,1); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=8455 AND `id` IN (0,1,2,3,4); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=8660 AND `id` IN (0,1,2,3); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=8679 AND `id` IN (0,1); +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`)VALUES +(8303,0,0,'I need another waiver!',1,1,0,0,0,0,''), -- Spellcast 38255 +(8304,0,0,'I''m ready for my test flight!',1,1,0,0,0,0,''), +(8304,1,0,'Take me to Singing Ridge.',1,1,8454,0,0,0,''), +(8304,2,0,'Send me to Razaan''s Landing!',1,1,0,0,0,0,''), +(8304,3,0,'Take me to Ruuan.',1,1,0,0,0,0,''), +(8304,4,0,'Send me to Raven''s Wood!',1,1,0,0,0,0,''), +(8304,5,0,'I want to fly to an old location!',1,1,8455,0,0,0,''), +(8306,1,0,'Why are you so far from Toshley''s Station?',1,1,8343,0,0,0,''), +(8429,0,0,'Overseer, I am here to negotiate on behalf of the Cenarion Expedition.',1,1,8430,0,0,0,''), +(8435,0,0,'Oh, it''s not my fault, I can assure you.',1,1,8437,0,0,0,''), +(8436,0,0,'I''m fine, thank you. You asked for me?',1,1,8435,0,0,0,''), +(8437,0,0,'Um, no... no, I don''t want that at all.',1,1,8438,0,0,0,''), +(8438,0,0,'Impressive. When do we attack?',1,1,8439,0,0,0,''), +(8439,0,0,'Absolutely!',1,1,8440,0,0,0,''), +(8454,0,0,'I have the signed waiver! Fire me into the Singing Ridge!',1,1,0,0,0,0,''), +(8455,0,0,'Send me back to the Jagged Ridge.',1,1,0,0,0,0,''), +(8455,1,0,'Send me back to the Singing Ridge.',1,1,0,0,0,0,''), +(8455,2,0,'Send me back to Razaan''s Landing.',1,1,0,0,0,0,''), +(8455,3,0,'Send me back to Ruuan.',1,1,0,0,0,0,''), +(8455,4,0,'Send me back to Raven''s Wood.',1,1,0,0,0,0,''), +(8490,0,1,'Very well, let me see what you''ve got.',3,128,0,0,0,0,''), +(8660,0,0,'<Call forth Gezzarak the Huntress.>',1,1,0,0,0,0,''), +(8660,1,0,'<Call forth Darkscreecher Akkarai.>',1,1,0,0,0,0,''), +(8660,2,0,'<Call forth Karrog.>',1,1,0,0,0,0,''), +(8660,3,0,'<Call forth Vakkiz the Windrager.>',1,1,0,0,0,0,''), +(8661,0,1,'Show me your assortment of, err... things.',3,128,0,0,0,0,''), +(8671,0,0,'Place 35 Apexis Shards into the prism.',1,1,0,0,0,0,''), +(8672,0,0,'Purchase 1 Unstable Flask of the Beast for the cost of 10 Apexis Shards',1,1,8673,0,0,0,''), +(8672,1,0,'Purchase 5 Unstable Flasks of the Beast for the cost of 50 Apexis Shards',1,1,8674,0,0,0,''), +(8673,0,0,'Use the fel crystalforge to make another purchase.',1,1,8672,0,0,0,''), +(8674,0,0,'Use the fel crystalforge to make another purchase.',1,1,8672,0,0,0,''), +(8675,0,0,'Use the Bash''ir crystalforge to make another purchase.',1,1,8677,0,0,0,''), +(8676,0,0,'Use the Bash''ir crystalforge to make another purchase.',1,1,8677,0,0,0,''), +(8677,0,0,'Purchase 1 Unstable Flask of the Sorcerer for the cost of 10 Apexis Shards',1,1,8676,0,0,0,''), +(8677,1,0,'Purchase 5 Unstable Flasks of the Sorcerer for the cost of 50 Apexis Shards',1,1,8675,0,0,0,''), +(8679,0,0,'Kronk, tell me about the charged crystal foci.',1,1,8757,0,0,0,''), +(8683,0,1,'Skwak!',3,128,0,0,0,0,''), +(8685,0,0,'Place 35 Apexis Shards near the dragon egg to crack it open.',1,1,0,0,0,0,''), +(8687,0,0,'<Call forth Terokk.>',1,1,0,0,0,0,''), +(8689,0,0,'Place 35 Apexis Shards near the dragon egg to crack it open.',1,1,0,0,0,0,''), +(8690,0,0,'Place 35 Apexis Shards near the dragon egg to crack it open.',1,1,0,0,0,0,''), +(8691,0,0,'Place 35 Apexis Shards near the dragon egg to crack it open.',1,1,0,0,0,0,''), +(8716,0,1,'Let me browse your goods.',3,128,0,0,0,0,''), +(8717,0,1,'Let me browse your goods.',3,128,0,0,0,0,''), +(8718,1,0,'Yes, I''d love a ride to Blackwind Landing.',1,1,0,0,0,0,''), +(8719,1,0,'Absolutely! Send me to the Skyguard Outpost.',1,1,0,0,0,0,''), +(8721,0,1,'Let me browse your goods.',3,128,0,0,0,0,''), +(8722,0,1,'Let me browse your goods.',3,128,0,0,0,0,''), +(8723,0,1,'Let me browse your goods.',3,128,0,0,0,0,''), +(8724,0,1,'Let me browse your goods.',3,128,0,0,0,0,''), +(8726,0,1,'Jho''nass, let me see what you have to offer.',3,128,0,0,0,0,''), +(8737,0,1,'Let me browse your goods.',3,128,0,0,0,0,''); + +-- Insert npc_text from sniff +DELETE FROM `npc_text` WHERE `ID` IN (10838,10878,10909,10915,10918,10968,10977,10984,10985,10986,10987,10990,10991,10993,10996,10998,10999,11012,11013,11014,11015,11020,11022,11023,11024,11037,11063); +INSERT INTO `npc_text` (`ID`,`text0_0`,`text0_1`,`lang0`,`prob0`,`em0_0`,`em0_1`,`em0_2`,`em0_3`,`em0_4`,`em0_5`,`text1_0`,`text1_1`,`lang1`,`prob1`,`em1_0`,`em1_1`,`em1_2`,`em1_3`,`em1_4`,`em1_5`,`text2_0`,`text2_1`,`lang2`,`prob2`,`em2_0`,`em2_1`,`em2_2`,`em2_3`,`em2_4`,`em2_5`,`text3_0`,`text3_1`,`lang3`,`prob3`,`em3_0`,`em3_1`,`em3_2`,`em3_3`,`em3_4`,`em3_5`,`text4_0`,`text4_1`,`lang4`,`prob4`,`em4_0`,`em4_1`,`em4_2`,`em4_3`,`em4_4`,`em4_5`,`text5_0`,`text5_1`,`lang5`,`prob5`,`em5_0`,`em5_1`,`em5_2`,`em5_3`,`em5_4`,`em5_5`,`text6_0`,`text6_1`,`lang6`,`prob6`,`em6_0`,`em6_1`,`em6_2`,`em6_3`,`em6_4`,`em6_5`,`text7_0`,`text7_1`,`lang7`,`prob7`,`em7_0`,`em7_1`,`em7_2`,`em7_3`,`em7_4`,`em7_5`,`WDBVerified`) VALUES +(10838,'Yes, $g king : queen;?','',0,1,0,1,0,0,0,0,'You kill gronn! Now you fight things from sky?','',0,1,0,15,0,0,0,0,'Me life for $N!','',0,1,0,15,0,0,0,0,'Dis drink good!','',0,1,0,1,0,0,0,0,'If $G King : Queen; $N dance, me dance!','',0,1,0,1,0,0,0,0,'$G King : Queen; not angry with me?','',0,1,0,1,0,0,0,0,'Why you look at me like dat? You not gonna kiss me, right!?','',0,1,0,1,0,0,0,0,'Now all Sons of Gruul dead! Now new $g king : queen; lead all ogres to Ogri''la!','',0,1,0,15,0,0,0,0,12340), +(10878,'Da $g king : queen;! Chort ready to serve.','',0,1,0,2,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10909,'Burning eyes within the prism fill your mind with a sense of dread...','',0,1,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10915,'<As you place your apexis shards within the hollow of the Bash''ir crystalforge and pull the lever, the device literally disintegrates them. A few moments later your flasks appear at your feet.>','',0,1,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10918,'The boy''s too stupid still to say it -- not enough crystal exposure yet -- but, he''s thankful for what you did in getting him those flasks.$B$BNow, only nine more sons to go. Gah!$B$B<Both of Torkus''s heads sigh.>$B$BWant to take one of them off of our hands? We''ll sell him to you cheap.','',0,1,0,1,0,5,0,6,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10968,'Mighty one! How can we serve you?','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10977,'','Hey, comrade. If you get yourself in good with the Skyguard, I can offer you a direct flight to our base, Blackwind Landing, in the Skethyl Mountains.$B$BDo you like my beautiful nether ray? It is lovely.',0,1,0,1,0,6,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10984,'Everyone''s gotta drink. What can we get for you?','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10985,'Greetings $G brother:sister;, how can we help?','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10986,'Our drinks should quench even the mightiest of thirsts.','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10987,'Drink or be gone!','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10990,'Yer gettin'' ta be something of a revered figure ''round here, $g boy : girl;! If''n I didn''t know better, I''d say ye were gunnin'' fer me job!!!$B$BAll the same, if ye keep up the way ye have been, ye''ll deserve it!','',0,1,0,5,0,396,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10991,'What can I say, $N? Yer the finest o'' the Sha''tari Skyguard!$B$BJust don''t be lettin'' that go ta yer head. I can still teach ya a thing or two, $g lad : lass;!$B$B<Sky Commander Keller grins at you and winks.>','',0,1,0,2,0,11,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10993,'How can we be of service, exalted one?','',0,1,1,16,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10996,'We are happy to provide you with supplies.','',0,1,1,1,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10998,'Honored $G brother:sister;, how can we help?','',0,1,1,1,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10999,'Friend! It''s been too long. What can we get for you?','',0,1,1,1,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11013,'It''s an honor to have a $r such as yourself aiding us ogres. You''re keeping our hope of a better future alive.$B$BNow if we could just get rid of these headaches. Are you sure you don''t want one of our sons?','',0,1,0,1,0,6,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11012,'There are few things you can trust in life. Steel, you can trust.','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11014,'What is steel compared to the hand that shapes it?','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11015,'It''s amazing how much you''ve helped us out. We dare say that if it weren''t for you, we''d already have been overrun by the demons, or fried to a crisp by the Black Dragonflight!$B$BOn a side note, we did mention that we''d sell you one of our sons, cheap, right? No, not interested?','',0,1,0,1,0,6,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11020,'Gahk like little, $r $N. Yous kill da big demon; make all da little demons scared!$B$B<Gahk''s heads both grin at you.>','',0,1,0,1,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11022,'What can we get for you, our exalted $G brother:sister;?','',0,1,1,16,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11023,'How might we be of assistance?','',0,1,1,1,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11024,'Honored $G brother:sister;, how may we help?','',0,1,1,396,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11037,'You''re like something of a revered figure around here, $g man : kitten;. Seems like everyone''s talking about you. That''s cool.$B$BLet''s see if there''s something in stock that you''re interested in. We have a lot of nice stuff.','',0,1,0,25,0,1,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(11063,'You can never be too prepared.','',0,1,1,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8303 AND `SourceEntry`=10569; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8304 AND `SourceEntry`=10537; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8620 AND `SourceEntry`=10860; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8642 AND `SourceEntry` IN (10992,10994,10995); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8657 AND `SourceEntry`=10878; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8660 AND `SourceEntry`=11057; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8669 AND `SourceEntry` IN (10938,10988,10989,10990,10991); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8670 AND `SourceEntry` IN (10997,11001,11002,11004); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8671 AND `SourceEntry`=10951; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8672 AND `SourceEntry`=10922; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8677 AND `SourceEntry`=10913; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8678 AND `SourceEntry` IN (10917,10918,11013,11015,11018); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8679 AND `SourceEntry` IN (10920,11027,11028); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8680 AND `SourceEntry` IN (10923,10924,10925,11019,11020,11021); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8681 AND `SourceEntry` IN (10926,10927,11007,11009,11010,11011); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup` IN (8685,8689,8690,8691) AND `SourceEntry`=10932; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8716 AND `SourceEntry` IN (10965,10966,10968,10969); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8717 AND `SourceEntry` IN (10972,10973,10974,10975,10976); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8718 AND `SourceEntry`=10978; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8719 AND `SourceEntry`=10979; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8721 AND `SourceEntry` IN (10983,10984,10985,10986,10987); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8722 AND `SourceEntry` IN (10993,10996,10998,10999,11000); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8723 AND `SourceEntry` IN (11008,11012,11014,11016,11017); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8724 AND `SourceEntry` IN (11022,11023,11024,11025,11026); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8726 AND `SourceEntry` IN (11036,11037,11038); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8737 AND `SourceEntry` IN (11060,11061,11063); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=8757 AND `SourceEntry`=11095; + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8304 AND `SourceEntry` IN (0,1,2,3,4,5); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8429 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8454 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8455 AND `SourceEntry` IN (0,1,2,3,4); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8660 AND `SourceEntry` IN (0,1,2,3); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8671 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8672 AND `SourceEntry` IN (0,1); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8677 AND `SourceEntry` IN (0,1); +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8685 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8687 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8689 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8690 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8691 AND `SourceEntry`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8718 AND `SourceEntry`=1; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8719 AND `SourceEntry`=1; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,8303,10569,0,0,8,10557,0,0,0,0,'','Tally Zapnabber - Show different gossip if player has completed quest 10557'), +(14,8304,10537,0,0,1,37108,0,0,0,0,'','Rally Zapnabber - Show different gossip if player is affected by aura 37108'), +(14,8620,10860,0,0,8,11000,0,0,0,0,'','Mog''dorg the Wizened - Show different gossip if player has rewarded quest 11000'), +(14,8642,10992,0,0,5,1031,32,0,0,0,'','Sky Sergeant Vanderlip - Show different gossip if player is honored with Sha''tari Skyguards'), +(14,8642,10994,0,0,5,1031,64,0,0,0,'','Sky Sergeant Vanderlip - Show different gossip if player is revered with Sha''tari Skyguards'), +(14,8642,10995,0,0,5,1031,128,0,0,0,'','Sky Sergeant Vanderlip - Show different gossip if player is exalted with Sha''tari Skyguards'), +(14,8657,10878,0,0,8,11000,0,0,0,0,'','Chort - Show different gossip if player has rewarded quest 11000'), +(14,8660,11057,0,0,2,32620,1,0,0,0,'','Skull Pile - Show different gossip if player has item 32620'), +(14,8669,10938,0,0,8,11065,0,0,0,0,'','Sky Commander Keller - Show different gossip if player has rewarded quest 11065'), +(14,8669,10938,0,0,8,11010,0,0,0,0,'','Sky Commander Keller - Show different gossip if player has rewarded quest 11010'), +(14,8669,10988,0,0,8,11062,0,0,0,0,'','Sky Commander Keller - Show different gossip if player has rewarded quest 11062'), +(14,8669,10989,0,0,5,1031,32,0,0,0,'','Sky Commander Keller - Show different gossip if player is honored with Sha''tari Skyguards'), +(14,8669,10990,0,0,5,1031,64,0,0,0,'','Sky Commander Keller - Show different gossip if player is revered with Sha''tari Skyguards'), +(14,8669,10991,0,0,5,1031,128,0,0,0,'','Sky Commander Keller - Show different gossip if player is exalted with Sha''tari Skyguards'), +(14,8670,10997,0,0,8,11065,0,0,0,0,'','Skyguard Khatie - Show different gossip if player has rewarded quest 11065'), +(14,8670,11001,0,0,5,1031,32,0,0,0,'','Skyguard Khatie - Show different gossip if player is honored with Sha''tari Skyguards'), +(14,8670,11002,0,0,5,1031,64,0,0,0,'','Skyguard Khatie - Show different gossip if player is revered with Sha''tari Skyguards'), +(14,8670,11004,0,0,5,1031,128,0,0,0,'','Skyguard Khatie - Show different gossip if player is exalted with Sha''tari Skyguards'), +(14,8671,10951,0,0,2,32569,35,0,1,0,'','Fel Crystal Prism - Show different gossip if player does not have 35 of item 32569'), +(14,8672,10922,0,0,2,32569,10,0,1,0,'','Fel Crystalforge - Show different gossip if player has 10 of item 32569'), +(14,8677,10913,0,0,2,32569,10,0,0,0,'','Bash''ir Crystalforge - Show different gossip if player has 10 of item 32569'), +(14,8678,10917,0,0,8,11030,0,0,0,0,'','Torkus - Show different gossip if player has rewarded quest 11030'), +(14,8678,10918,0,0,8,11061,0,0,0,0,'','Torkus - Show different gossip if player has rewarded quest 11061'), +(14,8678,11013,0,0,5,1038,32,0,0,0,'','Torkus - Show different gossip if player is honored with Ogri''la'), +(14,8678,11015,0,0,5,1038,64,0,0,0,'','Torkus - Show different gossip if player is revered with Ogri''la'), +(14,8678,11018,0,0,5,1038,128,0,0,0,'','Torkus - Show different gossip if player is exalted with Ogri''la'), +(14,8679,10920,0,0,8,11026,0,0,0,0,'','Kronk - Show different gossip if player has rewarded quest 11026'), +(14,8679,11027,0,0,5,1038,64,0,0,0,'','Kronk - Show different gossip if player is revered with Ogri''la'), +(14,8679,11028,0,0,5,1038,128,0,0,0,'','Kronk - Show different gossip if player is exalted with Ogri''la'), +(14,8680,10923,0,0,5,1038,32+16+8,0,0,0,'','Gahk - Show different gossip if player is neutral, friendly or honored with Ogri''la'), +(14,8680,10924,0,0,8,11026,0,0,0,0,'','Gahk - Show different gossip if player has rewarded quest 11026'), +(14,8680,10925,0,0,8,11060,0,0,0,0,'','Gahk - Show different gossip if player has rewarded quest 11060'), +(14,8680,11019,0,0,5,1038,64,0,0,0,'','Gahk - Show different gossip if player is revered with Ogri''la'), +(14,8680,11020,0,0,8,11079,0,0,0,0,'','Gahk - Show different gossip if player has rewarded quest 11079'), +(14,8680,11021,0,0,5,1038,128,0,0,0,'','Gahk - Show different gossip if player is exalted with Ogri''la'), +(14,8681,10926,0,0,5,1038,16+8,0,0,0,'','Chu''a''lor - Show different gossip if player is neutral or friendly with Ogri''la'), +(14,8681,10927,0,0,8,11025,0,0,0,0,'','Chu''a''lor - Show different gossip if player has rewarded quest 11025'), +(14,8681,11007,0,0,8,11058,0,0,0,0,'','Chu''a''lor - Show different gossip if player has rewarded quest 11058'), +(14,8681,11009,0,0,5,1038,32,0,0,0,'','Chu''a''lor - Show different gossip if player is honored with Ogri''la'), +(14,8681,11010,0,0,5,1038,64,0,0,0,'','Chu''a''lor - Show different gossip if player is revered with Ogri''la'), +(14,8681,11011,0,0,5,1038,128,0,0,0,'','Chu''a''lor - Show different gossip if player is exalted with Ogri''la'), +(14,8685,10932,0,0,2,32569,35,0,1,0,'','Show different gossip if player has 35 of item 32569'), +(14,8689,10932,0,0,2,32569,35,0,1,0,'','Show different gossip if player has 35 of item 32569'), +(14,8690,10932,0,0,2,32569,35,0,1,0,'','Show different gossip if player has 35 of item 32569'), +(14,8691,10932,0,0,2,32569,35,0,1,0,'','Show different gossip if player has 35 of item 32569'), +(14,8716,10965,0,0,5,1038,16,0,0,0,'','Ogri''la Merchant - Show different gossip if player is friendly with Ogri''la'), +(14,8716,10966,0,0,5,1038,32,0,0,0,'','Ogri''la Merchant - Show different gossip if player is honored with Ogri''la'), +(14,8716,10968,0,0,5,1038,64,0,0,0,'','Ogri''la Merchant - Show different gossip if player is revered with Ogri''la'), +(14,8716,10969,0,0,5,1038,128,0,0,0,'','Ogri''la Merchant - Show different gossip if player is exalted with Ogri''la'), +(14,8717,10972,0,0,5,1038,128,0,0,0,'','Food Vendor - Show different gossip if player is exalted with Ogri''la'), +(14,8717,10973,0,0,5,1038,64,0,0,0,'','Food Vendor - Show different gossip if player is revered with Ogri''la'), +(14,8717,10974,0,0,5,1038,32,0,0,0,'','Food Vendor - Show different gossip if player is honored with Ogri''la'), +(14,8717,10975,0,0,5,1038,16,0,0,0,'','Food Vendor - Show different gossip if player is friendly with Ogri''la'), +(14,8717,10976,0,0,5,1038,8,0,0,0,'','Food Vendor - Show different gossip if player is neutral with Ogri''la'), +(14,8718,10978,0,0,5,1031,224,0,0,0,'','Skyguard Handler Irena - Show different gossip if player is honored, revered or exalted with Sha''tari Skyguards'), +(14,8719,10979,0,0,5,1031,224,0,0,0,'','Skyguard Handler Deesak - Show different gossip if player is honored, revered or exalted with Sha''tari Skyguards'), +(14,8721,10983,0,0,5,1038,128,0,0,0,'','Ogri''la Keg King - Show different gossip if player is exalted with Ogri''la'), +(14,8721,10984,0,0,5,1038,64,0,0,0,'','Ogri''la Keg King - Show different gossip if player is revered with Ogri''la'), +(14,8721,10985,0,0,5,1038,32,0,0,0,'','Ogri''la Keg King - Show different gossip if player is honored with Ogri''la'), +(14,8721,10986,0,0,5,1038,16,0,0,0,'','Ogri''la Keg King - Show different gossip if player is friendly with Ogri''la'), +(14,8721,10987,0,0,5,1038,8,0,0,0,'','Ogri''la Keg King - Show different gossip if player is neutral with Ogri''la'), +(14,8722,10993,0,0,5,1038,128,0,0,0,'','Ogri''la Trader - Show different gossip if player is exalted with Ogri''la'), +(14,8722,10996,0,0,5,1038,64,0,0,0,'','Ogri''la Trader - Show different gossip if player is revered with Ogri''la'), +(14,8722,10998,0,0,5,1038,32,0,0,0,'','Ogri''la Trader - Show different gossip if player is honored with Ogri''la'), +(14,8722,10999,0,0,5,1038,16,0,0,0,'','Ogri''la Trader - Show different gossip if player is friendly with Ogri''la'), +(14,8722,11000,0,0,5,1038,8,0,0,0,'','Ogri''la Trader - Show different gossip if player is neutral with Ogri''la'), +(14,8723,11008,0,0,5,1038,128,0,0,0,'','Ogri''la Steelshaper - Show different gossip if player is exalted with Ogri''la'), +(14,8723,11012,0,0,5,1038,64,0,0,0,'','Ogri''la Steelshaper - Show different gossip if player is revered with Ogri''la'), +(14,8723,11014,0,0,5,1038,32,0,0,0,'','Ogri''la Steelshaper - Show different gossip if player is honored with Ogri''la'), +(14,8723,11016,0,0,5,1038,16,0,0,0,'','Ogri''la Steelshaper - Show different gossip if player is friendly with Ogri''la'), +(14,8723,11017,0,0,5,1038,8,0,0,0,'','Ogri''la Steelshaper - Show different gossip if player is neutral with Ogri''la'), +(14,8724,11022,0,0,5,1038,128,0,0,0,'','Mingo - Show different gossip if player is exalted with Ogri''la'), +(14,8724,11023,0,0,5,1038,64,0,0,0,'','Mingo - Show different gossip if player is revered with Ogri''la'), +(14,8724,11024,0,0,5,1038,32,0,0,0,'','Mingo - Show different gossip if player is honored with Ogri''la'), +(14,8724,11025,0,0,5,1038,16,0,0,0,'','Mingo - Show different gossip if player is friendly with Ogri''la'), +(14,8724,11026,0,0,5,1038,8,0,0,0,'','Mingo - Show different gossip if player is neutral with Ogri''la'), +(14,8726,11036,0,0,5,1038,32,0,0,0,'','Jho''nass - Show different gossip if player is honored with Ogri''la'), +(14,8726,11037,0,0,5,1038,64,0,0,0,'','Jho''nass - Show different gossip if player is revered with Ogri''la'), +(14,8726,11038,0,0,5,1038,128,0,0,0,'','Jho''nass - Show different gossip if player is exalted with Ogri''la'), +(14,8737,11063,0,0,5,1031,32,0,0,0,'','Skyguard Pyrotechnician - Show different gossip if player is honored with Sha''tari Skyguards'), +(14,8737,11061,0,0,5,1031,64,0,0,0,'','Skyguard Pyrotechnician - Show different gossip if player is revered with Sha''tari Skyguards'), +(14,8737,11060,0,0,5,1031,128,0,0,0,'','Skyguard Pyrotechnician - Show different gossip if player is exalted with Sha''tari Skyguards'), +(14,8757,11095,0,0,5,1038,224,0,0,0,'','Kronk - Show different gossip if player is honored, revered or exalted with Ogri''la'), + +(15,8304,0,0,0,9,10557,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has taken quest 10557'), +(15,8304,1,0,0,9,10710,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has taken quest 10710'), +(15,8304,2,0,0,9,10711,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has taken quest 10711'), +(15,8304,3,0,0,9,10712,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has taken quest 10712'), +(15,8304,4,0,0,9,10716,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has taken quest 10716'), +(15,8304,5,0,0,8,10557,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has taken quest 10557'), +(15,8429,0,0,0,9,10682,0,0,0,0,'','Overseer Nuaar - Show gossip option only if player has taken quest 10682'), +(15,8454,0,0,0,2,30539,1,0,0,0,'','Rally Zapnabber - Show gossip option only if player has item 30539'), +(15,8455,1,0,0,8,10710,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has completed quest 10710'), +(15,8455,2,0,0,8,10711,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has completed quest 10711'), +(15,8455,3,0,0,8,10712,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has completed quest 10712'), +(15,8455,4,0,0,8,10716,0,0,0,0,'','Rally Zapnabber - Show gossip option only if player has completed quest 10716'), +(15,8660,0,0,0,9,11885,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11885'), +(15,8660,1,0,0,9,11885,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11885'), +(15,8660,2,0,0,9,11885,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11885'), +(15,8660,3,0,0,9,11885,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11885'), +(15,8660,0,0,1,9,11074,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11074'), +(15,8660,1,0,1,9,11074,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11074'), +(15,8660,2,0,1,9,11074,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11074'), +(15,8660,3,0,1,9,11074,0,0,0,0,'','Skull Pile - Show gossip option only if player has taken quest 11074'), +(15,8671,0,0,0,2,32569,35,0,0,0,'','Fel Crystal Prism - Show gossip option only if player has 35 of item 32569'), +(15,8672,0,0,0,2,32569,10,0,0,0,'','Fel Crystalforge - Show gossip option only if player has 10 of item 32569'), +(15,8672,1,0,0,2,32569,50,0,0,0,'','Fel Crystalforge - Show gossip option only if player has 50 of item 32569'), +(15,8677,0,0,0,2,32569,10,0,0,0,'','Bash''ir Crystalforge - Show gossip option only if player has 10 of item 32569'), +(15,8677,1,0,0,2,32569,50,0,0,0,'','Bash''ir Crystalforge - Show gossip option only if player has 50 of item 32569'), +(15,8685,0,0,0,2,32569,35,0,0,0,'','Show gossip option only if player has 35 of item 32569'), +(15,8687,0,0,0,2,32720,1,0,0,0,'','Ancient Skull Pile - Show gossip option only if player has 1 of item 32720'), +(15,8689,0,0,0,2,32569,35,0,0,0,'','Show gossip option only if player has 35 of item 32569'), +(15,8690,0,0,0,2,32569,35,0,0,0,'','Show gossip option only if player has 35 of item 32569'), +(15,8691,0,0,0,2,32569,35,0,0,0,'','Show gossip option only if player has 35 of item 32569'), +(15,8718,1,0,0,5,1031,224,0,0,0,'','Skyguard Handler Irena - Show gossip option only if player is honored, revered or exalted with Sha''tari Skyguards'), +(15,8719,1,0,0,5,1031,224,0,0,0,'','Skyguard Handler Deesak - Show gossip option only if player is honored, revered or exalted with Sha''tari Skyguards'); diff --git a/sql/updates/world/2012_05_31_00_world_reference_loot_template.sql b/sql/updates/world/2012_05_31_00_world_reference_loot_template.sql new file mode 100644 index 00000000000..03723c82536 --- /dev/null +++ b/sql/updates/world/2012_05_31_00_world_reference_loot_template.sql @@ -0,0 +1,2 @@ +UPDATE `reference_loot_template` SET `entry`=14011 WHERE `entry`=3014; +UPDATE `creature_loot_template` SET `mincountOrRef`=-14011 WHERE `mincountOrRef`=-3014; diff --git a/sql/updates/world/2012_05_31_01_world_item_template.sql b/sql/updates/world/2012_05_31_01_world_item_template.sql new file mode 100644 index 00000000000..144ee6715a9 --- /dev/null +++ b/sql/updates/world/2012_05_31_01_world_item_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE `item_template` ADD `flagsCustom` INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `maxMoneyLoot`; +UPDATE `item_template` SET `flagsCustom`=`flagsCustom`|0x1 WHERE `Duration`<0; +UPDATE `item_template` SET `duration`=ABS(`duration`); +ALTER TABLE `item_template` CHANGE `Duration` `duration` INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `ArmorDamageModifier`; diff --git a/sql/updates/world/2012_05_31_01_world_sai.sql b/sql/updates/world/2012_05_31_01_world_sai.sql new file mode 100644 index 00000000000..3055e98f167 --- /dev/null +++ b/sql/updates/world/2012_05_31_01_world_sai.sql @@ -0,0 +1,139 @@ +-- http://www.youtube.com/watch?v=G89A9ITuTfs +-- Missing combat spell entries; Cata spells: 70316 (Cleave),84419 (Challenging Shout) + +-- Paval should also attack --- faction 35 to 232 ---- +-- Couldn't fix Ogron evading when entering combat + +-- [Q] Questioning Reethe +SET @ENTRY_OGRON := 4983; -- Ogron +SET @ENTRY_PAVAL := 4980; -- Paval Reethe +SET @ENTRY_CALDWELL := 5046; -- Lieutenant Caldwell +SET @ENTRY_SKIRM := 5044; -- Theramore Skirmisher +SET @ENTRY_HALAN := 5045; -- Private Hallan +SET @SPELL_FAKE_SHOT := 7105; + +-- Quest completable by external event +UPDATE `quest_template` SET `SpecialFlags`=`SpecialFlags`|2 WHERE `Id`=1273; -- Questioning Reethe + +-- Set SAI AIName +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (@ENTRY_OGRON,@ENTRY_PAVAL,@ENTRY_CALDWELL,@ENTRY_SKIRM,@ENTRY_HALAN); + +-- Template updates +UPDATE `creature` SET `spawntimesecs`=120 WHERE `id`=@ENTRY_PAVAL; +UPDATE `creature_template` SET `faction_A`=35,`faction_H`=35 WHERE `entry` IN (@ENTRY_CALDWELL,@ENTRY_SKIRM,@ENTRY_HALAN); -- Script changes faction to 151 later +UPDATE `creature_template` SET `equipment_id`=189 WHERE `entry`=@ENTRY_HALAN; +UPDATE `creature_model_info` SET `bounding_radius`=1.29485,`combat_reach`=2.175,`gender`=0 WHERE `modelid`=10704; -- Ogron +DELETE FROM `creature_template_addon` WHERE `entry` IN (@ENTRY_OGRON,@ENTRY_PAVAL); +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(@ENTRY_OGRON,0,0,257,0,NULL),-- Ogron +(@ENTRY_PAVAL,0,0,1,0,NULL); -- Paval Reethe + +-- Waypoints +DELETE FROM `waypoints` WHERE `entry`=@ENTRY_OGRON; +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(@ENTRY_OGRON,1,-3349.78,-3134.81,28.5267,'Ogron'), +(@ENTRY_OGRON,2,-3366.01,-3144.31,35.2659,'Ogron'), +(@ENTRY_OGRON,3,-3367.34,-3164.10,35.9618,'Ogron'), +(@ENTRY_OGRON,4,-3372.77,-3174.81,35.8517,'Ogron'), +(@ENTRY_OGRON,5,-3378.53,-3191.64,35.7204,'Ogron'), +(@ENTRY_OGRON,6,-3370.92,-3190.48,34.1671,'Ogron'), +(@ENTRY_OGRON,7,-3366.86,-3209.47,33.9713,'Ogron'); +-- (@ENTRY_OGRON,8,-3365.56,-3209.19,34.0187,'Ogron'); + +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY_OGRON,@ENTRY_HALAN,@ENTRY_SKIRM,@ENTRY_CALDWELL,@ENTRY_PAVAL) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY_OGRON*100,@ENTRY_OGRON*100+1,@ENTRY_CALDWELL*100,@ENTRY_HALAN*100,@ENTRY_PAVAL*100,@ENTRY_CALDWELL*100+1,@ENTRY_PAVAL*100+1,@ENTRY_OGRON*100+2) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY_OGRON,0,0,0,6,0,100,0,0,0,0,0,6,1273,0,0,0,0,0,7,0,0,0,0,0,0,0,'Ogron - On Death - Fail Quest'), +(@ENTRY_OGRON,0,1,0,19,0,100,0,1273,0,0,0,80,@ENTRY_OGRON*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - On Quest Accept - Script'), +(@ENTRY_OGRON*100,9,0,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'Ogron - On Script - Say "I noticed some fire.."'), +(@ENTRY_OGRON*100,9,1,0,0,0,100,0,0,0,0,0,53,0,@ENTRY_OGRON,0,0,0,2,1,0,0,0,0,0,0,0,'Ogron - On Script - Start WP'), +(@ENTRY_OGRON,0,2,0,40,0,100,0,5,@ENTRY_OGRON,0,0,54,3000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - On WP 5 - Pause Path'), +(@ENTRY_OGRON,0,3,4,55,0,100,0,5,@ENTRY_OGRON,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - On WP 5 - Say "That''s Reethe..."'), -- Link to 4 +(@ENTRY_OGRON,0,4,0,61,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,6.281,'Ogron - On Link (WP 5) - Set Orientation'), +(@ENTRY_OGRON,0,5,0,58,0,100,0,7,@ENTRY_OGRON,0,0,80,@ENTRY_OGRON*100+1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - On WP 7 - Run Second Script'), +(@ENTRY_OGRON*100+1,9,0,0,0,0,100,0,0,0,0,0,54,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Paval - On Script - Pause WP'), +(@ENTRY_OGRON*100+1,9,1,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "W-what do you..."'), +(@ENTRY_OGRON*100+1,9,2,0,0,0,100,0,4000,4000,0,0,1,1,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "I swear, I didn''t..."'), +(@ENTRY_OGRON*100+1,9,3,0,0,0,100,0,4000,4000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - On Script - Say "Just tell us..."'), +(@ENTRY_OGRON*100+1,9,4,0,0,0,100,0,3500,3500,0,0,1,2,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "I... Well, I may..."'), +(@ENTRY_OGRON*100+1,9,5,0,0,0,100,0,3500,3500,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - On Script - Say "Look here,if you..."'), +(@ENTRY_OGRON*100+1,9,6,0,0,0,100,0,2000,2000,0,0,1,3,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "Not one step closer..."'), +(@ENTRY_OGRON*100+1,9,7,0,0,0,100,0,3000,3000,0,0,1,4,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "And I don''t know..."'), +(@ENTRY_OGRON*100+1,9,8,0,0,0,100,0,3500,3500,0,0,1,5,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "What was that? Did..."'), +(@ENTRY_OGRON*100+1,9,9,0,0,0,100,0,0,0,0,0,12,@ENTRY_HALAN,2,5*60*1000,0,0,0,8,0,0,0,-3384.600098,-3211.340088,34.868,0,'Ogron - On Script - Summon Private Hallan'), +(@ENTRY_OGRON*100+1,9,10,0,0,0,100,0,0,0,0,0,12,@ENTRY_SKIRM,2,5*60*1000,0,0,0,8,0,0,0,-3384.443604,-3208.477539,34.849,0,'Ogron - On Script - Summon Theramore Skirmisher'), +(@ENTRY_OGRON*100+1,9,11,0,0,0,100,0,0,0,0,0,12,@ENTRY_SKIRM,2,5*60*1000,0,0,0,8,0,0,0,-3385.615234,-3209.867432,34.904,0,'Ogron - On Script - Summon Theramore Skirmisher'), +(@ENTRY_OGRON*100+1,9,12,0,0,0,100,0,0,0,0,0,12,@ENTRY_CALDWELL,2,5*60*1000,0,0,0,8,0,0,0,-3381.498535,-3209.195068,35.037,0,'Ogron - On Script - Summon Lieutenant Caldwell'), +(@ENTRY_OGRON*100+1,9,13,0,0,0,100,0,0,0,0,0,8,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - On Script - Set react state aggresive'), + +(@ENTRY_HALAN,0,0,0,11,0,100,0,0,0,0,0,46,5,0,0,0,0,0,1,0,0,0,0,0,0,0,'Hallan - On Spawn - Move forward'), +(@ENTRY_SKIRM,0,0,0,11,0,100,0,0,0,0,0,46,4.5,0,0,0,0,0,1,0,0,0,0,0,0,0,'Skirmisher - On Spawn - Move forward'), +(@ENTRY_HALAN,0,1,0,11,0,100,0,0,0,0,0,59,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Hallan - On Spawn - Set Run 0'), +(@ENTRY_SKIRM,0,1,0,11,0,100,0,0,0,0,0,59,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Skirmisher - On Spawn - Set Run 0'), + +(@ENTRY_CALDWELL,0,0,0,11,0,100,0,0,0,0,0,80,@ENTRY_CALDWELL*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Caldwell - On spawn - Script'), +(@ENTRY_CALDWELL*100,9,0,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,-3373.983398,-3210.881104,34.711,0,'Caldwell - On Script - Move'), +(@ENTRY_CALDWELL*100,9,1,0,0,0,100,0,2000,2000,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'Caldwell - On Script - Say "Paval Reethe! Found..."'), +(@ENTRY_CALDWELL*100,9,2,0,0,0,100,0,4000,4000,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,'Caldwell - On Script - Say "Private, show Lieutenant..."'), +(@ENTRY_CALDWELL*100,9,3,0,0,0,100,0,500,500,0,0,45,1,1,0,0,0,0,11,@ENTRY_HALAN,20,0,0,0,0,0,'Caldwell - On Script - Set Data Hallan'), + +(@ENTRY_HALAN,0,2,0,38,0,100,0,1,1,0,0,80,@ENTRY_HALAN*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Hallan - On Data Set - Run Script'), +(@ENTRY_HALAN*100,9,0,0,0,0,100,0,1000,1000,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'Hallan - On Script - Say "Gladly, sir."'), +(@ENTRY_HALAN*100,9,1,0,0,0,100,0,0,0,0,0,11,@SPELL_FAKE_SHOT,0,0,0,0,0,11,@ENTRY_PAVAL,60,0,0,0,0,0,'Hallan - On Script - Cast Fake Shot'), + +(@ENTRY_PAVAL,0,0,0,8,0,100,0,@SPELL_FAKE_SHOT,0,0,0,80,@ENTRY_PAVAL*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Paval - On Spellhit - Run Script'), +(@ENTRY_PAVAL*100,9,0,0,0,0,100,0,0,0,0,0,1,6,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "Paval staggers back..."'), +(@ENTRY_PAVAL*100,9,1,0,0,0,100,0,2000,2000,0,0,1,7,0,0,0,0,0,9,@ENTRY_PAVAL,0,15,0,0,0,0,'Paval - On Script - Say "Ugh... Hallan..."'), +(@ENTRY_PAVAL*100,9,2,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.771,'Paval - On Script - Face Caldwell'), +(@ENTRY_PAVAL*100,9,3,0,0,0,100,0,2000,2000,0,0,1,2,0,0,0,0,0,9,@ENTRY_CALDWELL,0,15,0,0,0,0,'Caldwell - On Script - Say "Now let''s..."'), +(@ENTRY_PAVAL*100,9,4,0,0,0,100,0,1000,1000,0,0,1,4,0,0,0,0,0,9,@ENTRY_OGRON,0,15,0,0,0,0,'Ogron - On Script - Say "Damn it! You..."'), +(@ENTRY_PAVAL*100,9,5,0,0,0,100,0,0,0,0,0,2,16,0,0,0,0,0,9,@ENTRY_HALAN,0,15,0,0,0,0,'Paval - On Script - Set faction 151 on Hallan'), +(@ENTRY_PAVAL*100,9,6,0,0,0,100,0,0,0,0,0,2,16,0,0,0,0,0,9,@ENTRY_SKIRM,0,15,0,0,0,0,'Paval - On Script - Set faction 151 on Skirm'), +(@ENTRY_PAVAL*100,9,7,0,0,0,100,0,0,0,0,0,2,16,0,0,0,0,0,9,@ENTRY_CALDWELL,0,15,0,0,0,0,'Paval - On Script - Set faction 151 on Caldwell'), + +(@ENTRY_CALDWELL,0,1,0,6,0,100,0,0,0,0,0,45,1,1,0,0,0,0,11,@ENTRY_PAVAL,20,0,0,0,0,0,'Caldwell - On Death - Set data to Paval'), +(@ENTRY_CALDWELL,0,2,0,6,0,100,0,0,0,0,0,45,1,1,0,0,0,0,11,@ENTRY_OGRON,20,0,0,0,0,0,'Caldwell - On Death - Set data to Ogron'), +(@ENTRY_OGRON,0,7,0,38,0,100,0,1,1,0,0,69,0,0,0,0,0,0,8,0,0,0,-3366.86,-3209.47,33.9713,0,'Ogron - On Data set - Move to pos'), +(@ENTRY_PAVAL,0,6,0,38,0,100,0,1,1,0,0,80,@ENTRY_PAVAL*100+1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Paval - On Data Set - Run second timed action list'), +(@ENTRY_PAVAL*100+1,9,0,0,0,0,100,0,0,0,0,0,15,1273,0,0,0,0,0,17,0,15,0,0,0,0,0,'Paval - On Script - Quest Credit'), +(@ENTRY_PAVAL*100+1,9,1,0,0,0,100,0,2000,2000,0,0,84,5,0,0,0,0,0,9,@ENTRY_OGRON,0,15,0,0,0,0,'Ogron - On Script - Say "Still with us..."'), +(@ENTRY_PAVAL*100+1,9,2,0,0,0,100,0,2000,2000,0,0,1,8,0,0,0,0,0,1,0,0,0,0,0,0,0,'Paval - On Script - Say "Must be your lucky day..."'), +(@ENTRY_PAVAL*100+1,9,3,0,0,0,100,0,0,0,0,0,37,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Paval - On Script - Die'), +(@ENTRY_PAVAL*100+1,9,4,0,0,0,100,0,1000,1000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Paval - On Script - Despawn'), +(@ENTRY_PAVAL*100+1,9,5,0,0,0,100,0,1000,1000,0,0,84,6,0,0,0,0,0,9,@ENTRY_OGRON,0,15,0,0,0,0,'Ogron - On Script - Say "Looks dead to me..."'), +(@ENTRY_PAVAL*100+1,9,6,0,0,0,100,0,3500,3500,0,0,84,7,0,0,0,0,0,9,@ENTRY_OGRON,0,15,0,0,0,0,'Ogron - On Script - Say "By the way..."'), +(@ENTRY_PAVAL*100+1,9,7,0,0,0,100,0,0,0,0,0,45,4,4,0,0,0,0,9,@ENTRY_OGRON,0,15,0,0,0,0,'Paval - On Script - Set Data Ogron'), + +(@ENTRY_OGRON,0,8,0,0,0,100,1,500,1500,0,0,1,8,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ogron - In combat say "Me smash.." or "I''ll crush you!"'); + +-- Texts +DELETE FROM `creature_text` WHERE `entry` IN (@ENTRY_OGRON,@ENTRY_PAVAL,@ENTRY_CALDWELL,@ENTRY_HALAN); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY_OGRON,0,0,'I noticed some fire on that island over there. A human, too. Let''s go check it out, $N.',12,0,0,0,0,0,'Ogron'), +(@ENTRY_OGRON,1,0,'That''s Reethe alright. Let''s go see what he has to say, yeah?',12,0,0,0,0,0,'Ogron'), + +(@ENTRY_PAVAL,0,0,'W-what do you want? Just leave me alone...',12,0,0,0,0,0,'Paval'), +(@ENTRY_PAVAL,1,0,'I swear, I didn''t steal anything from you! Here, take some of my supplies, just go away!',12,0,0,0,0,0,'Paval'), +(@ENTRY_OGRON,2,0,'Just tell us what you know about the Shady Rest Inn, and I won''t bash your skull in.',12,0,0,0,0,0,'Ogron'), +(@ENTRY_PAVAL,2,0,'I... Well, I may of taken a little thing or two from the inn... but what would an ogre care about that?',12,0,0,0,0,0,'Paval'), +(@ENTRY_OGRON,3,0,'Look here, if you don''t tell me about the fire--',12,0,0,0,0,0,'Ogron'), +(@ENTRY_PAVAL,3,0,'Not one step closer, ogre!',12,0,0,0,0,0,'Paval'), +(@ENTRY_PAVAL,4,0,'And I don''t know anything about this fire of yours...',12,0,0,0,0,0,'Paval'), +(@ENTRY_PAVAL,5,0,'What was that? Did you hear something?',12,0,0,0,0,0,'Paval'), + +(@ENTRY_CALDWELL,0,0,'Paval Reethe! Found you at last. And consorting with ogres now? No fear, even deserters and traitors are afforded some mercy.',12,0,0,0,0,0,'Caldwell'), +(@ENTRY_CALDWELL,1,0,'Private, show Lieutenant Reethe some mercy.',12,0,0,0,0,0,'Caldwell'), +(@ENTRY_HALAN,0,0,'Gladly, sir.',12,0,0,0,0,0,'Hallan'), +(@ENTRY_PAVAL,6,0,'%s staggers back as the arrow lodges itself deeply in his chest.',16,0,0,0,0,0,'Paval'), +(@ENTRY_PAVAL,7,0,'Ugh... Hallan, didn''t think you had it in you...',12,0,0,16,0,0,'Paval'), +(@ENTRY_CALDWELL,2,0,'Now, let''s clean up the rest of the trash, men!',12,0,0,0,0,0,'Caldwell'), +(@ENTRY_OGRON,4,0,'Damn it! You''d better not die on me, human!',12,0,0,0,0,0,'Ogron'), +-- QC +(@ENTRY_OGRON,5,0,'Still with us, Reethe?',12,0,0,0,0,0,'Ogron'), +(@ENTRY_PAVAL,8,0,'Must be your lucky day. Alright, I''ll talk. Just leave me alone. Look, you''re not going to believe me, but it wa... oh, Light, looks like the girl could shoot...',12,0,0,0,0,0,'Paval'), +-- Paval dies & despawns +(@ENTRY_OGRON,6,0,'Looks dead to me. Not much use to us like this. You''d better go back and tell Krog what happened.',12,0,0,0,0,0,'Ogron'), +(@ENTRY_OGRON,7,0,'By the way, thanks for watching my back.',12,0,0,0,0,0,'Ogron'), + +(@ENTRY_OGRON,8,0,'Me smash! You die!',12,0,0,0,0,0,'Ogron'), +(@ENTRY_OGRON,8,1,'I''ll crush you!',12,0,0,0,0,0,'Ogron'); diff --git a/sql/updates/world/2012_05_31_02_world_creature_model_info.sql b/sql/updates/world/2012_05_31_02_world_creature_model_info.sql new file mode 100644 index 00000000000..a1aa1155aa6 --- /dev/null +++ b/sql/updates/world/2012_05_31_02_world_creature_model_info.sql @@ -0,0 +1,4 @@ +-- Grunt Ounda should only have a female model +UPDATE `creature_model_info` SET + `modelid_other_gender` = 0 +WHERE `modelid` = 4260; diff --git a/sql/updates/world/2012_05_31_03_world_gameobject_loot_template.sql b/sql/updates/world/2012_05_31_03_world_gameobject_loot_template.sql new file mode 100644 index 00000000000..5dcedaaf342 --- /dev/null +++ b/sql/updates/world/2012_05_31_03_world_gameobject_loot_template.sql @@ -0,0 +1,4 @@ +-- Update drop chance of Ensorcelled Parchment from 0.2% to 100% +UPDATE `gameobject_loot_template` SET `ChanceOrQuestChance`=100 WHERE `entry`=1570 AND `item`=3706; +-- Change spawntime from 2 secs to 3 minutes +UPDATE `gameobject` SET `spawntimesecs`=180 WHERE `id`=1765; diff --git a/sql/updates/world/2012_05_31_05_world_sai.sql b/sql/updates/world/2012_05_31_05_world_sai.sql new file mode 100644 index 00000000000..aa95c93aae1 --- /dev/null +++ b/sql/updates/world/2012_05_31_05_world_sai.sql @@ -0,0 +1,30 @@ +-- Ai and Script Update/Addition for Taragaman the Hungerer +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11520; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11520; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11520; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(11520, 0, 0, 0, 0, 0, 85, 2, 5000, 5000, 15000, 20000, 11, 18072, 1, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 'Taragaman the Hungerer - Cast Uppercut'), +(11520, 0, 1, 0, 0, 0, 75, 2, 8000, 8000, 20000, 25000, 11, 11970, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 'Taragaman the Hungerer - Cast Fire Nova'); + +-- Ai and Script Update/Addition for Jergosh the Invoker +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11518; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11518; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11518; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(11518, 0, 1, 0, 0, 0, 75, 2, 12000, 12000, 30000, 30000, 11, 20800, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Jergosh the Invoker - Cast Immolat'), +(11518, 0, 0, 0, 0, 0, 85, 2, 30000, 30000, 120000, 120000, 11, 11980, 1, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 'Jergosh the Invoker - Cast Curse of Weakness'); + +-- Ai and Script Update/Addition for Bazzalan +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11519; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11519; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11519; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(11519, 0, 1, 0, 0, 0, 75, 2, 3000, 5000, 12000, 15000, 11, 2818, 1, 32, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Bazzalan - Cast Poison'), +(11519, 0, 0, 0, 0, 0, 85, 2, 8000, 8000, 16000, 17000, 11, 14873, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Bazzalan - Cast Sinister Strike'); + +-- Ai and Script Update/Addition for Oggleflint +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11517; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11517; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11517; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(11517, 0, 0, 0, 0, 0, 70, 2, 8000, 8000, 15000, 15000, 11, 40505, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Oggleflint - Cast Cleave'); diff --git a/sql/updates/world/2012_05_31_06_world_gameobject.sql b/sql/updates/world/2012_05_31_06_world_gameobject.sql new file mode 100644 index 00000000000..1db1d6fbd76 --- /dev/null +++ b/sql/updates/world/2012_05_31_06_world_gameobject.sql @@ -0,0 +1,7 @@ +-- Add Missing Draconic for Dummies Objects +SET @GUID := 4595; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @GUID AND @GUID+2; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@GUID,180665,0,1,1,-8340.196,413.7499,124.489677,2.82742977,0,0,0.987688,0.156436,180,255,1), +(@GUID+1,180666,0,1,1,1628.83984,133.9376,-60.96726,-0.401424885,0,0,-0.199368,0.979925,180,255,1), +(@GUID+2,180667,469,1,1,-7526.57,-924.776,458.826,0.558504,0,0,0.275637,0.961262,180,255,1); diff --git a/sql/updates/world/2012_05_31_07_world_gossip.sql b/sql/updates/world/2012_05_31_07_world_gossip.sql new file mode 100644 index 00000000000..9b82f333a4c --- /dev/null +++ b/sql/updates/world/2012_05_31_07_world_gossip.sql @@ -0,0 +1,4 @@ +-- Add missing gossip for Draconic for Dummies objects +DELETE FROM `gossip_menu` WHERE `entry` IN (6668,6669,6670); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(6668,7937),(6669,7937),(6670,7937); diff --git a/sql/updates/world/2012_05_31_08_world_gameobject_template.sql b/sql/updates/world/2012_05_31_08_world_gameobject_template.sql new file mode 100644 index 00000000000..41527e22919 --- /dev/null +++ b/sql/updates/world/2012_05_31_08_world_gameobject_template.sql @@ -0,0 +1,2 @@ +-- Fix faction for Draconic for Dummies objects +UPDATE `gameobject_template` SET `faction`=35 WHERE `entry` IN (180665,180667); diff --git a/sql/updates/world/2012_05_31_09_world_sai.sql b/sql/updates/world/2012_05_31_09_world_sai.sql new file mode 100644 index 00000000000..a7eb1248905 --- /dev/null +++ b/sql/updates/world/2012_05_31_09_world_sai.sql @@ -0,0 +1,27 @@ + -- EAI to SAI Convert Ragefire Trogg +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11318; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11318; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11318; +INSERT INTO smart_scripts (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) +VALUES (11318, 0, 0, 0, 9, 0, 100, 2, 0, 5, 5000, 8000, 11, 11976, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Ragefire Trogg - Cast Strike'); + +-- EAI to SAI Convert Earthborer +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11320; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11320; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11320; +INSERT INTO smart_scripts (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) +VALUES (11320, 0, 0, 0, 0, 0, 70, 2, 6000, 6000, 10000, 10000, 11, 18070, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Earthborer - Cast Earthborer Acid'); + +-- EAI to SAI Convert Searing Blade Cultist +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11322; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11322; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11322; +INSERT INTO smart_scripts (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) +VALUES (11322, 0, 0, 0, 0, 0, 85, 2, 12000, 12000, 30000, 30000, 11, 18266, 1, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 'Searing Blade Cultist - Cast Curse of Agony'); + +-- EAI to SAI Convert Searing Blade Enforcer +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=11323; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11323; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=11323; +INSERT INTO smart_scripts (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) +VALUES (11323, 0, 0, 0, 0, 0, 75, 2, 8000, 8000, 10000, 10000, 11, 8242, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Searing Blade Enforcer - Cast Shield Slam'); diff --git a/sql/updates/world/2012_05_31_10_world_creature_template.sql b/sql/updates/world/2012_05_31_10_world_creature_template.sql new file mode 100644 index 00000000000..5499d26b0e3 --- /dev/null +++ b/sql/updates/world/2012_05_31_10_world_creature_template.sql @@ -0,0 +1,2 @@ +-- update the book to always drop of ragnaros +UPDATE `creature_loot_template` SET `ChanceOrQuestChance`=-100 WHERE `entry`=11502 AND `item`=21110; diff --git a/sql/updates/world/2012_05_31_11_world_creature.sql b/sql/updates/world/2012_05_31_11_world_creature.sql new file mode 100644 index 00000000000..177c6230964 --- /dev/null +++ b/sql/updates/world/2012_05_31_11_world_creature.sql @@ -0,0 +1,6 @@ +-- Add a couple more Domesticated Felboar Spawns +SET @GUID := 42567; +DELETE FROM `creature` WHERE `guid` IN (@GUID,@GUID+1); +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@GUID,21195,530,1,1,0,0,-2678.16016,1477.65625,26.9172077,4.86340427,300,5,0,1,0,1), +(@GUID+1,21195,530,1,1,0,0,-2691.666,1525,21.3857346,0.3155697,300,5,0,1,0,1); diff --git a/sql/updates/world/2012_05_31_12_world_creature.sql b/sql/updates/world/2012_05_31_12_world_creature.sql new file mode 100644 index 00000000000..cad0364d021 --- /dev/null +++ b/sql/updates/world/2012_05_31_12_world_creature.sql @@ -0,0 +1,9 @@ +-- Add missing 7th Legion Chain Gun spawns +DELETE FROM `creature` WHERE `guid` IN (42569,42570,42663,42664); +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(42569,27714,571,1,1,25331,0,3665.613,-1209.412,102.4201,4.206244,120,0,0,1,0,0), +(42570,27714,571,1,1,25331,0,3660.56,-1207.094,102.4201,4.29351,120,0,0,1,0,0), +(42663,27714,571,1,1,25331,0,3677.009,-1174.462,102.3367,1.169371,120,0,0,1,0,0), +(42664,27714,571,1,1,25331,0,3682.874,-1177.179,102.4757,1.169371,120,0,0,1,0,0); +-- Add Spells for 7th Legion Chain Gun +UPDATE `creature_template` SET `spell1`=49190,`spell2`=49550 WHERE `entry`=27714; diff --git a/sql/updates/world/2012_06_01_00_world_spell_script_names.sql b/sql/updates/world/2012_06_01_00_world_spell_script_names.sql new file mode 100644 index 00000000000..cc024fe71cb --- /dev/null +++ b/sql/updates/world/2012_06_01_00_world_spell_script_names.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN (50341,50344); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(50341, 'spell_gen_touch_the_nightmare'), +(50344, 'spell_gen_dream_funnel'); diff --git a/sql/updates/world/2012_06_01_01_world_creature_script.sql b/sql/updates/world/2012_06_01_01_world_creature_script.sql new file mode 100644 index 00000000000..d90800bd1af --- /dev/null +++ b/sql/updates/world/2012_06_01_01_world_creature_script.sql @@ -0,0 +1,2 @@ +-- Add Generic Harpoon gun script to prevent movement +UPDATE `creature_template` SET `ScriptName`= 'npc_generic_harpoon_cannon' WHERE `entry` IN (27714,30066,30337); diff --git a/sql/updates/world/2012_06_01_02_world_misc.sql b/sql/updates/world/2012_06_01_02_world_misc.sql new file mode 100644 index 00000000000..23663ef9270 --- /dev/null +++ b/sql/updates/world/2012_06_01_02_world_misc.sql @@ -0,0 +1,70 @@ +/* Quest: Kick, What Kick? - 12589 by Nay */ + +-- Lucky Wilhelm: 0xF150006D960041CB +-- Drostan: 0xF130006EA80041CA +-- Apple: 0xF130006D950041C8 + +-- Remove old conditions, now done in cpp +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry`=51330; + +-- Spells conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (51331,51332,51366); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 51331, 0, 0, 31, 0, 3, 28053, 0, 0, 0, '', 'Hit Apple - Apple - Q: Kick, What Kick?'), +(13, 1, 51332, 0, 0, 31, 0, 3, 28054, 0, 0, 0, '', 'Miss Apple - Wilhelm - Q: Kick, What Kick?'), +(13, 1, 51366, 0, 0, 31, 0, 3, 28093, 0, 0, 0, '', 'Miss Apple, Hit Bird - Sholazar Tickbird - Q: Kick, What Kick?'); + +-- Assign script to spell +DELETE FROM `spell_script_names` WHERE `spell_id`=51330; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(51330, 'spell_q12589_shoot_rjr'); + +-- Spellclick spell for Wilhelm +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=28054; +INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`cast_flags`,`user_type`) VALUES +(28054,50556,1,0); + +-- Addon data +DELETE FROM `creature_template_addon` WHERE `entry` IN (28053,28328,30737,28346); +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(28053,0,0,1,0, NULL), -- Apple +(28328,0,0,257,0, NULL), -- Drostan +(30737,0,0,256,0, NULL), -- Nesingwary Game Warden +(28346,0,0,1,0, NULL); -- Crunchy + +-- Put Apple in Wilhelm's head +DELETE FROM `vehicle_template_accessory` WHERE `entry`=28054 AND `accessory_entry`=28053; +INSERT INTO `vehicle_template_accessory` (`entry`,`accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES +(28054, 28053, -1, 0, 'Lucky Wilhelm - Apple', 6, 10000); + +-- Says and yells +DELETE FROM `creature_text` WHERE `entry`=28328 OR (`entry`=28054 AND `groupid` IN (0,1)); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(28328, 0, 0, 'The only thing hurt is your pride, lad. Buck up!', 12, 0, 100, 11, 0, 0, 'Drostan to Lucky Wilhelm'), +(28328, 0, 1, 'Stop whining. You''ve still got your luck.', 12, 0, 100, 11, 0, 0, 'Drostan to Lucky Wilhelm'), +(28328, 0, 2, 'Bah, it''s an improvement.', 12, 0, 100, 0, 0, 0, 'Drostan to Lucky Wilhelm'), +(28328, 0, 3, 'Calm down lad, it''s just a birdshot!', 12, 0, 100, 0, 0, 0, 'Drostan to Lucky Wilhelm'), +(28054, 0, 0, 'Not the ''stache! Now I''m asymmetrical!', 12, 0, 100, 5, 0, 0, 'Lucky Wilhelm'), +(28054, 0, 1, 'Ouch! That''s it, I quit the target business!', 12, 0, 100, 0, 0, 0, 'Lucky Wilhelm'), +(28054, 0, 2, 'My ear! You grazed my ear!', 12, 0, 100, 0, 0, 0, 'Lucky Wilhelm'), +(28054, 1, 0, 'Good shot!', 12, 0, 100, 4, 0, 0, 'Lucky Wilhelm'); + +/* * Hit: */ +/* player casts Shoot RJR on Lucky */ +/* apple gets hit by 51331 (Hit Apple) by player */ +/* after that apple casts 51371 (Apple Falls to ground) on self */ +/* Wilhelm says Good shot! */ +/* reward killcredit 28053 */ + +/* * Miss: */ +/* player casts Shoot RJR on Lucky */ +/* lucky gets hit by 51332 (Miss Apple) by player */ +/* lucky says random text */ +/* drostan says random text */ + +/* * Miss, Hit Bird - guessed */ +/* player casts Shoot RJR on Lucky */ +/* bird gets hit by 51366 (Miss Apple, Hit Bird and dies) */ +/* bird gets hit by 51369 (Tickbird Signal to Fall) */ +/* lucky says random text */ +/* drostan says random text */ diff --git a/sql/updates/world/2012_06_01_03_world_creature_template.sql b/sql/updates/world/2012_06_01_03_world_creature_template.sql new file mode 100644 index 00000000000..fb20691ad69 --- /dev/null +++ b/sql/updates/world/2012_06_01_03_world_creature_template.sql @@ -0,0 +1,2 @@ +-- Set same flag for diff_entry_1 +UPDATE `creature_template` SET `npcflag`=129 WHERE `entry`=30796; diff --git a/sql/updates/world/2012_06_01_04_world_misc.sql b/sql/updates/world/2012_06_01_04_world_misc.sql new file mode 100644 index 00000000000..d5273cec233 --- /dev/null +++ b/sql/updates/world/2012_06_01_04_world_misc.sql @@ -0,0 +1,41 @@ +-- Creature addon +DELETE FROM `creature_template_addon` WHERE `entry` IN (26421,26321,26333); +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(26421,0,0,1,0, NULL), -- Woodlands Walker +(26321,0,0,1,64, '47044'), -- Lothalor Ancient (Cosmetic - Confused State Visual (Big)) +(26333,0,0,1,0, '32566 46967'); -- Corrupted Lothalor Ancient (Purple Banish State, Purple Banish State - Breath) + +-- Woodlands Walker already has spellclick spell: 47575 (Strengthen the Ancients: On Interact Dummy to Woodlands Walker) + +-- Monster emotes +DELETE FROM `creature_text` WHERE `entry` IN (26421,26321); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(26421, 0, 0, 'Breaking off a piece of its bark, the %s hands it to you before departing.', 16, 0, 100, 0, 0, 0, 'Woodlands Walker'), +(26421, 1, 0, 'The %s is angered by your request and attacks!', 16, 0, 100, 0, 0, 0, 'Woodlands Walker'), +(26321, 0, 0, 'The %s gives you its thanks.', 16, 0, 100, 0, 0, 1525, 'Lothalor Ancient'); + +-- Assign scripts to spells +DELETE FROM `spell_script_names` WHERE `spell_id` IN (47575,47530); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(47575, 'spell_q12096_q12092_dummy'), +(47530, 'spell_q12096_q12092_bark'); + +/* +- player spellclicks Woodlands Walker, casts 47575 on the tree Woodlands Walker: two outcomes: + +- - tree turns enemy: +* say The %s is angered by your request and attacks! +* change faction to 14 +* start attack + +- - tree stays friendly: +* cast 47550 (Create Bark of the Walkers)on player +* say Breaking off a piece of its bark, the %s hands it to you before departing. +* despawn + + +- player uses item on Lothalor Ancient (47530 (Bark of the Walkers)): +* tree says The %s gives you its thanks. +* aura 47044 (Cosmetic - Confused State Visual (Big)) is removed +* despawns after 4 secs +*/ diff --git a/sql/updates/world/2012_06_02_00_world_sai.sql b/sql/updates/world/2012_06_02_00_world_sai.sql new file mode 100644 index 00000000000..af0b12be244 --- /dev/null +++ b/sql/updates/world/2012_06_02_00_world_sai.sql @@ -0,0 +1,118 @@ +-- Add missing gossip for quest 9738 "Lost in Action" +DELETE FROM `gossip_menu` WHERE `entry` IN (7521,7520,7540,7519,7525); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(7521,9121),(7520,9119),(7540,9144),(7519,9118),(7525,9125); +-- Add Gossip Options +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (7520,7540); +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(7520,0,0,"Alright, Bite, I'll let you out.",1,1,0,0,0,0,''), +(7540,0,0,"Naturalist, please grant me your boon.",1,1,0,0,0,0,''); +-- Conditions for the gossip options +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN (15) AND `SourceGroup` IN (7520,7540); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`comment`) VALUES +(15,7520,0,0,9,9738,'Gossip option 0 requires quest 9738 active'), +(15,7540,0,0,9,9738,'Gossip option 0 requires quest 9738 active'); -- cast 34906 on player +-- Add gossip to creature +UPDATE `creature_template` SET `gossip_menu_id`=7521 WHERE `entry`=17885; +UPDATE `creature_template` SET `gossip_menu_id`=7520 WHERE `entry`=17893; +UPDATE `creature_template` SET `gossip_menu_id`=7519 WHERE `entry`=17890; +UPDATE `creature_template` SET `gossip_menu_id`=7525 WHERE `entry`=17827; +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry` IN (17893,17957); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17893,0,0, 'Over here! Yeah, over here... I''m in this cage!!!',14,0,100,0,0,0, 'Naturalist Bite'), +(17893,1,0, 'Uh oh! It would appear that all of the noise you''ve been making has attracted some unwanted attention!',12,0,100,0,0,0, 'Naturalist Bite'), +(17957,0,0, 'Intrudersss with the prisssoner! Kill them!!!',14,0,100,0,0,0, 'Coilfang Champion'); +-- Earthbinder Rayge SAI +SET @ENTRY := 17885; +UPDATE `creature` SET `position_x`=296.6974,`position_y`=-362.373,`position_z`=50.15062,`orientation`=5.5676 WHERE `guid`=86372; +UPDATE `creature_template` SET `unit_flags`=512,`AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +UPDATE `creature_template_addon` SET `bytes2`=257,`auras`= '31526' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,64,0,100,6,0,0,0,0,33,@ENTRY,0,0,0,0,0,7,0,0,0,0,0,0,0,'Earthbinder Rayge - On Gossip Hello - Give Kill Credit'); +-- Weeder Greenthumb SAI +SET @ENTRY := 17890; +UPDATE `creature_template` SET `unit_flags`=512,`AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +UPDATE `creature_template_addon` SET `bytes1`=0,`bytes2`=257,`auras`= '29266' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,64,0,100,6,0,0,0,0,33,@ENTRY,0,0,0,0,0,7,0,0,0,0,0,0,0,'Weeder Greenthumb - On Gossip Hello - Give Kill Credit'); +-- Claw SAI +SET @ENTRY := 17827; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=9 AND `entryorguid`=@ENTRY*100; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,6,7400,7400,20000,20000,11,39435,0,0,0,0,0,5,0,0,0,0,0,0,0,'Claw - Combat - Cast Feral Charge'), +(@ENTRY,0,1,0,0,0,100,6,2400,2400,10600,21200,11,31429,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Combat - Cast Echoing Roar'), +(@ENTRY,0,2,0,0,0,100,6,5000,5000,30500,30500,11,34971,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Combat - Cast Frenzy'), +(@ENTRY,0,3,0,0,0,100,6,5300,5300,11100,21500,11,34298,0,0,0,0,0,2,0,0,0,0,0,0,0,'Claw - Combat - Cast Maul'), +(@ENTRY,0,4,0,2,1,100,7,0,20,0,0,80,@ENTRY*100,2,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - HP@20% - Run Script'), +(@ENTRY,0,5,0,64,0,100,6,0,0,0,0,33,17894,0,0,0,0,0,7,0,0,0,0,0,0,0,'Claw - On Gossip Hello - Give Kill Credit'), +(@ENTRY,0,6,0,6,0,100,6,0,0,0,0,45,0,1,0,0,0,0,19,17826,100,0,0,0,0,0,'Claw - On Death - Set Data on Swamplord Musel''ek'), +(@ENTRY,0,7,0,38,0,100,6,0,1,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Swamplord Musel''ek - On dataset - Set Phase 1'), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,28,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Remove all auras'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set Run on'), +(@ENTRY*100,9,2,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,289.2553,-129.7001,29.82101,2.495821,'Claw - Script - move to'), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,2,1660,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set faction'), +(@ENTRY*100,9,4,0,0,0,100,0,0,0,0,0,18,525072,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set unitflags'), +(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,3,0,2289,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set displayid'), +(@ENTRY*100,9,6,0,0,0,100,0,0,0,0,0,81,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set npcflags'), +(@ENTRY*100,9,7,0,0,0,100,0,4000,4000,4000,4000,69,0,0,0,0,0,0,8,0,0,0,290.5323,-125.3524,29.69708,1.824913,'Claw - Script - move to'), +(@ENTRY*100,9,8,0,0,0,100,0,0,0,0,0,3,17894,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set entry'), +(@ENTRY*100,9,9,0,0,0,100,0,0,0,0,0,18,557824,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set unitflags'), +(@ENTRY*100,9,10,0,0,0,100,0,0,0,0,0,90,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set bytes1'), +(@ENTRY*100,9,11,0,0,0,100,0,500,500,500,500,81,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Claw - Script - Set npcflags'); +-- Swamplord Musel'ek SAI +SET @ENTRY := 17826; +SET @SPELL1 := 18813; -- Knock Away +SET @SPELL2 := 22907; -- Shoot +SET @SPELL3 := 31615; -- Hunter's Mark +SET @SPELL4 := 31946; -- Throw Freezing Trap +SET @SPELL5 := 31623; -- Aimed Shot +SET @SPELL6 := 34974; -- Multi-Shot +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,1,0,0,0,100,6,35000,38000,30000,40000,11,@SPELL1,1,0,0,0,0,2,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Cast Knock Away'), +(@ENTRY,0,2,0,0,0,100,6,500,1000,2300,3900,11,@SPELL2,1,0,0,0,0,2,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Cast Knock Away'), +(@ENTRY,0,3,0,0,0,100,6,4000,8000,12000,16000,11,@SPELL3,0,0,0,0,0,6,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Cast Hunter''s Mark'), +(@ENTRY,0,4,0,0,0,100,6,4000,8000,12000,16000,11,@SPELL4,0,0,0,0,0,5,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Cast Throw Freezing Trap'), +(@ENTRY,0,5,6,0,0,100,6,12500,21500,20000,30000,11,@SPELL5,0,0,0,0,0,2,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Cast Aimed Shot'), +(@ENTRY,0,6,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Set ranged weapon'), +(@ENTRY,0,7,8,0,0,100,6,12500,21500,20000,30000,11,@SPELL6,0,0,0,0,0,2,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Cast Multi-Shot'), +(@ENTRY,0,8,0,61,0,100,0,0,0,0,0,40,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Set ranged weapon'), +(@ENTRY,0,9,0,4,0,100,6,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Swamplord Musel''ek - On Aggro - Say 1'), +(@ENTRY,0,10,0,5,0,100,6,5,5000,5000,1,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Swamplord Musel''ek - On Kill - Say 2'), +(@ENTRY,0,11,12,6,0,100,6,0,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Swamplord Musel''ek - On Death - Say 3'), +(@ENTRY,0,12,0,61,0,100,0,0,0,0,0,45,0,1,0,0,0,0,19,17827,100,0,0,0,0,0,'Swamplord Musel''ek - On Death - Set Data on Claw'), +(@ENTRY,0,13,14,38,0,100,6,0,1,0,0,70,0,0,0,0,0,0,19,17827,100,1,0,0,0,0,'Swamplord Musel''ek - On dataset - Respawn dead claw'), +(@ENTRY,0,14,0,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Swamplord Musel''ek - Combat - Say 0'); +-- NPC talk text insert from sniff +DELETE FROM `creature_ai_texts` WHERE `entry` BETWEEN -468 AND -463; +DELETE FROM `creature_text` WHERE `entry`=17826; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17826,0,0, 'Beast! Obey me! Kill them at once!',14,0,100,0,0,10383, 'Swamplord Musel''ek bear'), +(17826,1,0, 'We fight to the death!',14,0,100,0,0,10384, 'Swamplord Musel''ek Aggro'), +(17826,1,1, 'I will end this quickly...',14,0,100,0,0,10385, 'Swamplord Musel''ek Aggro'), +(17826,1,2, 'Acalah pek ecta!',14,0,100,0,0,10386, 'Swamplord Musel''ek Aggro'), +(17826,2,0, 'Krypta!',14,0,100,0,0,10387, 'Swamplord Musel''ek Slay'), +(17826,2,1, 'It is finished.',14,0,100,0,0,10388, 'Swamplord Musel''ek Slay'), +(17826,3,0, 'Well... done...',14,0,100,0,0,10389, 'Swamplord Musel''ek Death'); +-- Swamplord Musel'ek +SET @NPC := 56551; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=288.5823,`position_y`=-121.8309,`position_z`=29.70329,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`) VALUES (@NPC,@PATH,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,288.5823,-121.8309,29.70329,0,0,0,100,0), +(@PATH,2,281.5271,-120.3684,29.75141,0,0,0,100,0), +(@PATH,3,274.0677,-122.0538,29.80962,0,0,0,100,0), +(@PATH,4,281.5271,-120.3684,29.75141,0,0,0,100,0); diff --git a/sql/updates/world/2012_06_02_01_world_waypoints.sql b/sql/updates/world/2012_06_02_01_world_waypoints.sql new file mode 100644 index 00000000000..c50436bba8d --- /dev/null +++ b/sql/updates/world/2012_06_02_01_world_waypoints.sql @@ -0,0 +1,187 @@ +-- Ebon Blade Gargoyle +SET @NPC := 124428; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=8487.13,`position_y`=2648.587,`position_z`=661.3248,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`) VALUES (@NPC,@PATH,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,8487.13,2648.587,661.3248,0,0,0,100,0), +(@PATH,2,8489.394,2639.188,661.9919,0,0,0,100,0), +(@PATH,3,8498.239,2633.008,661.9919,0,0,0,100,0), +(@PATH,4,8514.016,2626.775,661.9919,0,0,0,100,0), +(@PATH,5,8529.975,2622.438,661.9919,0,0,0,100,0), +(@PATH,6,8556.946,2621.273,661.9919,0,0,0,100,0), +(@PATH,7,8576.765,2620.136,661.9919,0,0,0,100,0), +(@PATH,8,8584.989,2627.947,663.3527,0,0,0,100,0), +(@PATH,9,8590.352,2637.264,664.2969,0,0,0,100,0), +(@PATH,10,8597.313,2651.073,666.0464,0,0,0,100,0), +(@PATH,11,8590.045,2668.078,668.6855,0,0,0,100,0), +(@PATH,12,8577.563,2672.175,668.6855,0,0,0,100,0), +(@PATH,13,8567.869,2653.686,668.6855,0,0,0,100,0), +(@PATH,14,8559.406,2635.763,668.6855,0,0,0,100,0), +(@PATH,15,8550.115,2624.132,664.6028,0,0,0,100,0), +(@PATH,16,8538.325,2625.415,664.6028,0,0,0,100,0), +(@PATH,17,8531.294,2636.344,664.6028,0,0,0,100,0), +(@PATH,18,8536.005,2650.634,664.6028,0,0,0,100,0), +(@PATH,19,8536.659,2661.533,667.5744,0,0,0,100,0), +(@PATH,20,8528.161,2665.466,668.5468,0,0,0,100,0), +(@PATH,21,8521.834,2666.234,668.9914,0,0,0,100,0), +(@PATH,22,8506.145,2657.156,666.1024,0,0,0,100,0); + +-- Ebon Blade Gargoyle +SET @NPC := 124429; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=8553.722,`position_y`=2732.757,`position_z`=672.1373,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`) VALUES (@NPC,@PATH,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,8553.722,2732.757,672.1373,0,0,0,100,0), +(@PATH,2,8545.085,2736.81,677.1306,0,0,0,100,0), +(@PATH,3,8538.377,2724.997,676.7698,0,0,0,100,0), +(@PATH,4,8527.725,2701.114,677.464,0,0,0,100,0), +(@PATH,5,8515.729,2672.526,676.4364,0,0,0,100,0), +(@PATH,6,8501.882,2638.781,674.6306,0,0,0,100,0), +(@PATH,7,8492.601,2619.312,672.9641,0,0,0,100,0), +(@PATH,8,8501.216,2604.361,672.7973,0,0,0,100,0), +(@PATH,9,8509.95,2597.643,672.464,0,0,0,100,0), +(@PATH,10,8516.437,2603.336,670.7147,0,0,0,100,0), +(@PATH,11,8526.045,2624.93,675.242,0,0,0,100,0), +(@PATH,12,8538.438,2654.096,677.4644,0,0,0,100,0), +(@PATH,13,8552.567,2688.411,676.0737,0,0,0,100,0), +(@PATH,14,8561.252,2709.44,676.1867,0,0,0,100,0), +(@PATH,15,8564.74,2718.366,676.9643,0,0,0,100,0), +(@PATH,16,8586.875,2713.758,677.4359,0,0,0,100,0), +(@PATH,17,8588.923,2702.79,676.2701,0,0,0,100,0), +(@PATH,18,8580.09,2682.738,673.3813,0,0,0,100,0), +(@PATH,19,8572.153,2664.409,674.4087,0,0,0,100,0), +(@PATH,20,8559.122,2635.23,674.5473,0,0,0,100,0), +(@PATH,21,8547.672,2610.971,677.3528,0,0,0,100,0), +(@PATH,22,8547.112,2593.927,677.77,0,0,0,100,0), +(@PATH,23,8556.546,2591.858,678.7695,0,0,0,100,0), +(@PATH,24,8566.203,2601.376,677.2705,0,0,0,100,0), +(@PATH,25,8576.512,2615.707,675.7764,0,0,0,100,0), +(@PATH,26,8585.419,2632.535,673.7208,0,0,0,100,0), +(@PATH,27,8596.079,2656.51,673.0544,0,0,0,100,0), +(@PATH,28,8594.222,2669.849,673.4442,0,0,0,100,0), +(@PATH,29,8595.935,2690.9,673.4711,0,0,0,100,0), +(@PATH,30,8592.354,2705.919,675.5258,0,0,0,100,0), +(@PATH,31,8571.288,2721.3,668.0258,0,0,0,100,0); + +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`=32472; + +-- Vargul Plaguetalon +SET @NPC := 97634; +SET @PATH := @NPC*10; +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`=29453; +UPDATE `creature` SET `position_x`=5736.421,`position_y`=-1453.626,`position_z`=267.5013,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,5736.421,-1453.626,267.5013,0,0,0,100,0), +(@PATH,2,5700.896,-1467.002,263.9736,0,0,0,100,0), +(@PATH,3,5665.086,-1462.814,266.2513,0,0,0,100,0), +(@PATH,4,5623.596,-1446.303,258.3903,0,0,0,100,0), +(@PATH,5,5612.131,-1390.983,269.9736,0,0,0,100,0), +(@PATH,6,5630.01,-1325.786,252.9459,0,0,0,100,0), +(@PATH,7,5684.276,-1301.843,263.9736,0,0,0,100,0), +(@PATH,8,5717.019,-1325.604,263.9736,0,0,0,100,0), +(@PATH,9,5730.931,-1363.826,254.0014,0,0,0,100,0), +(@PATH,10,5737.854,-1429.533,273.2791,0,0,0,100,0); + +-- Scourgebeak Fleshripper +SET @NPC := 121011; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=6805.096,`position_y`=3548.115,`position_z`=785.0337,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,6805.096,3548.115,785.0337,0,0,0,100,0), +(@PATH,2,6797.807,3599.297,776.1726,0,0,0,100,0), +(@PATH,3,6840.798,3607.1,769.2557,0,0,0,100,0), +(@PATH,4,6880.369,3577.403,779.5615,0,0,0,100,0); + +-- Scourgebeak Fleshripper +SET @NPC := 121023; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=6490.46,`position_y`=3498.933,`position_z`=621.7417,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,6490.46,3498.933,621.7417,0,0,0,100,0), +(@PATH,2,6645.542,3512.415,678.8528,0,0,0,100,0), +(@PATH,3,6650.367,3555.357,680.6584,0,0,0,100,0), +(@PATH,4,6602.724,3563.045,661.1863,0,0,0,100,0), +(@PATH,5,6549.287,3554.462,642.825,0,0,0,100,0); + +-- Scourgebeak Fleshripper +SET @NPC := 121019; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=6653.509,`position_y`=3526.14,`position_z`=693.2337,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,6653.509,3526.14,693.2337,0,0,0,100,0), +(@PATH,2,6696.053,3579.272,700.4001,0,0,0,100,0), +(@PATH,3,6744.93,3562.146,704.2611,0,0,0,100,0), +(@PATH,4,6738.125,3521.812,692.5392,0,0,0,100,0); + +-- Scourgebeak Fleshripper +SET @NPC := 121017; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=6653.104,`position_y`=3415.26,`position_z`=672.1595,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,6653.104,3415.26,672.1595,0,0,0,100,0), +(@PATH,2,6717.518,3468.886,684.6567,0,0,0,100,0), +(@PATH,3,6771.674,3492.333,692.0456,0,0,0,100,0), +(@PATH,4,6728.592,3518.536,683.6566,0,0,0,100,0), +(@PATH,5,6627.954,3487.869,642.6566,0,0,0,100,0), +(@PATH,6,6571.027,3439.741,634.3512,0,0,0,100,0); + +-- Scourgebeak Fleshripper +SET @NPC := 121014; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=6641.402,`position_y`=3330.479,`position_z`=724.3008,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,6641.402,3330.479,724.3008,0,0,0,100,0), +(@PATH,2,6637.165,3426.095,701.4395,0,0,0,100,0), +(@PATH,3,6701.476,3449.434,708.6896,0,0,0,100,0), +(@PATH,4,6746.966,3410.158,735.9395,0,0,0,100,0), +(@PATH,5,6697.637,3352.607,725.0784,0,0,0,100,0); + +-- Scourgebeak Fleshripper +SET @NPC := 121025; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=6590.307,`position_y`=3325.47,`position_z`=699.1288,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,6590.307,3325.47,699.1288,0,0,0,100,0), +(@PATH,2,6543.557,3237.147,706.6288,0,0,0,100,0), +(@PATH,3,6518.691,3250.313,687.6565,0,0,0,100,0), +(@PATH,4,6512.266,3334.911,685.3231,0,0,0,100,0); + +-- Scourgebeak Fleshripper +SET @NPC := 121007; +SET @PATH := @NPC*10; +UPDATE `creature` SET `position_x`=6459.715,`position_y`=3049.952,`position_z`=701.608,`spawndist`=0,`MovementType`=2 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUE +(@PATH,1,6459.715,3049.952,701.608,0,0,0,100,0), +(@PATH,2,6485.836,3103.517,681.247,0,0,0,100,0), +(@PATH,3,6445.593,3154.588,677.886,0,0,0,100,0), +(@PATH,4,6392.533,3078.925,694.2471,0,0,0,100,0); diff --git a/sql/updates/world/2012_06_02_02_world_creature_text.sql b/sql/updates/world/2012_06_02_02_world_creature_text.sql new file mode 100644 index 00000000000..c38e413617d --- /dev/null +++ b/sql/updates/world/2012_06_02_02_world_creature_text.sql @@ -0,0 +1,22 @@ +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=39368; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(39368,0,0, 'All right, you twisted mess of broken gears, let''s get to work!',12,0,100,1,0,0, 'Drill Sergeant Steamcrank'), +(39368,1,0, 'I am going to teach you all what it takes to be a proper soldier!',12,0,100,5,0,0, 'Drill Sergeant Steamcrank'), +(39368,2,0, 'The first thing you need to learn is proper discipline.',12,0,100,1,0,0, 'Drill Sergeant Steamcrank'), +(39368,3,0, 'Show me that discipline with a proper salute when I say so!',12,0,100,5,0,0, 'Drill Sergeant Steamcrank'), +(39368,4,0, 'Okay, recruits, salute!',12,0,100,66,0,0, 'Drill Sergeant Steamcrank'), +(39368,5,0, 'Nice job!',12,0,100,273,0,0, 'Drill Sergeant Steamcrank'), +(39368,6,0, 'When you go into combat, it is important that you know how to intimidate the enemy with a deafening battle roar!',12,0,100,396,0,0, 'Drill Sergeant Steamcrank'), +(39368,7,0, 'When I give the signal,let loose your greatest roar!',12,0,100,1,0,0, 'Drill Sergeant Steamcrank'), +(39368,8,0, 'Let me hear that battle roar!',12,0,100,5,0,0, 'Drill Sergeant Steamcrank'), +(39368,9,0, 'Wow, nice and scary!',12,0,100,0,0,0, 'Drill Sergeant Steamcrank'), +(39368,10,0, 'Remember though, a key factor in winning any battle is positive reinforcement.',12,0,100,5,0,0, 'Drill Sergeant Steamcrank'), +(39368,11,0, 'Reward your fellow soldiers in battle with a resounding cheer. Now, cheer at me when I tell you to!',12,0,100,1,0,0, 'Drill Sergeant Steamcrank'), +(39368,12,0, 'Everyone, cheer!',12,0,100,0,0,0, 'Drill Sergeant Steamcrank'), +(39368,13,0, 'Fantastic!',12,0,100,273,0,0, 'Drill Sergeant Steamcrank'), +(39368,14,0, 'However, the most important part of battle is how you celebrate a good hard earned victory!',12,0,100,396,0,0, 'Drill Sergeant Steamcrank'), +(39368,15,0, 'Show me your best victory dance when I give the signal!',12,0,100,5,0,0, 'Drill Sergeant Steamcrank'), +(39368,16,0, 'Now, dance!',12,0,100,0,0,0, 'Drill Sergeant Steamcrank'), +(39368,17,0, 'Superb!',12,0,100,273,0,0, 'Drill Sergeant Steamcrank'), +(39368,18,0, 'You might be the best set of recruits I''ve ever seen! Let''s go through all of that again!',12,0,100,396,0,0, 'Drill Sergeant Steamcrank'); diff --git a/sql/updates/world/2012_06_02_03_world_creature_loot_template_hp.sql b/sql/updates/world/2012_06_02_03_world_creature_loot_template_hp.sql new file mode 100644 index 00000000000..cd6015929b1 --- /dev/null +++ b/sql/updates/world/2012_06_02_03_world_creature_loot_template_hp.sql @@ -0,0 +1,1132 @@ +SET @RefDLK := 26043; +SET @HFP := 6000; +SET @HFP1 := @HFP+1; +SET @HFP2 := @HFP+2; +SET @Scrolls := @HFP+3; +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +DELETE FROM `reference_loot_template` WHERE `entry` IN (@RefDLK,@HFP,@HFP1,@HFP2,@Scrolls); +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- Generic Lowlevel Ref1 +(@HFP,1,20,1,0,-4000,1), -- Grey level 61 +(@HFP,2,5,1,0,-4001,1), -- Grey level 64 +(@HFP,3,2,1,0,-4100,1), -- Green level 57 +(@HFP,4,2,1,0,-4101,1), -- Green level 58 +(@HFP,5,2,1,0,-4102,1), -- Green level 59 +(@HFP,6,2,1,0,-4103,1), -- Green level 60 +(@HFP,7,2,1,0,-4104,1), -- Green level 61 +(@HFP,8,2,1,0,-4105,1), -- Green level 62 +(@HFP,9,0.5,1,0,-4200,1), -- Blue level 60 +(@HFP,10,0.5,1,0,-4201,1), -- Blue level 61 +(@HFP,11,0.5,1,0,-4202,1), -- Blue level 62 +(@HFP,12,0.5,1,0,-4203,1), -- Blue level 63 +(@HFP,13,0.5,1,0,-4204,1), -- Blue level 64 +(@HFP,4500,0.1,1,0,1,1), -- Traveler's Backpack +(@HFP,3914,0.05,1,0,1,1), -- Journeyman's Backpack +-- Generic Lowlevel Ref2 +(@HFP1,1,20,1,0,-4000,1), -- Grey level 61 +(@HFP1,2,5,1,0,-4001,1), -- Grey level 64 +(@HFP1,3,2,1,0,-4103,1), -- Green level 60 +(@HFP1,4,2,1,0,-4104,1), -- Green level 61 +(@HFP1,5,2,1,0,-4105,1), -- Green level 62 +(@HFP1,6,0.5,1,0,-4200,1), -- Blue level 60 +(@HFP1,7,0.5,1,0,-4201,1), -- Blue level 61 +(@HFP1,8,0.5,1,0,-4202,1), -- Blue level 62 +(@HFP1,9,0.5,1,0,-4203,1), -- Blue level 63 +(@HFP1,10,0.5,1,0,-4204,1), -- Blue level 64 +-- High level Ref +(@HFP2,1,30,1,1,-4002,1), -- Grey level 64 items (ilvl 69) +(@HFP2,2,30,1,1,-4002,1), -- Grey level 67 items (ilvl 72) +(@HFP2,3,2,1,2,-4110,1), -- Green level 67 items (ilvl 111) +(@HFP2,4,2,1,2,-4111,1), -- Green level 68 items (ilvl 114) +(@HFP2,5,2,1,2,-4112,1), -- Green level 69 items (ilvl 117) +(@HFP2,6,0.5,1,3,-4208,1), -- Blue level 68 items (ilvl 115) +(@HFP2,7,0.5,1,3,-4209,1), -- Blue level 69 items (ilvl 115) +(@HFP2,8,0.5,1,3,-4210,1), -- Blue level 70 items (ilvl 115) +-- TBC Scrolls +(@Scrolls,33459,0,1,1,1,1), -- Scroll of Protection VI +(@Scrolls,33457,0,1,1,1,1), -- Scroll of Agility VI +(@Scrolls,33458,0,1,1,1,1), -- Scroll of Intellect VI +(@Scrolls,33460,0,1,1,1,1), -- Scroll of Spirit VI +(@Scrolls,33461,0,1,1,1,1), -- Scroll of Stamina VI +(@Scrolls,33462,0,1,1,1,1), -- Scroll of Strength VI +-- Doom Lord Kazzak +(@RefDLK,30732,0,1,1,1,1), -- Exodar Life-Staff +(@RefDLK,30733,0,1,1,1,1), -- Hope Ender +(@RefDLK,30734,0,1,1,1,1), -- Leggings of the Seventh Circle +(@RefDLK,30735,0,1,1,1,1), -- Ancient Spellcloak of the Highborne +(@RefDLK,30736,0,1,1,1,1), -- Ring of Flowing Light +(@RefDLK,30737,0,1,1,1,1), -- Gold-Leaf Wildboots +(@RefDLK,30738,0,1,1,1,1), -- Ring of Reciprocity +(@RefDLK,30739,0,1,1,1,1), -- Scaled Greaves of the Marksman +(@RefDLK,30740,0,1,1,1,1), -- Ripfiend Shoulderplates +(@RefDLK,30741,0,1,1,1,1); -- Topaz-Studded Battlegrips +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +DELETE FROM `creature_loot_template` WHERE `entry` IN (18728,187281,19191,16977,19354,17084,17057,16873,16871,19422,16907,19424,19423,16903,16901,19701,16876,16925,18952,16972,16973,17014,16844,19299,16847,16863,18981,16959,19434,16938,16937,19312,22461,19190,18733,24918,18977,17034,19459,19136,19264,16954,18678,18827,16947,16845,19457,16967,16966,22374,18978,16880,17058,22323,19261,17035,17053,16978,16846,16912,16911,19408,17039,16857,18677,19192,16946,16950,16934,19189,19188,16932,16933,20798,19458,16974,19415,16878,16870,19295,16867,19414,19413,19410,19411,16960,16879,16929,16928,16927,19282,19335,19443,16951,19349,19350,16968,26222,26223,16975,20145,16904,16906,16905,19527,16939,18679,19263,19298,16964,19442,24919,18975); +INSERT INTO `creature_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- Doom Lord Kazzak, NPC 18728 +-- --------------------------------------------------- +(18728,1,100,1,0,-@RefDLK,2), -- Two from Doom Loor Kazzak Reference +(18728,2,5,1,0,-4113,1), -- Level 70 TBC Green Reference +-- --------------------------------------------------- +-- Arazzius the Cruel, NPC 19191 +-- --------------------------------------------------- +(19191,21877,50,1,0,1,3), -- Netherweave Cloth +(19191,27854,5,1,0,1,1), -- Smoked Talbuk Venison +(19191,28399,5,1,0,1,1), -- Filtered Draenic Water +(19191,13446,1.5,1,0,1,1), -- Major Healing Potion +(19191,13444,1.5,1,0,1,1), -- Major Mana Potion +(19191,1,15,1,0,-4000,1), -- Grey itemlevel 66 (level 61 items) +(19191,2,5,1,0,-4001,1), -- Grey itemlevel 69 (lvl 64 items) +(19191,3,7.5,1,0,-4103,1), -- Green itemlevel 90 +(19191,4,5,1,0,-4104,1), -- Green itemlevel 93 +(19191,5,2.5,1,0,-4105,1), -- Green itemlevel 96 +(19191,6,0.5,1,0,-4201,1), -- Blues level 61 +(19191,7,0.5,1,0,-4202,1), -- Blues level 62 +(19191,8,0.5,1,0,-4203,1), -- Blues level 63 +(19191,9,0.5,1,0,-4204,1), -- Blues level 64 +-- --------------------------------------------------- +-- Arch Mage Xintor, NPC 16977 +-- --------------------------------------------------- +(16977,21877,55,1,0,1,1), -- Netherweave Cloth +(16977,14047,15,1,0,1,3), -- Runecloth +(16977,27859,10,1,0,1,1), -- Zanger Caps +(16977,28399,5,1,0,1,1), -- Filtered Draenic Water +(16977,13446,2,1,0,1,1), -- Major Healing Potion +(16977,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Arzeth the Merciless, NPC 19354 +-- --------------------------------------------------- +(19354,21877,70,1,0,1,1), -- Netherweave Cloth +(19354,27854,7,1,0,1,1), -- Smoked Talbuk Venison +(19354,28399,3,1,0,1,1), -- Filtered Draenic Water +(19354,13446,3,1,0,1,1), -- Major Healing Potion +(19354,13444,1,1,0,1,1), -- Major Healing Potion +(19354,5760,1,1,0,1,1), -- Eternium Lockbox +(19354,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Avruu, NPC 17084 +-- --------------------------------------------------- +(17084,23580,80,1,0,1,1), -- Avruu's Orb +(17084,21877,45,1,0,1,3), -- Netherweave Cloth +(17084,17056,30,1,0,1,1), -- Light Feather +(17084,23483,-10,1,0,1,1), -- QItem: Haal'eshi Scroll +(17084,27854,5,1,0,1,1), -- Smoked Talbuk Venison +(17084,28399,3,1,0,1,1), -- Filtered Draenic Water +(17084,13446,3,1,0,1,1), -- Major Healing Potion +(17084,13444,1,1,0,1,1), -- Major Healing Potion +(17084,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Blacktalon teh Savage, NPC 17057 +-- --------------------------------------------------- +(17057,23687,-100,1,0,1,1), -- QItem: Blacktalon's Claws +(17057,24516,75,1,0,1,1), -- Damaged Rock Flayer Talon +(17057,21877,40,1,0,1,1), -- Netherweave Cloth +(17057,24517,20,1,0,1,1), -- Blood Soaked Tail +(17057,27854,3,1,0,1,1), -- Smoked Talbuk Venison +(17057,28399,2,1,0,1,1), -- Filtered Draenic Water +(17057,13446,1.5,1,0,1,1), -- Major Healing Potion +(17057,13444,0.75,1,0,1,1), -- Major Healing Potion +(17057,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Bleeding Hollow Dark Shaman, NPC 16873 +-- --------------------------------------------------- +(16873,30157,-25,1,0,1,1), -- QItem: Cursed Talisman +(16873,30425,-17,1,0,1,1), -- QItem: Bleeding Hollow Blood +(16873,28399,3,1,0,1,1), -- Filtered Draenic Water +(16873,13446,2,1,0,1,1), -- Major Healing Potion +(16873,5760,0.1,1,0,1,1), -- Eternium Lockbox +(16873,1,2,1,0,-6003,1), -- Scroll of * Reference +(16873,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bleeding Hollow Grunt, NPC 16871 +-- --------------------------------------------------- +(16871,30157,-25,1,0,1,1), -- QItem: Cursed Talisman +(16871,30425,-17,1,0,1,1), -- QItem: Bleeding Hollow Blood +(16871,28399,3,1,0,1,1), -- Filtered Draenic Water +(16871,13446,2,1,0,1,1), -- Major Healing Potion +(16871,5760,0.1,1,0,1,1), -- Eternium Lockbox +(16871,1,2,1,0,-6003,1), -- Scroll of * Reference +(16871,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bleeding Hollow Necrolyte, NPC 19422 +-- --------------------------------------------------- +(19422,30157,-25,1,0,1,1), -- QItem: Cursed Talisman +(19422,30425,-17,1,0,1,1), -- QItem: Bleeding Hollow Blood +(19422,28399,3,1,0,1,1), -- Filtered Draenic Water +(19422,13446,2,1,0,1,1), -- Major Healing Potion +(19422,5760,0.1,1,0,1,1), -- Eternium Lockbox +(19422,1,2,1,0,-6003,1), -- Scroll of * Reference +(19422,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bleeding Hollow Peon, NPC 16907 +-- --------------------------------------------------- +(16907,30157,-25,1,0,1,1), -- QItem: Cursed Talisman +(16907,30425,-17,1,0,1,1), -- QItem: Bleeding Hollow Blood +(16907,28399,3,1,0,1,1), -- Filtered Draenic Water +(16907,13446,2,1,0,1,1), -- Major Healing Potion +(16907,5760,0.1,1,0,1,1), -- Eternium Lockbox +(16907,1,2,1,0,-6003,1), -- Scroll of * Reference +(16907,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bleeding Hollow Tormentor, NPC 19424 +-- --------------------------------------------------- +(19424,30157,-25,1,0,1,1), -- QItem: Cursed Talisman +(19424,30425,-17,1,0,1,1), -- QItem: Bleeding Hollow Blood +(19424,28399,3,1,0,1,1), -- Filtered Draenic Water +(19424,13446,2,1,0,1,1), -- Major Healing Potion +(19424,5760,0.1,1,0,1,1), -- Eternium Lockbox +(19424,1,2,1,0,-6003,1), -- Scroll of * Reference +(19424,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bleeding Hollow Worg, NPC 19423 +-- --------------------------------------------------- +(19423,3299,70,1,0,1,1), -- Fractured Canine +(19423,33547,25,1,0,1,1), -- Hardened Claw +(19423,4583,1,1,0,1,1), -- Thick Furry Mane +(19423,4584,1,1,0,1,1), -- Large Trophy Paw +(19423,5759,0.2,1,0,1,1), -- Thorium Lockbox +(19423,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Blistering Oozeling, NPC 16903 +-- --------------------------------------------------- +(16903,25444,100,1,0,1,1), -- Corrosive Ichor +(16903,23339,-25,1,0,1,1), -- QItem: Arelion's Journal +(16903,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Blistering Rot, NPC 16901 +-- --------------------------------------------------- +(16901,25444,80,1,1,1,1), -- Corrosive Ichor +(16901,25446,20,1,1,1,1), -- Brittle Skull +(16901,5760,0.2,1,0,1,1), -- Eternium Lockbox +(16901,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bonechewer Evoker, NPC 19701 +-- --------------------------------------------------- +(19701,21877,55,1,0,1,1), -- Netherweave Cloth +(19701,30327,-30,1,0,1,1), -- QItem: Bonechewer Blood +(19701,14047,20,1,0,1,3), -- Runecloth +(19701,27854,7,1,0,1,1), -- Smoked Talbuk Venison +(19701,28399,3,1,0,1,1), -- Filtered Draenic Water +(19701,13446,3,1,0,1,1), -- Major Healing Potion +(19701,13444,1,1,0,1,1), -- Major Healing Potion +(19701,5759,0.2,1,0,1,1), -- Thorium Lockbox +(19701,1,2,1,0,-6003,1), -- Scroll of * Reference +(19701,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bonechewer Mutant, NPC 16876 +-- --------------------------------------------------- +(16876,21877,55,1,0,1,1), -- Netherweave Cloth +(16876,30327,-30,1,0,1,1), -- QItem: Bonechewer Blood +(16876,14047,20,1,0,1,3), -- Runecloth +(16876,27854,7,1,0,1,1), -- Smoked Talbuk Venison +(16876,28399,3,1,0,1,1), -- Filtered Draenic Water +(16876,13446,3,1,0,1,1), -- Major Healing Potion +(16876,13444,1,1,0,1,1), -- Major Healing Potion +(16876,5759,0.2,1,0,1,1), -- Thorium Lockbox +(16876,1,2,1,0,-6003,1), -- Scroll of * Reference +(16876,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bonechewer Raider, NPC 16925 +-- --------------------------------------------------- +(16925,21877,55,1,0,1,1), -- Netherweave Cloth +(16925,30327,-30,1,0,1,1), -- QItem: Bonechewer Blood +(16925,14047,20,1,0,1,3), -- Runecloth +(16925,27859,7,1,0,1,1), -- Zanger Caps +(16925,28399,3,1,0,1,1), -- Filtered Draenic Water +(16925,13446,3,1,0,1,1), -- Major Healing Potion +(16925,13444,1,1,0,1,1), -- Major Healing Potion +(16925,5759,0.2,1,0,1,1), -- Thorium Lockbox +(16925,1,2,1,0,-6003,1), -- Scroll of * Reference +(16925,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bonechewer Scavenger, NPC 18952 +-- --------------------------------------------------- +(18952,21877,55,1,0,1,1), -- Netherweave Cloth +(18952,30327,-30,1,0,1,1), -- QItem: Bonechewer Blood +(18952,14047,20,1,0,1,3), -- Runecloth +(18952,27854,7,1,0,1,1), -- Smoked Talbuk Venison +(18952,28399,3,1,0,1,1), -- Filtered Draenic Water +(18952,13446,3,1,0,1,1), -- Major Healing Potion +(18952,13444,1,1,0,1,1), -- Major Healing Potion +(18952,5759,0.2,1,0,1,1), -- Thorium Lockbox +(18952,1,2,1,0,-6003,1), -- Scroll of * Reference +(18952,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bonestripper Buzzard, NPC 16972 +-- --------------------------------------------------- +(16972,25425,80,1,0,1,1), -- Molted Feather +(16972,27671,50,1,0,1,1), -- Buzzard Meat +(16972,23239,-10,1,0,1,1), -- Plump Buzzard Wing +(16972,17056,30,1,0,1,1), -- Light Feather +(16972,25427,19,1,0,1,1), -- Beaten Talon +(16972,5759,0.2,1,0,1,1), -- Thorium Lockbox +(16972,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Bonestripper Vulture, NPC 16973 +-- --------------------------------------------------- +(16973,25425,80,1,0,1,1), -- Molted Feather +(16973,27671,50,1,0,1,1), -- Buzzard Meat +(16973,23387,-40,1,0,1,1), -- Bonestripper Tail Feather +(16973,25427,19,1,0,1,1), -- Beaten Talon +(16973,5760,0.2,1,0,1,1), -- Eternium Lockbox +(16973,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Collapsing Voidwalker, NPC 17014 +-- --------------------------------------------------- +(17014,29161,-100,1,0,1,3), -- Void Ridge Soul Shard +(17014,22577,20,1,0,1,2), -- Mote of Shadow +(17014,1,50,1,1,-6000,1), -- Generic HellfirePeninsula Loot +(17014,2,50,1,1,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Crust Burster, NPC 16844 +-- --------------------------------------------------- +(16844,25434,80,1,0,1,1), -- Fractured Carapace +(16844,25436,20,1,0,1,1), -- Twitching Leg +(16844,1,80,1,1,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Deathwhisperer, NPC 19299 +-- --------------------------------------------------- +(19299,21877,10,1,0,2,3), -- Netherweave Cloth +(19299,27854,2,1,0,1,1), -- Smoked Talbuk Venison +(19299,28399,2,1,0,1,1), -- Filtered Draenic Water +(19299,13444,1,1,0,1,1), -- Major Mana Potion +(19299,1,90,1,1,-6000,1), -- Generic HellfirePeninsula Loot +(19299,31902,0.05,1,0,1,1), -- Eight of Furies +(19299,31911,0.05,1,0,1,1), -- Eight of Lunacy +-- --------------------------------------------------- +-- Debilitated Mag'har Grunt, NPC 16847 +-- --------------------------------------------------- +(16847,23589,-50,1,0,1,1), -- QItem: Mag'har Ancestral Beads +(16847,21877,50,1,0,1,1), -- Netherweave Cloth +(16847,14047,15,1,0,1,3), -- Runecloth +(16847,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(16847,28399,3,1,0,1,1), -- Filtered Draenic Water +(16847,13446,2,1,0,1,1), -- Major Healing Potion +(16847,13444,1,1,0,1,1), -- Major Healing Potion +(16847,5759,0.15,1,0,1,1), -- Thorium Lockbox +(16847,1,2,1,0,-6003,1), -- Scroll of * Reference +(16847,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Deranged Helboar, NPC 16863 +-- --------------------------------------------------- +(16863,23270,-40,1,0,1,1), -- QItem: Tainted Helboar Meat +(16863,3403,40,1,1,1,1), -- Ivory Boar Tusk +(16863,2295,40,1,1,1,1), -- Large Boar Tusk +(16863,44754,15,1,1,1,1), -- Severed Boar Tusk +(16863,25440,1.5,1,1,1,1), -- Cracked Boar Tusk +(16863,25442,0.5,1,0,1,1), -- Mangled Snout +(16863,1,2,1,0,-6003,1), -- Scroll of * Reference +(16863,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Doomwhisperer, NPC 18981 +-- --------------------------------------------------- +(18981,28513,-50,1,0,1,1), -- QItem: Demonic Rune Stone +(18981,21877,50,1,0,1,1), -- Netherweave Cloth +(18981,14047,15,1,0,1,3), -- Runecloth +(18981,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18981,28399,3,1,0,1,1), -- Filtered Draenic Water +(18981,13446,2,1,0,1,1), -- Major Healing Potion +(18981,13444,1,1,0,1,1), -- Major Healing Potion +(18981,5759,0.15,1,0,1,1), -- Thorium Lockbox +(18981,1,2,1,0,-6003,1), -- Scroll of * Reference +(18981,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Dread Tactician, NPC 16959 +-- --------------------------------------------------- +(16959,21877,13,1,0,1,1), -- Netherweave Cloth +(16959,14047,15,1,0,1,3), -- Runecloth +(16959,27854,2,1,0,1,1), -- Smoked Talbuk Venison +(16959,27860,3,1,0,1,1), -- Purified Draenic Water +(16959,22829,0.5,1,0,1,1), -- Super Healing Potion +(16959,22832,0.25,1,0,1,1), -- Super Mana Potion +(16959,1,80,1,0,-6002,1), -- Generic HellfirePeninsula Loot2 +-- --------------------------------------------------- +-- Dreadcaller, NPC 19434 +-- --------------------------------------------------- +(19434,21877,60,1,0,1,1), -- Netherweave Cloth +(19434,14047,15,1,0,1,3), -- Runecloth +(19434,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(19434,28399,3,1,0,1,1), -- Filtered Draenic Water +(19434,13446,2,1,0,1,1), -- Major Healing Potion +(19434,13444,1,1,0,1,1), -- Major Healing Potion +(19434,5759,0.2,1,0,1,1), -- Thorium Lockbox +(19434,1,2,1,0,-6003,1), -- Scroll of * Reference +(19434,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Dreghood Brute, NPC 16938 +-- --------------------------------------------------- +(16938,21877,70,1,0,1,1), -- Netherweave Cloth +(16938,27854,11,1,0,1,1), -- Mag'har Grainbread +(16938,28399,3,1,0,1,1), -- Filtered Draenic Water +(16938,13446,2,1,0,1,1), -- Major Healing Potion +(16938,13444,1,1,0,1,1), -- Major Healing Potion +(16938,1,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Dreghood Geomancer, NPC 16937 +-- --------------------------------------------------- +(16937,21877,70,1,0,1,1), -- Netherweave Cloth +(16937,27854,11,1,0,1,1), -- Mag'har Grainbread +(16937,28399,3,1,0,1,1), -- Filtered Draenic Water +(16937,13446,2,1,0,1,1), -- Major Healing Potion +(16937,13444,1,1,0,1,1), -- Major Healing Potion +-- --------------------------------------------------- +-- Drillmaster Zurok, NPC 19312 +-- --------------------------------------------------- +(19312,21877,60,1,0,1,1), -- Netherweave Cloth +(19312,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(19312,28399,3,1,0,1,1), -- Filtered Draenic Water +(19312,13446,2,1,0,1,1), -- Major Healing Potion +(19312,13444,1,1,0,1,1), -- Major Healing Potion +(19312,5760,0.2,1,0,1,1), -- Eternium Lockbox +(19312,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Fel Canon MKI, NPC 22461 +-- --------------------------------------------------- +(22461,31944,80,1,1,1,1), -- Demonic Capacitor +(22461,31945,20,1,1,1,1), -- Shadow Circuit +-- --------------------------------------------------- +-- Fel Handler, NPC 19190 +-- --------------------------------------------------- +(19190,28513,-50,1,0,1,1), -- QItem: Demonic Rune Stone +(19190,27854,10,1,0,1,1), -- Smoked Talbuk Venison +(19190,28399,5,1,0,1,1), -- Filtered Draenic Water +(19190,13446,3,1,0,1,1), -- Major Healing Potion +(19190,13444,1.5,1,0,1,1), -- Major Mana Potion +(19190,5759,0.2,1,0,1,1), -- Thorium Lockbox +(19190,1,2,1,0,-6003,1), -- Scroll of * Reference +(19190,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Fel Reaver, NPC 18733 +-- --------------------------------------------------- +(18733,1,100,1,0,-6002,1), -- Generic HellfirePeninsula Loot2 +-- --------------------------------------------------- +-- Felblood Initiate, NPC 24918 +-- --------------------------------------------------- +(24918,21877,75,1,0,1,3), -- Netherweave Cloth +(24918,27857,8,1,0,1,1), -- Garadar Sharp +(24918,27860,5,1,0,1,1), -- Filtered Draenic Water +(24918,22829,3,1,0,1,1), -- Super Healing Potion +(24918,22832,1.5,1,0,1,1), -- Super Healing Potion +(24918,31952,0.2,1,0,1,1), -- Khorium Lockbox +(24918,31888,0.01,1,0,1,1), -- Three of Blessings +(24918,31908,0.01,1,0,1,1), -- Three of Furies +(24918,1,80,1,0,-6002,1), -- Generic HellfirePeninsula Loot2 +-- --------------------------------------------------- +-- Felguard Destroyer, NPC 18977 +-- --------------------------------------------------- +(18977,21877,40,1,0,1,3), -- Netherweave Cloth +(18977,27854,5,1,0,1,1), -- Smoked Talbuk Venison +(18977,28399,4,1,0,1,1), -- Filtered Draenic Water +(18977,13446,2,1,0,1,1), -- Major Healing Potion +(18977,13444,1,1,0,1,1), -- Major Mana Potion +(18977,5759,0.3,1,0,1,1), -- Thorium Lockbox +(18977,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Female Kaliri Hatchling, NPC 17034 +-- --------------------------------------------------- +(17034,23588,-40,1,0,1,1), -- QItem: Kaliri Feather +(17034,25425,81,1,1,1,1), -- Molted Feather +(17034,25427,19,1,1,1,1), -- Beaten Talon +(17034,5760,0.2,1,0,1,1), -- Eternium Lockbox +(17034,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Feng, NPC 19459 +-- --------------------------------------------------- +(19459,3299,70,1,0,1,1), -- Fractured Canine +(19459,33547,30,1,0,1,1), -- Hardened Claw +(19459,5759,0.3,1,0,1,1), -- Thorium Lockbox +(19459,4583,0.3,1,0,1,1), -- Thick Furry Mane +(19459,4584,0.2,1,0,1,1), -- Large Trophy Paw +(19459,1,70,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Flamewalker Imp, NPC 19136 +-- --------------------------------------------------- +(19136,21877,92,1,0,1,1), -- Netherweave Cloth +(19136,22785,0.05,1,0,1,3), -- Felweed +-- --------------------------------------------------- +-- Force-Commander Gorax, NPC 19264 +-- --------------------------------------------------- +(19264,21877,80,1,0,1,3), -- Netherweave Cloth +(19264,27854,10,1,0,1,1), -- Smoked Talbuk Venison +(19264,28399,5,1,0,1,1), -- Filtered Draenic Water +(19264,13446,3,1,0,1,1), -- Major Healing Potion +(19264,13444,1.5,1,0,1,1), -- Major Mana Potion +(19264,5760,0.3,1,0,1,1), -- Eternium Lockbox +(19264,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Forge-Camp Legionnaire, NPC 16954 +-- --------------------------------------------------- +(16954,21877,80,1,0,1,3), -- Netherweave Cloth +(16954,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(16954,28399,4,1,0,1,1), -- Filtered Draenic Water +(16954,13446,2,1,0,1,1), -- Major Healing Potion +(16954,13444,1,1,0,1,1), -- Major Mana Potion +(16954,5759,0.3,1,0,1,1), -- Thorium Lockbox +(16954,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16954,2,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Fulgorge, NPC 18678 +-- --------------------------------------------------- +(18678,31176,0,1,1,1,1), -- Rockwurm Plate Handguards +(18678,31177,0,1,1,1,1), -- Rockwurm Scale Gauntlets +(18678,31179,0,1,1,1,1), -- Rockwurm Hide Gloves +(18678,31181,0,1,1,1,1), -- Rockwurm Hide Handwraps +(18678,25434,1,1,0,1,3), -- Fractured Carapace +(18678,25436,0.2,1,0,2,4), -- Twitching Leg +-- --------------------------------------------------- +-- Gan'arg Sapper, NPC 18827 +-- --------------------------------------------------- +(18827,21877,83,1,0,1,3), -- Netherweave Cloth +(18827,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(18827,28399,4,1,0,1,1), -- Filtered Draenic Water +(18827,13446,3,1,0,1,1), -- Major Healing Potion +(18827,13444,1.5,1,0,1,1), -- Major Mana Potion +(18827,5759,0.2,1,0,1,1), -- Thorium Lockbox +(18827,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(18827,2,3,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Gan'arg Servant, NPC 16947 +-- --------------------------------------------------- +(16947,21877,83,1,0,1,3), -- Netherweave Cloth +(16947,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(16947,28399,4,1,0,1,1), -- Filtered Draenic Water +(16947,13446,3,1,0,1,1), -- Major Healing Potion +(16947,13444,1.5,1,0,1,1), -- Major Mana Potion +(16947,5759,0.1,1,0,1,1), -- Thorium Lockbox +(16947,1,95,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16947,2,3,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Gorkan Bloodfist, NPC 16845 +-- --------------------------------------------------- +(16845,21877,3,1,0,2,3), -- Netherweave Cloth +(16845,27854,1,1,0,1,1), -- Smoked Talbuk Venison +(16845,22829,0.5,1,0,1,1), -- Super Healing Potion +(16845,1,2,1,0,-4110,1), -- Level 67 Green Items (ilvl 111) +-- --------------------------------------------------- +-- Grillok "Darkeye", NPC 19457 +-- --------------------------------------------------- +(19457,31529,-100,1,0,1,1), -- QItem: Grillok's Eyepatch +(19457,21877,45,1,0,1,3), -- Netherweave Cloth +(19457,30157,-5,1,0,1,1), -- QItem: Cursed Talisman +(19457,30425,-10,1,0,1,1), -- QItem: Bleeding Hollow Blood +(19457,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(19457,28399,2,1,0,1,1), -- Filtered Draenic Water +(19457,13446,2,1,0,1,1), -- Major Healing Potion +(19457,13444,1,1,0,1,1), -- Major Mana Potion +(19457,5760,0.1,1,0,1,1), -- Eternium Lockbox +(19457,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Haal'eshi Talonguard, NPC 16967 +-- --------------------------------------------------- +(16967,21877,60,1,0,1,3), -- Netherweave Cloth +(16967,17056,42,1,0,1,1), -- Light Feather +(16967,23483,-15,1,0,1,1), -- QItem: Haal'eshi Scroll +(16967,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(16967,28399,3,1,0,1,1), -- Filtered Draenic Water +(16967,13446,2,1,0,1,1), -- Major Healing Potion +(16967,13444,1,1,0,1,1), -- Major Mana Potion +(16967,5760,0.1,1,0,1,1), -- Eternium Lockbox +(16967,1,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16967,2,3,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Haal'eshi Windwalker, NPC 16966 +-- --------------------------------------------------- +(16966,21877,60,1,0,1,3), -- Netherweave Cloth +(16966,17056,42,1,0,1,1), -- Light Feather +(16966,23483,-15,1,0,1,1), -- QItem: Haal'eshi Scroll +(16966,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(16966,28399,3,1,0,1,1), -- Filtered Draenic Water +(16966,13446,2,1,0,1,1), -- Major Healing Potion +(16966,13444,1,1,0,1,1), -- Major Mana Potion +(16966,5760,0.1,1,0,1,1), -- Eternium Lockbox +(16966,1,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16966,2,3,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Hand of Kargath, NPC 22374 +-- --------------------------------------------------- +(22374,31706,-100,1,0,1,1), -- QItem: The Head of the Hand of Kargath +(22374,21877,40,1,0,1,3), -- Netherweave Cloth +(22374,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(22374,28399,2,1,0,1,1), -- Filtered Draenic Water +(22374,13446,1,1,0,1,1), -- Major Healing Potion +(22374,13444,0.5,1,0,1,1), -- Major Mana Potion +(22374,5760,0.1,1,0,1,1), -- Eternium Lockbox +(22374,1,80,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Heckling Fel Sprite, NPC 18978 +-- --------------------------------------------------- +(18978,21877,95,1,0,1,1), -- Netherweave Cloth +-- --------------------------------------------------- +-- Hulking Helboar, NPC 16880 +-- --------------------------------------------------- +(16880,23336,-30,1,0,1,1), -- QItem: Helboar Blood Sample +(16880,23270,-5,1,0,1,1), -- QItem: Tainted Hellboar Meat +(16880,3403,82,1,1,1,1), -- Ivory Boar Tusk +(16880,25440,1.5,1,1,1,1), -- Cracked Boar Tusk +(16880,25442,0.3,1,2,1,1), -- Mangled Snout +(16880,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Illidari Taskmaster, NPC 17058 +-- --------------------------------------------------- +(17058,29113,-50,1,0,1,1), -- QItem: Demonic Essence +(17058,21877,60,1,0,1,3), -- Netherweave Cloth +(17058,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(17058,28399,3,1,0,1,1), -- Filtered Draenic Water +(17058,13446,2,1,0,1,1), -- Major Healing Potion +(17058,13444,1,1,0,1,1), -- Major Mana Potion +(17058,5760,0.2,1,0,1,1), -- Eternium Lockbox +(17058,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +(17058,2,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Incandescent Fel Spark, NPC 22323 +-- --------------------------------------------------- +(22323,24508,80,1,1,1,1), -- Elemental Fragment +(22323,24511,20,1,1,1,1), -- Primordial Essence +(22323,22574,35,1,0,1,2), -- Mote of Fire +(22323,1,90,1,0,-6002,1), -- Generic HellfirePeninsula Loot2 +-- --------------------------------------------------- +-- Infernal Warbringer, NPC 19261 +-- --------------------------------------------------- +(19261,1,70,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Kaliri Matriarch, NPC 17035 +-- --------------------------------------------------- +(17035,23588,-27,1,0,1,1), -- QItem: Kaliri Feather +(17035,25425,81,1,1,1,1), -- Molted Feather +(17035,25427,19,1,1,1,1), -- Beaten Talon +(17035,5760,0.07,1,0,1,1), -- Eternium Lockbox +(17035,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Kaliri Swooper, NPC 17053 +-- --------------------------------------------------- +(17053,23588,-25,1,0,1,1), -- QItem: Kaliri Feather +(17053,25425,81,1,1,1,1), -- Molted Feather +(17053,25427,19,1,1,1,1), -- Beaten Talon +(17053,5760,0.05,1,0,1,1), -- Eternium Lockbox +(17053,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Lieutenant Commander Thalvos, NPC 16978 +-- --------------------------------------------------- +(16978,28562,-100,1,0,1,1), -- QItem: Unyielding Battle Horn +(16978,21877,55,1,0,1,1), -- Netherweave Cloth +(16978,27859,5,1,0,1,1), -- Zanger Caps +(16978,28399,2.5,1,0,1,1), -- Filtered Draenic Water +(16978,13446,2,1,0,1,1), -- Major Healing Potion +(16978,13444,2,1,0,1,1), -- Major Mana Potion +(16978,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Mag'har Grunt, NPC 16846 +-- --------------------------------------------------- +(16846,23589,-50,1,0,1,1), -- QItem: Mag'har Ancestral Beads +(16846,21877,60,1,0,1,1), -- Netherweave Cloth +(16846,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(16846,28399,3,1,0,1,1), -- Filtered Draenic Water +(16846,13446,2,1,0,1,1), -- Major Healing Potion +(16846,13444,1,1,0,1,1), -- Major Healing Potion +(16846,5759,0.15,1,0,1,1), -- Eternium Lockbox +(16846,1,2,1,0,-6003,1), -- Scroll of * Reference +(16846,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Mag'har Hunter, NPC 16912 +-- --------------------------------------------------- +(16912,21877,60,1,0,1,1), -- Netherweave Cloth +(16912,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(16912,28399,3,1,0,1,1), -- Filtered Draenic Water +(16912,13446,2,1,0,1,1), -- Major Healing Potion +(16912,13444,1,1,0,1,1), -- Major Healing Potion +(16912,5759,0.15,1,0,1,1), -- Eternium Lockbox +(16912,1,2,1,0,-6003,1), -- Scroll of * Reference +(16912,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Mag'har Watcher, NPC 16911 +-- --------------------------------------------------- +(16911,21877,60,1,0,1,1), -- Netherweave Cloth +(16911,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(16911,28399,3,1,0,1,1), -- Filtered Draenic Water +(16911,13446,2,1,0,1,1), -- Major Healing Potion +(16911,13444,1,1,0,1,1), -- Major Healing Potion +(16911,5759,0.15,1,0,1,1), -- Eternium Lockbox +(16911,1,2,1,0,-6003,1), -- Scroll of * Reference +(16911,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Maiden of Pain, NPC 19408 +-- --------------------------------------------------- +(19408,14047,15,1,0,1,3), -- Runecloth +(19408,27854,9,1,0,1,1), -- Smoked Talbuk Venison +(19408,28399,4,1,0,1,1), -- Filtered Draenic Water +(19408,13446,3,1,0,1,1), -- Major Healing Potion +(19408,13444,1.5,1,0,1,1), -- Major Healing Potion +(19408,5760,0.15,1,0,1,1), -- Eternium Lockbox +(19408,1,2,1,0,-6003,1), -- Scroll of * Reference +(19408,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Male Kaliri Hatchling, NPC 17039 +-- --------------------------------------------------- +(17039,23588,-25,1,0,1,1), -- QItem: Kaliri Feather +(17039,25425,81,1,1,1,1), -- Molted Feather +(17039,25427,19,1,1,1,1), -- Beaten Talon +(17039,5760,0.2,1,0,1,1), -- Eternium Lockbox +(17039,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Marauding Crust Burster, NPC 16857 +-- --------------------------------------------------- +(16857,23338,7,1,0,1,1), -- Eroded Leather Case +(16857,25434,80,1,0,1,1), -- Fractured Carapace +(16857,25436,20,1,0,1,1), -- Twitching Leg +(16857,5759,0.1,1,0,1,1), -- Thorium Lockbox +(16857,1,80,1,1,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Mekthorg the Wild, NPC 18677 +-- --------------------------------------------------- +(18677,31168,0,1,1,1,1), -- Demon-Forged Chestguard +(18677,31170,0,1,1,1,1), -- Demon-Forged Hauberk +(18677,31172,0,1,1,1,1), -- Demon-Cured Tunic +(18677,31174,0,1,1,1,1), -- Demonweave Raiment +(18677,21877,40,1,0,1,3), -- Netherweave Cloth +(18677,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(18677,28399,2,1,0,1,3), -- Netherweave Cloth +-- --------------------------------------------------- +-- Mistress of Doom, NPC 19192 +-- --------------------------------------------------- +(19192,21877,80,1,0,1,3), -- Netherweave Cloth +(19192,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(19192,28399,5,1,0,1,1), -- Filtered Draenic Water +(19192,13446,3,1,0,1,1), -- Major Healing Potion +(19192,13444,1.5,1,0,1,1), -- Major Healing Potion +(19192,5759,0.15,1,0,1,1), -- Eternium Lockbox +(19192,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Mo'arg Forgefiend, NPC 16946 +-- --------------------------------------------------- +(16946,21877,80,1,0,1,3), -- Netherweave Cloth +(16946,27854,9,1,0,1,1), -- Smoked Talbuk Venison +(16946,28399,4,1,0,1,1), -- Filtered Draenic Water +(16946,13446,3,1,0,1,1), -- Major Healing Potion +(16946,13444,1.5,1,0,1,1), -- Major Healing Potion +(16946,5760,0.15,1,0,1,1), -- Eternium Lockbox +(16946,1,2,1,0,-6003,1), -- Scroll of * Reference +(16946,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Netherhound, NPC 16950 +-- --------------------------------------------------- +(16950,28513,-60,1,0,1,1), -- QItem: Demonic Rune Stone +(16950,3299,43,1,0,1,1), -- Fractured Canine +(16950,33547,17,1,0,1,1), -- Hardened Claw +(16950,4583,0.5,1,0,1,1), -- Thick Furry Mane +(16950,4584,0.2,1,0,1,1), -- Large Trophy Paw +(16950,5759,0.05,1,0,1,1), -- Thorium Lockbox +(16950,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Quillfang Ravager, NPC 16934 +-- --------------------------------------------------- +(16934,27674,50,1,0,1,1), -- Ravager Flesh +(16934,23965,81,1,1,1,1), -- Chipped Ravager Claw +(16934,23979,19,1,1,1,1), -- Chipped Ravager Carapace +(16934,1,85,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Quillfang Skitterer, NPC 19189 +-- --------------------------------------------------- +(19189,27674,50,1,0,1,1), -- Ravager Flesh +(19189,23217,-4,1,0,1,1), -- QItem: Ravager Egg +(19189,23965,81,1,1,1,1), -- Chipped Ravager Claw +(19189,23979,19,1,1,1,1), -- Chipped Ravager Carapace +(19189,1,85,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Raging Colossus, NPC 19188 +-- --------------------------------------------------- +(19188,29579,80,1,0,2,4), -- Crystalized Stone Chips +(19188,29476,19,1,0,1,1), -- Crimson Crystal Shard +(19188,29578,19,1,0,2,4), -- Crystalized Stone +(19188,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Razorfang Hatchling, NPC 16932 +-- --------------------------------------------------- +(16932,23217,-1,1,0,1,1), -- QItem: Ravager Egg +(16932,27674,50,1,0,1,1), -- Ravager Flesh +(16932,23976,0,1,1,1,1), -- Gnarled Ravager Carapace +(16932,23977,0,1,1,1,1), -- Gnarled Ravager Fang +(16932,23978,0,1,1,1,1), -- Gnarled Ravager Claw +(16932,1,85,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Razorfang Ravager, NPC 16933 +-- --------------------------------------------------- +(16933,23965,81,1,1,1,1), -- Chipped Ravager Claw +(16933,23979,19,1,1,1,1), -- Chipped Ravager Carapace +(16933,27674,50,1,0,1,1), -- Ravager Flesh +(16933,23217,-20,1,0,1,1), -- QItem: Ravager Egg +(16933,1,85,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Razorsaw, NPC 20798 +-- --------------------------------------------------- +(20798,29590,55,1,0,1,1), -- Burning Legion Missive +(20798,29586,-100,1,0,1,1), -- QItem: Head of Forgefiend Razorsaw +(20798,21877,50,1,0,1,3), -- Netherweave Cloth +(20798,27854,5,1,0,1,1), -- Smoked Talbuk Venison +(20798,28399,2.5,1,0,1,1), -- Filtered Draenic Water +(20798,13446,1.5,1,0,1,1), -- Major Healing Potion +(20798,13444,0.75,1,0,1,1), -- Major Mana Potion +(20798,5760,0.15,1,0,1,1), -- Eternium Lockbox +(20798,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Ripp, NPC 19458 +-- --------------------------------------------------- +(19458,3299,70,1,0,1,1), -- Fractured Canine +(19458,33547,25,1,0,1,1), -- Hardened Claw +(19458,4583,1,1,0,1,1), -- Thick Furry Mane +(19458,4584,1,1,0,1,1), -- Large Trophy Paw +(19458,5759,0.2,1,0,1,1), -- Thorium Lockbox +(19458,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Rogue Voidwalker, NPC 16974 +-- --------------------------------------------------- +(16974,23218,-85,1,0,1,1), -- Condensed Voidwalker Essence +(16974,22577,20,1,0,1,1), -- Mote of Shadow +(16974,1,90,1,0,-6000,1), -- Generic HellfirePeninsule Loot +-- --------------------------------------------------- +-- Shattered Hand Acolyte, NPC 19415 +-- --------------------------------------------------- +(19415,21877,70,1,0,1,3), -- Netherweave Cloth +(19415,27854,9,1,0,1,1), -- Smoked Talbuk Venison +(19415,28399,4,1,0,1,1), -- Filtered Draenic Water +(19415,13446,2,1,0,1,1), -- Major Healing Potion +(19415,13444,1,1,0,1,1), -- Major Healing Potion +(19415,5760,0.2,1,0,1,1), -- Eternium Lockbox +(19415,1,2,1,0,-6003,1), -- Scroll of * Reference +(19415,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Berserker, NPC 16878 +-- --------------------------------------------------- +(16878,21877,82,1,0,1,3), -- Netherweave Cloth +(16878,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(16878,28399,4,1,0,1,1), -- Filtered Draenic Water +(16878,13446,3,1,0,1,1), -- Major Healing Potion +(16878,13444,1.5,1,0,1,1), -- Major Healing Potion +(16878,5760,0.2,1,0,1,1), -- Eternium Lockbox +(16878,1,2,1,0,-6003,1), -- Scroll of * Reference +(16878,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Captain, NPC 16870 +-- --------------------------------------------------- +(16870,21877,80,1,0,1,3), -- Netherweave Cloth +(16870,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(16870,28399,4,1,0,1,1), -- Filtered Draenic Water +(16870,13446,2,1,0,1,1), -- Major Healing Potion +(16870,13444,1,1,0,1,1), -- Major Healing Potion +(16870,5760,0.2,1,0,1,1), -- Eternium Lockbox +(16870,1,2,1,0,-6003,1), -- Scroll of * Reference +(16870,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Grenadier, NPC 19295 +-- --------------------------------------------------- +(19295,21877,85,1,0,1,3), -- Netherweave Cloth +(19295,27854,9,1,0,1,1), -- Smoked Talbuk Venison +(19295,28399,4,1,0,1,1), -- Filtered Draenic Water +(19295,13446,2,1,0,1,1), -- Major Healing Potion +(19295,13444,1,1,0,1,1), -- Major Healing Potion +(19295,1,75,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Grunt, NPC 16867 +-- --------------------------------------------------- +(16867,21877,80,1,0,1,3), -- Netherweave Cloth +(16867,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(16867,28399,4,1,0,1,1), -- Filtered Draenic Water +(16867,13446,2,1,0,1,1), -- Major Healing Potion +(16867,13444,1,1,0,1,1), -- Major Healing Potion +(16867,5760,0.18,1,0,1,1), -- Eternium Lockbox +(16867,1,2,1,0,-6003,1), -- Scroll of * Reference +(16867,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Guard, NPC 19414 +-- --------------------------------------------------- +(19414,21877,80,1,0,1,3), -- Netherweave Cloth +(19414,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(19414,28399,4,1,0,1,1), -- Filtered Draenic Water +(19414,13446,3,1,0,1,1), -- Major Healing Potion +(19414,13444,1.5,1,0,1,1), -- Major Healing Potion +(19414,5760,0.18,1,0,1,1), -- Eternium Lockbox +(19414,1,2,1,0,-6003,1), -- Scroll of * Reference +(19414,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Mage, NPC 19413 +-- --------------------------------------------------- +(19413,21877,60,1,0,1,3), -- Netherweave Cloth +(19413,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(19413,28399,3,1,0,1,1), -- Filtered Draenic Water +(19413,13446,2,1,0,1,1), -- Major Healing Potion +(19413,13444,1,1,0,1,1), -- Major Healing Potion +(19413,1,2,1,0,-6003,1), -- Scroll of * Reference +(19413,2,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Neophyte, NPC 19410 +-- --------------------------------------------------- +(19410,21877,80,1,0,1,3), -- Netherweave Cloth +(19410,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(19410,28399,4,1,0,1,1), -- Filtered Draenic Water +(19410,13446,2,1,0,1,1), -- Major Healing Potion +(19410,13444,1,1,0,1,1), -- Major Healing Potion +(19410,5760,0.18,1,0,1,1), -- Eternium Lockbox +(19410,1,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Shattered Hand Warlock, NPC 19411 +-- --------------------------------------------------- +(19411,21877,80,1,0,1,3), -- Netherweave Cloth +(19411,27854,9,1,0,1,1), -- Smoked Talbuk Venison +(19411,28399,4,1,0,1,1), -- Filtered Draenic Water +(19411,13446,2,1,0,1,1), -- Major Healing Potion +(19411,13444,1,1,0,1,1), -- Major Healing Potion +(19411,5760,0.18,1,0,1,1), -- Eternium Lockbox +(19411,1,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Sister of Grief, NPC 16960 +-- --------------------------------------------------- +(16960,21877,80,1,0,1,3), -- Netherweave Cloth +(16960,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(16960,28399,4,1,0,1,1), -- Filtered Draenic Water +(16960,13446,2,1,0,1,1), -- Major Healing Potion +(16960,13444,1,1,0,1,1), -- Major Healing Potion +(16960,1,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Starving Helboar, NPC 16879 +-- --------------------------------------------------- +(16879,23270,-5,1,0,1,1), -- QItem: Tainted Helboar Meat +(16879,2295,74,1,1,1,1), -- Large Boar Tusk +(16879,44754,24,1,1,1,1), -- Severed Boar Tusk +(16879,25440,2,1,1,1,1), -- Cracked Boar Tusk +(16879,25442,0.5,1,0,1,1), -- Mangled Snout +(16879,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Stonescythe Alpha, NPC 16929 +-- --------------------------------------------------- +(16929,24516,81,1,1,1,1), -- Damaged Rock Flayer Talon +(16929,24517,19,1,1,1,1), -- Blood Soaked Tail +(16929,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(16929,28399,2,1,0,1,1), -- Filtered Draenic Water +(16929,13446,1.2,1,0,1,1), -- Major Healing Potion +(16929,13444,0.6,1,0,1,1), -- Major Healing Potion +(16929,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16929,2,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Stonescythe Ambusher, NPC 16928 +-- --------------------------------------------------- +(16928,24516,81,1,1,1,1), -- Damaged Rock Flayer Talon +(16928,24517,19,1,1,1,1), -- Blood Soaked Tail +(16928,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Stonescythe Whelp, NPC 16927 +-- --------------------------------------------------- +(16927,24516,81,1,1,1,1), -- Damaged Rock Flayer Talon +(16927,24517,19,1,1,1,1), -- Blood Soaked Tail +(16927,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(16927,28399,2,1,0,1,1), -- Filtered Draenic Water +(16927,13446,1.2,1,0,1,1), -- Major Healing Potion +(16927,13444,0.6,1,0,1,1), -- Major Healing Potion +(16927,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16927,2,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Subjugator Shi'aziv, NPC 19282 +-- --------------------------------------------------- +(19282,28513,-25,1,0,1,1), -- QItem: Demonic Rune Stone +(19282,27854,3,1,0,1,1), -- Smoked Talbuk Venison +(19282,28399,1.5,1,0,1,1), -- Filtered Draenic Water +(19282,13446,1,1,0,1,1), -- Major Healing Potion +(19282,13444,0.5,1,0,1,1), -- Major Healing Potion +(19282,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Subjugator Yalqiz, NPC 19335 +-- --------------------------------------------------- +(19335,27854,1.2,1,0,1,1), -- Smoked Talbuk Venison +(19335,28399,0.6,1,0,1,1), -- Filtered Draenic Water +(19335,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Tagar Spinebreaker, NPC 19443 +-- --------------------------------------------------- +(19443,21877,33,1,0,1,3), -- Netherweave Cloth +(19443,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(19443,28399,2,1,0,1,1), -- Filtered Draenic Water +(19443,13446,1,1,0,1,1), -- Major Healing Potion +(19443,13444,0.5,1,0,1,1), -- Major Healing Potion +(19443,1,70,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Terrorfiend, NPC 16951 +-- --------------------------------------------------- +(16951,21877,70,1,0,1,3), -- Netherweave Cloth +(16951,23269,-25,1,0,1,1), -- Felblood Sample +(16951,27854,7,1,0,1,1), -- Smoked Talbuk Venison +(16951,28399,3.5,1,0,1,1), -- Filtered Draenic Water +(16951,13446,2,1,0,1,1), -- Major Healing Potion +(16951,13444,1,1,0,1,1), -- Major Healing Potion +(16951,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot +(16951,2,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Thornfang Ravager, NPC 19349 +-- --------------------------------------------------- +(19349,27674,50,1,0,1,1), -- Ravager Flesh +(19349,23965,81,1,1,1,1), -- Chipped Ravager Claw +(19349,23979,19,1,1,1,1), -- Chipped Ravager Carapace +(19349,5760,0.1,1,0,1,1), -- Eternium Lockbox +(19349,1,85,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Thornfang Venomspitter, NPC 19350 +-- --------------------------------------------------- +(19350,23965,81,1,1,1,1), -- Chipped Ravager Claw +(19350,23979,19,1,1,1,1), -- Chipped Ravager Carapace +(19350,1,85,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 +-- --------------------------------------------------- +-- Tunneler, NPC 16968 +-- --------------------------------------------------- +(16968,23338,5,1,0,1,1), -- Eroded Leather Case +(16968,25434,81,1,1,1,1), -- Fractured Carapace +(16968,25436,19,1,1,1,1), -- Twitching Leg +(16968,5760,0.1,1,0,1,1), -- Eternium Lockbox +(16968,1,80,1,1,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Twilight Cryomancer, NPC 26222 +-- --------------------------------------------------- +(26222,14047,85,1,0,1,2), -- Runecloth +(26222,8952,9,1,0,1,2), -- Roasted Quail +(26222,8766,4.5,1,0,1,2), -- Morning Glory Dew +(26222,13446,6,1,0,1,2), -- Major Healing Potion +(26222,13444,3,1,0,1,2), -- Major Mana Potion +(26222,1,10,1,0,-1052,1), -- Level 52 Grey reference +(26222,2,10,1,0,-1053,1), -- Level 53 Grey reference +-- --------------------------------------------------- +-- Twilight Frostblade, NPC 26223 +-- --------------------------------------------------- +(26223,14047,85,1,0,1,2), -- Runecloth +(26223,8952,9,1,0,1,2), -- Roasted Quail +(26223,8766,4.5,1,0,1,2), -- Morning Glory Dew +(26223,13446,6,1,0,1,2), -- Major Healing Potion +(26223,13444,3,1,0,1,2), -- Major Mana Potion +(26223,1,10,1,0,-1052,1), -- Level 52 Grey reference +(26223,2,10,1,0,-1053,1), -- Level 53 Grey reference +-- --------------------------------------------------- +-- Uncontrolled Voidwalker, NPC 16975 +-- --------------------------------------------------- +(16975,23218,-80,1,0,1,1), -- Condensed Voidwalker Essence +(16975,22577,20,1,0,1,1), -- Mote of Shadow +(16975,1,90,1,0,-6000,1), -- Generic HellfirePeninsule Loot +-- --------------------------------------------------- +-- Unstable Voidwalker, NPC 20145 +-- --------------------------------------------------- +(20145,29051,-100,1,0,1,1), -- QItem: Warp Nether +-- --------------------------------------------------- +-- Unyielding Footman, NPC 16904 +-- --------------------------------------------------- +(16904,21877,60,1,0,1,1), -- Netherweave Cloth +(16904,14047,20,1,0,1,3), -- Runecloth +(16904,27859,8,1,0,1,1), -- Zanger Caps +(16904,28399,4,1,0,1,1), -- Filtered Draenic Water +(16904,13446,2,1,0,1,1), -- Major Healing Potion +(16904,13444,1,1,0,1,1), -- Major Mana Potion +(16904,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Unyielding Knight, NPC 16906 +-- --------------------------------------------------- +(16906,28552,15,1,0,1,1), -- A Mysterious Tome +(16906,21877,60,1,0,1,1), -- Netherweave Cloth +(16906,14047,20,1,0,1,3), -- Runecloth +(16906,27859,8,1,0,1,1), -- Zanger Caps +(16906,28399,4,1,0,1,1), -- Filtered Draenic Water +(16906,13446,2,1,0,1,1), -- Major Healing Potion +(16906,13444,1,1,0,1,1), -- Major Mana Potion +(16906,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16906,2,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Unyielding Sorcerer, NPC 16905 +-- --------------------------------------------------- +(16905,21877,60,1,0,1,1), -- Netherweave Cloth +(16905,14047,20,1,0,1,3), -- Runecloth +(16905,27859,8,1,0,1,1), -- Zanger Caps +(16905,28399,4,1,0,1,1), -- Filtered Draenic Water +(16905,13446,2,1,0,1,1), -- Major Healing Potion +(16905,13444,1,1,0,1,1), -- Major Mana Potion +(16905,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +(16905,2,2,1,0,-6003,1), -- Scroll of * Reference +-- --------------------------------------------------- +-- Vacillating Voidcaller, NPC 19527 +-- --------------------------------------------------- +(19527,29161,-100,1,0,1,3), -- Void Ridge Soul Shard +(19527,22577,20,1,0,1,2), -- Mote of Shadow +(19527,1,50,1,1,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Void Baron Galaxis, NPC 16939 +-- --------------------------------------------------- +(16939,29162,-100,1,0,1,1), -- Galaxis Soul Shard +-- --------------------------------------------------- +-- Vorakem Doomspeaker, NPC 18679 +-- --------------------------------------------------- +(18679,31182,0,1,1,1,1), -- Legion Helm +(18679,31183,0,1,1,1,1), -- Legion Coif +(18679,31184,0,1,1,1,1), -- Legion Headguard +(18679,31185,0,1,1,1,1), -- Legion Crown +(18679,21877,40,1,0,1,3), -- Netherweave Cloth +(18679,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(18679,28399,2.5,1,0,1,1), -- Filtered Draenic Water +(18679,13446,1,1,0,1,1), -- Major Healing Potion +(18679,13444,0.5,1,0,1,1), -- Major Healing Potion +-- --------------------------------------------------- +-- Warboss Nekrogg, NPC 19263 +-- --------------------------------------------------- +(19263,21877,90,1,0,1,1), -- Netherweave Cloth +(19263,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Warbringer Arix'Amal, NPC 19298 +-- --------------------------------------------------- +(19298,29795,-85,1,0,1,1), -- QItem: Burning Legion Gate Key +(19298,29588,50,1,0,1,1), -- Burning Legion Gate Key +(19298,21877,46,1,0,1,3), -- Netherweave Cloth +(19298,27854,5,1,0,1,1), -- Smoked Talbuk Venison +(19298,28399,2.5,1,0,1,1), -- Filtered Draenic Water +(19298,13446,1.4,1,0,1,1), -- Major Healing Potion +(19298,13444,0.7,1,0,1,1), -- Major Healing Potion +(19298,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Warlord Morkh, NPC 16964 +-- --------------------------------------------------- +(16964,30158,-100,1,0,1,1), -- QItem: Morkh's Shattered Armor +(16964,21877,35,1,0,1,1), -- Netherweave Cloth +(16964,14047,10,1,0,1,3), -- Runecloth +(16964,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(16964,28399,2,1,0,1,1), -- Filtered Draenic Water +(16964,13446,1,1,0,1,1), -- Major Healing Potion +(16964,13444,0.5,1,0,1,1), -- Major Healing Potion +(16964,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Worg Master Kruush, NPC 19442 +-- --------------------------------------------------- +(19442,31374,-100,1,0,1,1), -- QItem: Worg Master's Head +(19442,30425,-25,1,0,1,1), -- QItem: Bleeding Hollow Blood +(19442,30157,-10,1,0,1,1), -- QItem: Cursed Talisman +(19442,21877,45,1,0,1,3), -- Netherweave Cloth +(19442,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(19442,28399,2,1,0,1,1), -- Filtered Draenic Water +(19442,13446,1,1,0,1,1), -- Major Healing Potion +(19442,13444,0.5,1,0,1,1), -- Major Mana Potion +(19442,5759,0.1,1,0,1,1), -- Thorium Lockbox +(19442,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot +-- --------------------------------------------------- +-- Wrath Herald, NPC 24919 +-- --------------------------------------------------- +(24919,34259,-100,1,0,1,1), -- Demonic Blood +(24919,21877,45,1,0,1,3), -- Netherweave Cloth +(24919,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(24919,27860,2,1,0,1,1), -- Purified Draenic Water +(24919,22829,1.6,1,0,1,1), -- Super Healing Potion +(24919,22832,0.8,1,0,1,1), -- Super Mana Potion +(24919,1,100,1,0,-6002,1), -- Generic HellfirePeninsula Loot2 +-- --------------------------------------------------- +-- Wrathguard, NPC 18975 +-- --------------------------------------------------- +(18975,28513,-85,1,0,1,1), -- QItem: Demonic Rune Stone +(18975,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(18975,28399,4,1,0,1,1), -- Filtered Draenic Water +(18975,13446,3,1,0,1,1), -- Major Healing Potion +(18975,13444,1.5,1,0,1,1), -- Major Healing Potion +(18975,5759,0.15,1,0,1,1), -- Thorium Lockbox +(18975,1,2,1,0,-6003,1), -- Scroll of * Reference +(18975,2,90,1,0,-6000,1); -- Generic HellfirePeninsula Loot + +UPDATE `creature_template` SET `lootid`=`entry` WHERE `entry` IN (26222,26223); +DELETE FROM `reference_loot_template` WHERE `entry`=34081; diff --git a/sql/updates/world/2012_06_02_03_world_creature_loot_template_zm.sql b/sql/updates/world/2012_06_02_03_world_creature_loot_template_zm.sql new file mode 100644 index 00000000000..e739f81407b --- /dev/null +++ b/sql/updates/world/2012_06_02_03_world_creature_loot_template_zm.sql @@ -0,0 +1,902 @@ +SET @ZM1:=6010; +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +DELETE FROM `reference_loot_template` WHERE `entry`=@ZM1; +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +(@ZM1,1,30,1,0,-4000,1), -- Grey Items level 61 (ilvl 66) +(@ZM1,2,30,1,0,-4001,1), -- Grey Items level 64 (ilvl 69) +(@ZM1,3,2,1,0,-4103,1), -- Green Items level 60 (ilvl 90) +(@ZM1,4,2,1,0,-4104,1), -- Green Items level 61 (ilvl 93) +(@ZM1,5,2,1,0,-4105,1), -- Green Items level 62 (ilvl 96) +(@ZM1,6,2,1,0,-4106,1), -- Green Items level 63 (ilvl 99) +(@ZM1,7,0.5,1,0,-4203,1), -- Blue items level 63 (ilvl 94) +(@ZM1,8,0.5,1,0,-4204,1), -- Blue items level 64 (ilvl 97) +(@ZM1,9,0.5,1,0,-4205,1), -- Blue items level 65 (ilvl 97) +(@ZM1,5760,0.5,1,0,1,1); -- Eternium Lockbox +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +DELETE FROM `creature_loot_template` WHERE `entry` IN (18285,18119,18120,18117,20443,20444,18118,18121,19732,18283,20792,18088,20088,20090,18089,20089,20196,18127,18682,20197,18281,20293,20295,20294,18159,20442,18992,19174,18681,18116,18115,19733,20079,18087,19946,19947,18086,18122,18134,18214,20198,20270,18113,18114,19734,18129,19730,19729,18080,20290,20291,18282,20445,20292,18137,18136,18135,18130,18131,18133,20283,19706,18680,18213,18286,18212,18160,20324,20279,20280,18046,18044,18128,18280,18154,19519,18125,18340,20477,18138,18077,18079,20115,18132,19402,18124,18123,20387); +INSERT INTO `creature_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- "Count" Ungula, NPC 18285 +-- --------------------------------------------------- +(18285,25459,-100,1,0,1,1), -- QItem: "Count" Ungula's Mandible +(18285,25434,80,1,1,1,1), -- Fractured Carapace +(18285,25436,20,1,1,1,1), -- Twitsching Leg +(18285,24493,-10,1,0,1,1), -- QItem: Marshfang Slicer Blade +(18285,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Ango'rosh Brute, NPC 18119 +-- --------------------------------------------------- +(18119,21877,10,1,0,1,3), -- Netherweave Cloth +(18119,27854,1.2,1,0,1,1), -- Smoked Talbuk Venison +(18119,28399,0.6,1,0,1,1), -- Filtered Draenic Water +(18119,1,80,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Ango'rosh Mauler, NPC 18120 +-- --------------------------------------------------- +(18120,24240,-50,1,0,1,1), -- QItem: Box of Mushrooms +(18120,21877,70,1,0,1,3), -- Netherweave Cloth +(18120,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18120,28399,3,1,0,1,1), -- Filtered Draenic Water +(18120,13446,2,1,0,1,1), -- Major Healing Potion +(18120,13444,1,1,0,1,1), -- Major Mana Potion +(18120,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(18120,2,85,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Ango'rosh Ogre, NPC 18117 +-- --------------------------------------------------- +(18117,24238,-50,1,0,1,1), -- QItem: Mushroom Sample +(18117,21877,62,1,0,1,3), -- Netherweave Cloth +(18117,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18117,28399,3,1,0,1,1), -- Filtered Draenic Water +(18117,13446,2,1,0,1,1), -- Major Healing Potion +(18117,13444,1,1,0,1,1), -- Major Mana Potion +(18117,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(18117,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Ango'rosh Sentry, NPC 20443 +-- --------------------------------------------------- +(20443,24238,-50,1,0,1,1), -- QItem: Mushroom Sample +(20443,21877,44,1,0,1,3), -- Netherweave Cloth +(20443,27854,4,1,0,1,1), -- Smoked Talbuk Venison +(20443,28399,2,1,0,1,1), -- Filtered Draenic Water +(20443,13446,1.5,1,0,1,1), -- Major Healing Potion +(20443,13444,0.75,1,0,1,1), -- Major Mana Potion +(20443,1,80,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Ango'rosh Shadowmage, NPC 20444 +-- --------------------------------------------------- +(20444,24240,-40,1,0,1,1), -- QItem: Box of Mushrooms +(20444,21877,70,1,0,1,3), -- Netherweave Cloth +(20444,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(20444,28399,3,1,0,1,1), -- Filtered Draenic Water +(20444,13446,2,1,0,1,1), -- Major Healing Potion +(20444,13444,1,1,0,1,1), -- Major Mana Potion +(20444,2,85,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Ango'rosh Shaman, NPC 18118 +-- --------------------------------------------------- +(18118,24238,-45,1,0,1,1), -- QItem: Mushroom Sample +(18118,21877,60,1,0,1,3), -- Netherweave Cloth +(18118,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18118,28399,3,1,0,1,1), -- Filtered Draenic Water +(18118,13446,2,1,0,1,1), -- Major Healing Potion +(18118,13444,1,1,0,1,1), -- Major Mana Potion +(18118,2,2,1,0,-6003,1), -- Scroll of * VI Reference +(18118,1,80,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Ango'rosh Souleater, NPC 18121 +-- --------------------------------------------------- +(18121,24240,-35,1,0,1,1), -- QItem: Box of Mushrooms +(18121,21877,70,1,0,1,3), -- Netherweave Cloth +(18121,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18121,28399,3,1,0,1,1), -- Filtered Draenic Water +(18121,13446,2,1,0,1,1), -- Major Healing Potion +(18121,13444,1,1,0,1,1), -- Major Mana Potion +(18121,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(18121,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Ango'rosh Warlock, NPC 19732 +-- --------------------------------------------------- +(19732,21877,82,1,0,1,3), -- Netherweave Cloth +(19732,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(19732,28399,4,1,0,1,1), -- Filtered Draenic Water +(19732,13446,3,1,0,1,1), -- Major Healing Potion +(19732,13444,1.5,1,0,1,1), -- Major Mana Potion +(19732,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Blacksting, NPC 18283 +-- --------------------------------------------------- +(18283,25448,-100,1,0,1,1), -- QItem: Blacksting's Stinger +(18283,25434,80,1,1,1,1), -- Fractured Carapace +(18283,25436,18,1,1,1,1), -- Twitching Leg +(18283,24372,-10,1,0,1,1), -- QItem: Diaphanous Wing +(18283,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Bloodscale Elemental, NPC 20792 +-- --------------------------------------------------- +(20792,24507,81,1,1,1,1), -- Elemental Shard +(20792,24510,19,1,1,1,1), -- Primordial Core +(20792,22578,19,1,0,1,2), -- Mote of Water +(20792,7080,1,1,0,1,2), -- Essence of Water +(20792,1,95,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Bloodscale Enchantress, NPC 18088 +-- --------------------------------------------------- +(18088,24401,35,1,0,1,1), -- Unidentified Plant Parts +(18088,17057,33,1,0,1,1), -- Shiny Fish Scales +(18088,17058,30,1,0,1,1), -- Fish Oil +(18088,24476,19,1,0,1,1), -- Jaggal Clam +(18088,24280,-10,1,0,1,1), -- QItem: Naga Claws +(18088,24330,-1,1,0,1,1), -- QItem: Drain Schematics +(18088,27858,4,1,0,1,3), -- Sunspring Carp +(18088,28399,2,1,0,1,1), -- Filtered Draenic Water +(18088,13446,1.5,1,0,1,1), -- Major Healing Potion +(18088,13444,0.75,1,0,1,1), -- Major Mana Potion +(18088,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(18088,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Bloodscale Overseer, NPC 20088 +-- --------------------------------------------------- +(20088,24280,-80,1,0,1,1), -- QItem: Naga Claws +(20088,24401,30,1,0,1,1), -- Unidentified Plant Parts +(20088,17057,25,1,0,1,1), -- Shiny Fish Scales +(20088,17058,20,1,0,1,1), -- Fish Oil +(20088,24476,15,1,0,1,1), -- Jaggal Clam +(20088,24330,-2,1,0,1,1), -- QItem: Drain Schematics +(20088,27858,4,1,0,1,3), -- Sunspring Carp +(20088,28399,2,1,0,1,1), -- Filtered Draenic Water +(20088,13446,1,1,0,1,1), -- Major Healing Potion +(20088,13444,0.5,1,0,1,1), -- Major Mana Potion +(20088,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(20088,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Bloodscale Sentry, NPC 20090 +-- --------------------------------------------------- +(20090,24507,68,1,1,1,1), -- Elemental Shard +(20090,24510,17,1,1,1,1), -- Primordial Core +(20090,22578,15,1,0,1,2), -- Mote of Water +(20090,7080,1,1,0,1,2), -- Essence of Water +(20090,1,95,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Bloodscale Slavedriver, NPC 18089 +-- --------------------------------------------------- +(18089,24401,35,1,0,1,1), -- Unidentified Plant Parts +(18089,17057,33,1,0,1,1), -- Shiny Fish Scales +(18089,17058,30,1,0,1,1), -- Fish Oil +(18089,24476,19,1,0,1,1), -- Jaggal Clam +(18089,24280,-5,1,0,1,1), -- QItem: Naga Claws +(18089,24330,-0.5,1,0,1,1), -- QItem: Drain Schematics +(18089,27858,4,1,0,1,3), -- Sunspring Carp +(18089,28399,2,1,0,1,1), -- Filtered Draenic Water +(18089,13446,1.5,1,0,1,1), -- Major Healing Potion +(18089,13444,0.75,1,0,1,1), -- Major Mana Potion +(18089,1,1,1,0,-6003,1), -- Scroll of * VI Reference +(18089,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Bloodscale Wavecaller, NPC 20089 +-- --------------------------------------------------- +(20089,24280,-80,1,0,1,1), -- QItem: Naga Claws +(20089,24401,30,1,0,1,1), -- Unidentified Plant Parts +(20089,17057,25,1,0,1,1), -- Shiny Fish Scales +(20089,17058,20,1,0,1,1), -- Fish Oil +(20089,24476,15,1,0,1,1), -- Jaggal Clam +(20089,24330,-2,1,0,1,1), -- QItem: Drain Schematics +(20089,27858,4,1,0,1,3), -- Sunspring Carp +(20089,28399,2,1,0,1,1), -- Filtered Draenic Water +(20089,13446,1,1,0,1,1), -- Major Healing Potion +(20089,13444,0.5,1,0,1,1), -- Major Mana Potion +(20089,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(20089,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Bloodthirsty Marshfang, NPC 20196 +-- --------------------------------------------------- +(20196,28058,81,1,1,1,1), -- Shredded Wyrm Wing +(20196,28059,19,1,1,1,1), -- Iridescent Eye +(20196,22578,19,1,0,1,1), -- Mote of Water +(20196,7080,1,1,0,1,1), -- Essence of Water +(20196,1,95,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Bog Lord, NPC 18127 +-- --------------------------------------------------- +(18127,25450,82,1,0,1,1), -- Creeping Moss +(18127,25452,18,1,1,1,1), -- Blighted Fungus +(18127,24291,-35,1,0,1,1), -- QItem: Bog Lord Tendril +(18127,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18127,22575,19,1,0,1,1), -- Mote of Life +(18127,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Bog Lurker, NPC 18682 +-- --------------------------------------------------- +(18682,31247,0,1,1,1,1), -- Bog Pauldrons +(18682,31248,0,1,1,1,1), -- Bog Epaulets +(18682,31249,0,1,1,1,1), -- Bog Spaulders +(18682,31250,0,1,1,1,1), -- Bog Mantle +(18682,25456,80,1,2,1,1), -- Glowing Spores +(18682,25454,20,1,2,1,1), -- Luminescent Globe +-- --------------------------------------------------- +-- Bogflare Needler, NPC 20197 +-- --------------------------------------------------- +(20197,25434,81,1,1,1,1), -- Fractured Carapace +(20197,25436,19,1,1,1,1), -- Twitching Leg +(20197,24372,-2,1,0,1,1), -- QItem: Diaphanous Wing +(20197,29960,0.05,1,0,1,1), -- Captured Firefly +(20197,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Boglash, NPC 18281 +-- --------------------------------------------------- +(18281,25434,80,1,1,1,1), -- Fractured Carapace +(18281,25436,18,1,1,1,1), -- Twitching Leg +(18281,27676,50,1,0,1,1), -- Strange Spores +(18281,24449,-35,1,0,1,1), -- QItem: Fertile Spores +(18281,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Bogstrok Clacker, NPC 20293 +-- --------------------------------------------------- +(20293,24401,40,1,0,1,1), -- Unidentified Plant Parts +(20293,17057,33,1,0,1,1), -- Shiny Fish Scales +(20293,17058,30,1,0,1,1), -- Fish Oil +(20293,24476,20,1,0,1,1), -- Jaggal Clam +(20293,27858,4,1,0,1,3), -- Sunspring Carp +(20293,28399,2,1,0,1,1), -- Filtered Draenic Water +(20293,13446,1.5,1,0,1,1), -- Major Healing Potion +(20293,13444,0.75,1,0,1,1), -- Major Mana Potion +(20293,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Bogstrok Crusher, NPC 20295 +-- --------------------------------------------------- +(20295,24401,40,1,0,1,1), -- Unidentified Plant Parts +(20295,17057,33,1,0,1,1), -- Shiny Fish Scales +(20295,17058,30,1,0,1,1), -- Fish Oil +(20295,24476,20,1,0,1,1), -- Jaggal Clam +(20295,27858,4,1,0,1,3), -- Sunspring Carp +(20295,28399,2,1,0,1,1), -- Filtered Draenic Water +(20295,13446,1.5,1,0,1,1), -- Major Healing Potion +(20295,13444,0.75,1,0,1,1), -- Major Mana Potion +(20295,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Bogstrok Razorclaw, NPC 20294 +-- --------------------------------------------------- +(20294,24401,40,1,0,1,1), -- Unidentified Plant Parts +(20294,17057,33,1,0,1,1), -- Shiny Fish Scales +(20294,17058,30,1,0,1,1), -- Fish Oil +(20294,24476,20,1,0,1,1), -- Jaggal Clam +(20294,27858,4,1,0,1,3), -- Sunspring Carp +(20294,28399,2,1,0,1,1), -- Filtered Draenic Water +(20294,13446,1.5,1,0,1,1), -- Major Healing Potion +(20294,13444,0.75,1,0,1,1), -- Major Mana Potion +(20294,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Boss Grog'ak, NPC 18159 +-- --------------------------------------------------- +(18159,24472,-100,1,0,1,1), -- QItem: Boss Grog'ak's Head +(18159,24238,-100,1,0,1,1), -- QItem: Mushroom Sample +(18159,21877,45,1,0,1,3), -- Netherweave Cloth +(18159,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18159,28399,3,1,0,1,1), -- Filtered Draenic Water +(18159,13446,2,1,0,1,1), -- Major Healing Potion +(18159,13444,1,1,0,1,1), -- Major Mana Potion +(18159,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Captain Bo'kar, NPC 20442 +-- --------------------------------------------------- +(20442,24240,-50,1,0,1,1), -- QItem: Box of Mushrooms +(20442,21877,80,1,0,1,3), -- Netherweave Cloth +(20442,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(20442,28399,3,1,0,1,1), -- Filtered Draenic Water +(20442,13446,2,1,0,1,1), -- Major Healing Potion +(20442,13444,1,1,0,1,1), -- Major Mana Potion +(20442,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Captain Krosh, NPC 18992 +-- --------------------------------------------------- +(18992,24240,-5,1,0,1,1), -- QItem: Box of Mushrooms +(18992,21877,25,1,0,1,3), -- Netherweave Cloth +(18992,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18992,28399,3,1,0,1,1), -- Filtered Draenic Water +(18992,13446,2,1,0,1,1), -- Major Healing Potion +(18992,13444,1,1,0,1,1), -- Major Mana Potion +(18992,1,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Chieftain Mummaki, NPC 19174 +-- --------------------------------------------------- +(19174,27943,-100,1,0,1,1), -- QItem: Chieftain Mummaki's Totem +(19174,21877,25,1,0,1,3), -- Netherweave Cloth +(19174,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(19174,28399,3,1,0,1,1), -- Filtered Draenic Water +(19174,13446,2,1,0,1,1), -- Major Healing Potion +(19174,13444,1,1,0,1,1), -- Major Mana Potion +(19174,1,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Coilfang Emissary, NPC 18681 +-- --------------------------------------------------- +(18681,31242,0,1,1,1,1), -- Nagascale Legplates +(18681,31243,0,1,1,1,1), -- Nagascale Legguard +(18681,31244,0,1,1,1,1), -- Nagahide Pants +(18681,31245,0,1,1,1,1), -- Nagahide Leggings +(18681,17057,40,1,0,1,2), -- Shiny Fish Scales +(18681,21877,40,1,0,1,3), -- Netherweave Cloth +(18681,17058,25,1,0,1,1), -- Fish Oil +-- --------------------------------------------------- +-- Daggerfen Assassin, NPC 18116 +-- --------------------------------------------------- +(18116,21877,75,1,0,1,3), -- Netherweave Cloth +(18116,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(18116,28399,4,1,0,1,1), -- Filtered Draenic Water +(18116,13446,2,1,0,1,1), -- Major Healing Potion +(18116,13444,1,1,0,1,1), -- Major Mana Potion +(18116,1,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Daggerfen Muckdweller, NPC 18115 +-- --------------------------------------------------- +(18115,21877,75,1,0,1,3), -- Netherweave Cloth +(18115,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(18115,28399,4,1,0,1,1), -- Filtered Draenic Water +(18115,13446,2,1,0,1,1), -- Major Healing Potion +(18115,13444,1,1,0,1,1), -- Major Mana Potion +(18115,1,80,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Daggerfen Servant, NPC 19733 +-- --------------------------------------------------- +(19733,17057,33,1,0,1,1), -- Shiny Fish Scales +(19733,17058,30,1,0,1,1), -- Fish Oil +(19733,24476,20,1,0,1,1), -- Jaggal Clam +(19733,27858,4,1,0,1,3), -- Sunspring Carp +(19733,28399,2,1,0,1,1), -- Filtered Draenic Water +(19733,13446,1.5,1,0,1,1), -- Major Healing Potion +(19733,13444,0.75,1,0,1,1), -- Major Mana Potion +(19733,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Darkcrest Sentry, NPC 20079 +-- --------------------------------------------------- +(20079,24507,70,1,1,1,1), -- Elemental Shard +(20079,24510,15,1,1,1,1), -- Primordial Core +(20079,22578,15,1,0,1,2), -- Mote of Water +(20079,7080,1,1,0,1,2), -- Essence of Water +(20079,1,95,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Darkcrest Siren, NPC 18087 +-- --------------------------------------------------- +(18087,24280,-80,1,0,1,1), -- QItem: Naga Claws +(18087,24401,30,1,0,1,1), -- Unidentified Plant Parts +(18087,17057,25,1,0,1,1), -- Shiny Fish Scales +(18087,17058,20,1,0,1,1), -- Fish Oil +(18087,24476,15,1,0,1,1), -- Jaggal Clam +(18087,27858,3,1,0,1,3), -- Sunspring Carp +(18087,28399,1.5,1,0,1,1), -- Filtered Draenic Water +(18087,13446,1,1,0,1,1), -- Major Healing Potion +(18087,13444,0.5,1,0,1,1), -- Major Mana Potion +(18087,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Darkcrest Slaver, NPC 19946 +-- --------------------------------------------------- +(19946,24280,-95,1,0,1,1), -- QItem: Naga Claws +(19946,24401,30,1,0,1,1), -- Unidentified Plant Parts +(19946,17057,25,1,0,1,1), -- Shiny Fish Scales +(19946,17058,20,1,0,1,1), -- Fish Oil +(19946,24476,15,1,0,1,1), -- Jaggal Clam +(19946,27858,3,1,0,1,3), -- Sunspring Carp +(19946,28399,1.5,1,0,1,1), -- Filtered Draenic Water +(19946,13446,1,1,0,1,1), -- Major Healing Potion +(19946,13444,0.5,1,0,1,1), -- Major Mana Potion +(19946,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(19946,2,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Darkcrest Sorceress, NPC 19947 +-- --------------------------------------------------- +(19947,24280,-95,1,0,1,1), -- QItem: Naga Claws +(19947,24401,30,1,0,1,1), -- Unidentified Plant Parts +(19947,17057,25,1,0,1,1), -- Shiny Fish Scales +(19947,17058,20,1,0,1,1), -- Fish Oil +(19947,24476,15,1,0,1,1), -- Jaggal Clam +(19947,27858,3,1,0,1,3), -- Sunspring Carp +(19947,28399,1.5,1,0,1,1), -- Filtered Draenic Water +(19947,13446,1,1,0,1,1), -- Major Healing Potion +(19947,13444,0.5,1,0,1,1), -- Major Mana Potion +(19947,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(19947,2,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Darkcrest Taskmaster, NPC 18086 +-- --------------------------------------------------- +(18086,24280,-80,1,0,1,1), -- QItem: Naga Claws +(18086,24401,30,1,0,1,1), -- Unidentified Plant Parts +(18086,17057,25,1,0,1,1), -- Shiny Fish Scales +(18086,17058,20,1,0,1,1), -- Fish Oil +(18086,24476,15,1,0,1,1), -- Jaggal Clam +(18086,27858,3,1,0,1,3), -- Sunspring Carp +(18086,28399,1.5,1,0,1,1), -- Filtered Draenic Water +(18086,13446,1,1,0,1,1), -- Major Healing Potion +(18086,13444,0.5,1,0,1,1), -- Major Mana Potion +(18086,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(18086,2,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Dreghood Drudge, NPC 18122 +-- --------------------------------------------------- +(18122,21877,60,1,0,1,3), -- Netherweave Cloth +(18122,24401,35,1,0,1,1), -- Unidentified Plant Parts +(18122,27854,3,1,0,1,1), -- Smoked Talbuk Venison +(18122,28399,1.5,1,0,1,1), -- Filtered Draenic Water +(18122,13446,1,1,0,1,1), -- Major Healing Potion +(18122,13444,0.5,1,0,1,1), -- Major Mana Potion +(18122,2,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Fen Strider, NPC 18134 +-- --------------------------------------------------- +(18134,25434,81,1,1,1,1), -- Fractured Carapace +(18134,25436,19,1,1,1,1), -- Twitching Leg +(18134,27676,50,1,0,1,1), -- Strange Spores +(18134,24449,-35,1,0,1,1), -- QItem: Fertile Spores +(18134,24427,20,1,0,1,1), -- QItem: Fen Strider Tentacle +(18134,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Fenclaw Thrasher, NPC 18214 +-- --------------------------------------------------- +(18214,25429,81,1,1,1,1), -- Grime-Encrusted Scale +(18214,25431,19,1,1,1,1), -- Ripped Fin +(18214,24486,-50,1,0,1,1), -- QItem: Fenclaw Hide +(18214,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18214,24476,15,1,0,1,1), -- Jaggal Clam +(18214,24375,-15,1,0,1,1), -- QItem: Thick Hydra Scale +(18214,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Fenglow Stinger, NPC 20198 +-- --------------------------------------------------- +(20198,25434,80,1,1,1,1), -- Fractured Carapace +(20198,25436,20,1,1,1,1), -- Twitching Leg +(20198,24372,-10,1,0,1,1), -- QItem: Diaphanous Wing +(20198,24401,25,1,0,1,1), -- Unidentified Plant Parts +(20198,24485,-30,1,0,1,1), -- QItem: Marshlight Bleeder Venom +(20198,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Feralfen Druid, NPC 20270 +-- --------------------------------------------------- +(20270,24497,-25,1,0,1,1), -- QItem: Feralfen Protection Totem +(20270,21877,60,1,0,1,3), -- Netherweave Cloth +(20270,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(20270,28399,3,1,0,1,1), -- Filtered Draenic Water +(20270,13446,2,1,0,1,1), -- Major Healing Potion +(20270,13444,1,1,0,1,1), -- Major Mana Potion +(20270,1,80,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +(20270,2,2,1,0,-6003,1), -- Scroll of * VI Reference +-- --------------------------------------------------- +-- Feralfen Hunter, NPC 18113 +-- --------------------------------------------------- +(18113,24497,-10,1,0,1,1), -- QItem: Feralfen Protection Totem +(18113,21877,60,1,0,1,3), -- Netherweave Cloth +(18113,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18113,28399,3,1,0,1,1), -- Filtered Draenic Water +(18113,13446,2,1,0,1,1), -- Major Healing Potion +(18113,13444,1,1,0,1,1), -- Major Mana Potion +(18113,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +(18113,2,2,1,0,-6003,1), -- Scroll of * VI Reference +-- --------------------------------------------------- +-- Feralfen Mystic, NPC 18114 +-- --------------------------------------------------- +(18114,24497,-40,1,0,1,1), -- QItem: Feralfen Protection Totem +(18114,21877,60,1,0,1,3), -- Netherweave Cloth +(18114,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18114,28399,3,1,0,1,1), -- Filtered Draenic Water +(18114,13446,2,1,0,1,1), -- Major Healing Potion +(18114,13444,1,1,0,1,1), -- Major Mana Potion +(18114,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +(18114,2,2,1,0,-6003,1), -- Scroll of * VI Reference +-- --------------------------------------------------- +-- Fungal Giant, NPC 19734 +-- --------------------------------------------------- +(19734,25450,81,1,0,1,1), -- Creeping Moss +(19734,25452,19,1,1,1,1), -- Blighted Fungus +(19734,24401,25,1,0,1,1), -- Unidentified Plant Parts +(19734,22575,19,1,0,1,3), -- Mote of Life +(19734,12803,1,1,0,1,1), -- Living Essence +(19734,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Greater Sporebat, NPC 18129 +-- --------------------------------------------------- +(18129,25456,81,1,1,1,1), -- Glowing Spores +(18129,25454,19,1,1,1,1), -- Luminescent Globe +(18129,27676,50,1,0,1,1), -- Strange Spores +(18129,24449,-35,1,0,1,1), -- QItem: Fertile Spores +(18129,24401,26,1,0,1,1), -- Unidentified Plant Parts +(18129,1,95,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Ironspine Gazer, NPC 19730 +-- --------------------------------------------------- +(19730,1701,80,1,1,1,1), -- Curved Basilisk Claw +(19730,11389,17,1,1,1,1), -- Shimmering Basilisk Sking +(19730,29553,2,1,1,1,1), -- Basilisk Guts +(19730,29554,1,1,1,1,1), -- Encrusted Basilisk Skin +(19730,27677,45,1,0,1,1), -- Chunk O'Basilisk +(19730,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Ironspine Threshalisk, NPC 19729 +-- --------------------------------------------------- +(19729,1701,80,1,1,1,1), -- Curved Basilisk Claw +(19729,11389,17,1,1,1,1), -- Shimmering Basilisk Sking +(19729,29553,2,1,1,1,1), -- Basilisk Guts +(19729,29554,1,1,1,1,1), -- Encrusted Basilisk Skin +(19729,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Kataru, NPC 18080 +-- --------------------------------------------------- +(18080,21877,60,1,0,1,3), -- Netherweave Cloth +(18080,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18080,28399,3,1,0,1,1), -- Filtered Draenic Water +(18080,13446,2,1,0,1,1), -- Major Healing Potion +(18080,13444,1,1,0,1,1), -- Major Mana Potion +(18080,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Lagoon Eel, NPC 20290 +-- --------------------------------------------------- +(20290,28058,81,1,1,1,1), -- Shredded Wyrm Wing +(20290,28059,19,1,1,1,1), -- Iridescent Eye +(20290,22578,19,1,0,1,1), -- Mote of Water +(20290,7080,1,1,0,1,1), -- Essence of Water +(20290,1,85,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Lagoon Walker, NPC 20291 +-- --------------------------------------------------- +(20291,25450,82,1,0,1,1), -- Creeping Moss +(20291,25452,18,1,1,1,1), -- Blighted Fungus +(20291,24401,25,1,0,1,1), -- Unidentified Plant Parts +(20291,22575,19,1,0,1,2), -- Mote of Life +(20291,12803,1.5,1,0,1,2), -- Living Essence +(20291,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Lord Klaq, NPC 18282 +-- --------------------------------------------------- +(18282,24401,30,1,0,1,1), -- Unidentified Plant Parts +(18282,17057,30,1,0,1,1), -- Shiny Fish Scales +(18282,17058,25,1,0,1,1), -- Fish Oil +(18282,24476,15,1,0,1,1), -- Jaggal Clam +(18282,27858,4,1,0,1,3), -- Sunspring Carp +(18282,28399,2,1,0,1,1), -- Filtered Draenic Water +(18282,13446,1,1,0,1,1), -- Major Healing Potion +(18282,13444,0.5,1,0,1,1), -- Major Mana Potion +(18282,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Mal'druk the Soulrender, NPC 20445 +-- --------------------------------------------------- +(20445,21877,72,1,0,1,3), -- Netherweave Cloth +(20445,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(20445,28399,8,1,0,1,1), -- Filtered Draenic Water +(20445,13446,2,1,0,1,1), -- Major Healing Potion +(20445,13444,1,1,0,1,1), -- Major Mana Potion +(20445,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Marsh Baron Brok, NPC 20292 +-- --------------------------------------------------- +(20292,25450,80,1,0,1,1), -- Creeping Moss +(20292,25452,20,1,1,1,1), -- Blighted Fungus +(20292,24401,25,1,0,1,1), -- Unidentified Plant Parts +(20292,22575,19,1,0,1,2), -- Mote of Life +(20292,12803,1,1,0,1,2), -- Living Essence +(20292,1,100,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Marsh Dredger, NPC 18137 +-- --------------------------------------------------- +(18137,24401,35,1,0,1,1), -- Unidentified Plant Parts +(18137,17057,33,1,0,1,1), -- Shiny Fish Scales +(18137,17058,30,1,0,1,1), -- Fish Oil +(18137,24476,20,1,0,1,1), -- Jaggal Clam +(18137,27858,4,1,0,1,3), -- Sunspring Carp +(18137,28399,2,1,0,1,1), -- Filtered Draenic Water +(18137,13446,1,1,0,1,1), -- Major Healing Potion +(18137,13444,0.5,1,0,1,1), -- Major Mana Potion +(18137,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +(18137,2,2,1,0,-6003,1), -- Scroll of * VI Reference +-- --------------------------------------------------- +-- Marsh Lurker, NPC 18136 +-- --------------------------------------------------- +(18136,24401,35,1,0,1,1), -- Unidentified Plant Parts +(18136,17057,33,1,0,1,1), -- Shiny Fish Scales +(18136,17058,30,1,0,1,1), -- Fish Oil +(18136,24476,20,1,0,1,1), -- Jaggal Clam +(18136,27858,4,1,0,1,3), -- Sunspring Carp +(18136,28399,2,1,0,1,1), -- Filtered Draenic Water +(18136,13446,1,1,0,1,1), -- Major Healing Potion +(18136,13444,0.5,1,0,1,1), -- Major Mana Potion +(18136,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +(18136,2,2,1,0,-6003,1), -- Scroll of * VI Reference +-- --------------------------------------------------- +-- Marsh Walker, NPC 18135 +-- --------------------------------------------------- +(18135,25434,81,1,1,1,1), -- Fractured Carapace +(18135,25436,19,1,1,1,1), -- Twitching Leg +(18135,27676,50,1,0,1,1), -- Strange Spores +(18135,24449,-35,1,0,1,1), -- QItem: Fertile Spores +(18135,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Marshfang Ripper, NPC 18130 +-- --------------------------------------------------- +(18130,25434,81,1,1,1,1), -- Fractured Carapace +(18130,25436,19,1,1,1,1), -- Twitching Leg +(18130,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18130,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Marshfang Slicer, NPC 18131 +-- --------------------------------------------------- +(18131,24493,-100,1,0,1,1), -- QItem: Marshfang Slicer Blade +(18131,25434,81,1,1,1,1), -- Fractured Carapace +(18131,25436,19,1,1,1,1), -- Twitching Leg +(18131,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18131,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Marshlight Bleeder, NPC 18133 +-- --------------------------------------------------- +(18133,25434,80,1,1,1,1), -- Fractured Carapace +(18133,25436,20,1,1,1,1), -- Twitching Leg +(18133,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18133,24372,-10,1,0,1,1), -- QItem: Diaphanous Wing +(18133,24485,-30,1,0,1,1), -- QItem: Marshlight Bleeder Venom +(18133,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Marshrock Stomper, NPC 20283 +-- --------------------------------------------------- +(20283,1701,80,1,1,1,1), -- Curved Basilisk Claw +(20283,11389,17,1,1,1,1), -- Shimmering Basilisk Sking +(20283,29553,2,1,1,1,1), -- Basilisk Guts +(20283,29554,1,1,1,1,1), -- Encrusted Basilisk Skin +(20283,27677,45,1,0,1,1), -- Chunk O'Basilisk +(20283,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Marshrock Threshalisk, NPC 19706 +-- --------------------------------------------------- +(19706,1701,81,1,1,1,1), -- Curved Basilisk Claw +(19706,11389,18,1,1,1,1), -- Shimmering Basilisk Sking +(19706,29553,1,1,1,1,1), -- Basilisk Guts +(19706,27677,50,1,0,1,1), -- Chunk O'Basilisk +(19706,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Marticar, NPC 18680 +-- --------------------------------------------------- +(18680,31254,100,1,0,1,1), -- Striderhide Cloak +(18680,25456,80,1,1,2,4), -- Glowing Spores +(18680,25454,20,1,1,2,4), -- Luminescent Glove +-- --------------------------------------------------- +-- Mire Hydra, NPC 18213 +-- --------------------------------------------------- +(18213,25429,81,1,1,1,1), -- Grime-Encrusted Scale +(18213,25431,19,1,1,1,1), -- Ripped Fin +(18213,24375,-100,1,0,1,1), -- QItem: Thick Hydra Scale +(18213,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18213,24476,15,1,0,1,1), -- Jaggal Clam +(18213,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Mragesh, NPC 18286 +-- --------------------------------------------------- +(18286,25429,81,1,1,1,1), -- Grime-Encrusted Scale +(18286,25431,19,1,1,1,1), -- Ripped Fin +(18286,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18286,24476,15,1,0,1,1), -- Jaggal Clam +(18286,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Mudfin Frenzy, NPC 18212 +-- --------------------------------------------------- +(18212,25429,80,1,1,1,1), -- Grime-Encrusted Scale +(18212,25431,20,1,1,1,1), -- Ripped Fin +(18212,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18212,1,10,1,0,-4000,1), -- Grey lvl 61 Item +(18212,2,10,1,0,-4001,1), -- Grey lvl 64 Item +-- --------------------------------------------------- +-- Overlord Gorefist, NPC 18160 +-- --------------------------------------------------- +(18160,24240,-20,1,0,1,1), -- QItem: Box of Mushrooms +(18160,21877,55,1,0,1,3), -- Netherweave Cloth +(18160,27854,6,1,0,1,1), -- Smoked Talbuk Venison +(18160,28399,3,1,0,1,1), -- Filtered Draenic Water +(18160,13446,2,1,0,1,1), -- Major Healing Potion +(18160,13444,1,1,0,1,1), -- Major Mana Potion +(18160,2,85,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Parched Hydra, NPC 20324 +-- --------------------------------------------------- +(20324,25429,81,1,1,1,1), -- Grime-Encrusted Scale +(20324,25431,19,1,1,1,1), -- Ripped Fin +(20324,24401,25,1,0,1,1), -- Unidentified Plant Parts +(20324,24375,-100,1,0,1,1), -- QItem: Thick Hydra Scale +(20324,24476,15,1,0,1,1), -- Jaggal Clam +(20324,29480,-15,1,0,1,1), -- QItem: Parched Hydra Sample +(20324,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Ragestone Threshalisk, NPC 20279 +-- --------------------------------------------------- +(20279,1701,80,1,1,1,1), -- Curved Basilisk Claw +(20279,11389,17,1,1,1,1), -- Shimmering Basilisk Sking +(20279,29553,2,1,1,1,1), -- Basilisk Guts +(20279,29554,1,1,1,1,1), -- Encrusted Basilisk Skin +(20279,27677,45,1,0,1,1), -- Chunk O'Basilisk +(20279,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Ragestone Trampler, NPC 20280 +-- --------------------------------------------------- +(20280,1701,80,1,1,1,1), -- Curved Basilisk Claw +(20280,11389,17,1,1,1,1), -- Shimmering Basilisk Sking +(20280,29553,2,1,1,1,1), -- Basilisk Guts +(20280,29554,1,1,1,1,1), -- Encrusted Basilisk Skin +(20280,27677,45,1,0,1,1), -- Chunk O'Basilisk +(20280,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Rajah Haghazed, NPC 18046 +-- --------------------------------------------------- +(18046,24280,-65,1,0,1,1), -- QItem: Naga Claws +(18046,24476,26,1,0,1,1), -- Jaggal Clam +(18046,17057,25,1,0,1,1), -- Shiny Fish Scales +(18046,17058,20,1,0,1,1), -- Fish Oil +(18046,27858,4,1,0,1,3), -- Sunspring Carp +(18046,28399,2,1,0,1,1), -- Filtered Draenic Water +(18046,13446,1,1,0,1,1), -- Major Healing Potion +(18046,13444,0.5,1,0,1,1), -- Major Mana Potion +(18046,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Rajis Fyashe, NPC 18044 +-- --------------------------------------------------- +(18044,24280,-65,1,0,1,1), -- QItem: Naga Claws +(18044,24476,26,1,0,1,1), -- Jaggal Clam +(18044,17057,25,1,0,1,1), -- Shiny Fish Scales +(18044,17058,20,1,0,1,1), -- Fish Oil +(18044,27858,4,1,0,1,3), -- Sunspring Carp +(18044,28399,2,1,0,1,1), -- Filtered Draenic Water +(18044,13446,1,1,0,1,1), -- Major Healing Potion +(18044,13444,0.5,1,0,1,1), -- Major Mana Potion +(18044,2,90,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Sporebat, NPC 18128 +-- --------------------------------------------------- +(18128,25456,80,1,1,1,1), -- Glowing Spores +(18128,25454,20,1,1,1,1), -- Luminescent Globe +(18128,27676,50,1,0,1,1), -- Strange Spores +(18128,24449,-35,1,0,1,1), -- QItem: Fertile Spores +(18128,24401,26,1,0,1,1), -- Unidentified Plant Parts +(18128,24426,-20,1,0,1,1), -- QItem: Sporebat Eye +(18128,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Sporewing, NPC 18280 +-- --------------------------------------------------- +(18280,25456,80,1,1,1,1), -- Glowing Spores +(18280,25454,20,1,1,1,1), -- Luminescent Globe +(18280,27676,50,1,0,1,1), -- Strange Spores +(18280,24449,-35,1,0,1,1), -- QItem: Fertile Spores +(18280,24401,26,1,0,1,1), -- Unidentified Plant Parts +(18280,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Ssslith, NPC 18154 +-- --------------------------------------------------- +(18154,24476,30,1,0,1,1), -- Jaggal Clam +(18154,17057,25,1,0,1,1), -- Shiny Fish Scales +(18154,17058,20,1,0,1,1), -- Fish Oil +(18154,27858,4,1,0,1,3), -- Sunspring Carp +(18154,28399,2,1,0,1,1), -- Filtered Draenic Water +(18154,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Starving Bog Lord, NPC 19519 +-- --------------------------------------------------- +(19519,25450,80,1,0,1,1), -- Creeping Moss +(19519,25452,20,1,1,1,1), -- Blighted Fungus +(19519,24291,-20,1,0,1,1), -- QItem: Bog Lord Tendril +(19519,24401,25,1,0,1,1), -- Unidentified Plant Parts +(19519,22575,19,1,0,1,1), -- Mote of Life +(19519,12803,1,1,0,1,1), -- Living Essence +(19519,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Starving Fungal Giant, NPC 18125 +-- --------------------------------------------------- +(18125,25450,80,1,0,1,1), -- Creeping Moss +(18125,25452,20,1,1,1,1), -- Blighted Fungus +(18125,24291,-20,1,0,1,1), -- QItem: Bog Lord Tendril +(18125,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18125,22575,19,1,0,1,1), -- Mote of Life +(18125,12803,1,1,0,1,1), -- Living Essence +(18125,1,100,1,0,-6010,1), -- Generic Zangermarsh Loot +-- --------------------------------------------------- +-- Steam Pump Overseer, NPC 18340 +-- --------------------------------------------------- +(18340,24280,-45,1,0,1,1), -- QItem: Naga Claws +(18340,24401,35,1,0,1,1), -- Unidentified Plant Parts +(18340,17057,30,1,0,1,1), -- Shiny Fish Scales +(18340,17058,25,1,0,1,1), -- Fish Oil +(18340,24476,15,1,0,1,1), -- Jaggal Clam +(18340,24330,-40,1,0,1,1), -- QItem: Drain Schematics +(18340,27858,4,1,0,1,3), -- Sunspring Carp +(18340,28399,2,1,0,1,1), -- Filtered Draenic Water +(18340,13446,1.5,1,0,1,1), -- Major Healing Potion +(18340,13444,0.75,1,0,1,1), -- Major Mana Potion +(18340,1,2,1,0,-6003,1), -- Scroll of * VI Reference +(18340,2,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Terrorclaw, NPC 20477 +-- --------------------------------------------------- +(20477,17057,34,1,0,1,1), -- Shiny Fish Scales +(20477,24401,34,1,0,1,1), -- Unidentified Plant Parts +(20477,17058,30,1,0,1,1), -- Fish Oil +(20477,24476,20,1,0,1,1), -- Jaggal Clam +(20477,27858,4,1,0,1,3), -- Sunspring Carp +(20477,28399,2,1,0,1,1), -- Filtered Draenic Water +(20477,13446,1.5,1,0,1,1), -- Major Healing Potion +(20477,13444,0.75,1,0,1,1), -- Major Mana Potion +(20477,1,90,1,0,-6001,1), -- Generic HellfirePeninsula Loot1 (YES FOR ZM) +-- --------------------------------------------------- +-- Umbrafen Eel, NPC 18138 +-- --------------------------------------------------- +(18138,25429,80,1,1,1,1), -- Grime-Encrusted Scale +(18138,25431,20,1,1,1,1), -- Ripped Fin +(18138,24374,-40,1,0,1,1), -- QItem: Eel Filet +(18138,1,90,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Umbrafen Oracle, NPC 18077 +-- --------------------------------------------------- +(18077,21877,80,1,0,1,3), -- Netherweave Cloth +(18077,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(18077,28399,4,1,0,1,1), -- Filtered Draenic Water +(18077,13446,2,1,0,1,1), -- Major Healing Potion +(18077,13444,1,1,0,1,1), -- Major Mana Potion +(18077,2,2,1,0,-6003,1), -- Scroll of * VI Reference +(18077,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Umbrafen Seer, NPC 18079 +-- --------------------------------------------------- +(18079,21877,80,1,0,1,3), -- Netherweave Cloth +(18079,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(18079,28399,4,1,0,1,1), -- Filtered Draenic Water +(18079,13446,2,1,0,1,1), -- Major Healing Potion +(18079,13444,1,1,0,1,1), -- Major Mana Potion +(18079,2,2,1,0,-6003,1), -- Scroll of * VI Reference +(18079,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Umbrafen Witchdoctor, NPC 20115 +-- --------------------------------------------------- +(20115,21877,80,1,0,1,3), -- Netherweave Cloth +(20115,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(20115,28399,4,1,0,1,1), -- Filtered Draenic Water +(20115,13446,2,1,0,1,1), -- Major Healing Potion +(20115,13444,1,1,0,1,1), -- Major Mana Potion +(20115,2,2,1,0,-6003,1), -- Scroll of * VI Reference +(20115,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Umbraglow Stinger, NPC 18132 +-- --------------------------------------------------- +(18132,25434,80,1,1,1,1), -- Fractured Carapace +(18132,25436,20,1,1,1,1), -- Twitching Leg +(18132,24372,-40,1,0,1,1), -- QItem: Diaphanous Wing +(18132,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Withered Bog Lord, NPC 19402 +-- --------------------------------------------------- +(19402,25450,80,1,0,1,1), -- Creeping Moss +(19402,25452,20,1,1,1,1), -- Blighted Fungus +(19402,24291,-30,1,0,1,1), -- QItem: Bog Lord Tendril +(19402,24401,25,1,0,1,1), -- Unidentified Plant Parts +(19402,22575,19,1,0,1,1), -- Mote of Life +(19402,29481,-15,1,0,1,1), -- QItem: Withered Bog Lord Sample +(19402,12803,1,1,0,1,1), -- Living Essence +(19402,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Withered Giant, NPC 18124 +-- --------------------------------------------------- +(18124,25450,80,1,0,1,1), -- Creeping Moss +(18124,25452,20,1,1,1,1), -- Blighted Fungus +(18124,24401,25,1,0,1,1), -- Unidentified Plant Parts +(18124,24291,-20,1,0,1,1), -- QItem: Bog Lord Tendril +(18124,22575,19,1,0,1,1), -- Mote of Life +(18124,24373,-5,1,0,1,1), -- QItem: Scout Jyoba's Report +(18124,24483,2,1,0,1,1), -- Withered Basidium Ally +(18124,24484,2,1,0,1,1), -- Withered Basidium Horde +(18124,12803,1,1,0,1,1), -- Living Essence +(18124,1,100,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Wrekt Slave, NPC 18123 +-- --------------------------------------------------- +(18123,21877,75,1,0,1,3), -- Netherweave Cloth +(18123,27854,8,1,0,1,1), -- Smoked Talbuk Venison +(18123,28399,4,1,0,1,1), -- Filtered Draenic Water +(18123,13446,2,1,0,1,1), -- Major Healing Potion +(18123,13444,1,1,0,1,1), -- Major Mana Potion +(18123,2,2,1,0,-6003,1), -- Scroll of * VI Reference +(18123,1,80,1,0,-6000,1), -- Generic HellfirePeninsula Loot (YES FOR ZM) +-- --------------------------------------------------- +-- Young Sporebat, NPC 20387 +-- --------------------------------------------------- +(20387,25456,80,1,1,1,1), -- Glowing Spores +(20387,25454,20,1,1,1,1), -- Luminescent Globe +(20387,27676,50,1,0,1,1), -- Strange Spores +(20387,24401,26,1,0,1,1), -- Unidentified Plant Parts +(20387,1,90,1,0,-6000,1); -- Generic HellfirePeninsula Loot (YES FOR ZM) diff --git a/sql/updates/world/2012_06_02_03_world_reference_loot_template.sql b/sql/updates/world/2012_06_02_03_world_reference_loot_template.sql new file mode 100644 index 00000000000..c712cbe18bd --- /dev/null +++ b/sql/updates/world/2012_06_02_03_world_reference_loot_template.sql @@ -0,0 +1,791 @@ +SET @Grey := 1001; -- reference starting value TDB Field +DELETE FROM `reference_loot_template` WHERE `entry` BETWEEN @Grey AND @Grey+53; +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- level 52 Grey Items ilvl 57 +(@Grey+51,3951,0,1,1,1,1), -- Twill Vest +(@Grey+51,3976,0,1,1,1,1), -- Smooth Leather Armor +(@Grey+51,3995,0,1,1,1,1), -- Laminated Scale Cloak +(@Grey+51,8081,0,1,1,1,1), -- Light Plate Belt +(@Grey+51,8753,0,1,1,1,1), -- Smooth Leather Helmet +(@Grey+51,9186,0,1,1,1,1), -- Mind-numbing Poison III +(@Grey+51,13821,0,1,1,1,1), -- Bulky Maul +(@Grey+51,13825,0,1,1,1,1), -- Primed Musket +-- level 53 Grey Items ilvl 58 +(@Grey+52,3948,0,1,1,1,1), -- Twill Gloves +(@Grey+52,3973,0,1,1,1,1), -- Smooth Leather Gloves +(@Grey+52,3994,0,1,1,1,1), -- Laminated Scale Bracers +(@Grey+52,8080,0,1,1,1,1), -- Light Plate Chestpiece +(@Grey+52,13817,0,1,1,1,1); -- Tapered Greatsword +-- -------------------------------------------------------- +-- TBC_Greys_References +-- -------------------------------------------------------- +SET @GreyTBC := 4000; -- reference starting value TDB Field +DELETE FROM `reference_loot_template` WHERE `entry` BETWEEN @GreyTBC AND @GreyTBC+2; +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- level 61 Greys, ilvl 66 (32 items) +(@GreyTBC,24576,0,1,1,1,1), -- Loosely Threaded Belt +(@GreyTBC,24577,0,1,1,1,1), -- Loosely Threaded Boots +(@GreyTBC,24578,0,1,1,1,1), -- Loosely Threaded Bracers +(@GreyTBC,24580,0,1,1,1,1), -- Loosely Threaded Hat +(@GreyTBC,24782,0,1,1,1,1), -- Loosely Threaded Gloves +(@GreyTBC,25338,0,1,1,1,1), -- Loosely Threaded Pants +(@GreyTBC,25339,0,1,1,1,1), -- Loosely Threaded Shoulderpads +(@GreyTBC,25340,0,1,1,1,1), -- Loosely Threaded Vest +(@GreyTBC,25349,0,1,1,1,1), -- Moldy Leather Armor +(@GreyTBC,25350,0,1,1,1,1), -- Moldy Leather Belt +(@GreyTBC,25351,0,1,1,1,1), -- Moldy Leather Boots +(@GreyTBC,25352,0,1,1,1,1), -- Moldy Leather Bracers +(@GreyTBC,25353,0,1,1,1,1), -- Moldy Leather Gloves +(@GreyTBC,25354,0,1,1,1,1), -- Moldy Leather Helmet +(@GreyTBC,25355,0,1,1,1,1), -- Moldy Leather Pants +(@GreyTBC,25356,0,1,1,1,1), -- Moldy Leather Shoulderpads +(@GreyTBC,25365,0,1,1,1,1), -- Eroded Mail Armor +(@GreyTBC,25366,0,1,1,1,1), -- Eroded Mail Belt +(@GreyTBC,25367,0,1,1,1,1), -- Eroded Mail Boots +(@GreyTBC,25368,0,1,1,1,1), -- Eroded Mail Bracers +(@GreyTBC,25369,0,1,1,1,1), -- Eroded Mail Circlet +(@GreyTBC,25370,0,1,1,1,1), -- Eroded Mail Gloves +(@GreyTBC,25371,0,1,1,1,1), -- Eroded Mail Pants +(@GreyTBC,25372,0,1,1,1,1), -- Eroded Mail Shoulderpads +(@GreyTBC,25381,0,1,1,1,1), -- Tarnished Plate Belt +(@GreyTBC,25382,0,1,1,1,1), -- Tarnished Plate Boots +(@GreyTBC,25383,0,1,1,1,1), -- Tarnished Plate Bracers +(@GreyTBC,25384,0,1,1,1,1), -- Tarnished Plate Chestpiece +(@GreyTBC,25385,0,1,1,1,1), -- Tarnished Plate Gloves +(@GreyTBC,25386,0,1,1,1,1), -- Tarnished Plate Helmet +(@GreyTBC,25387,0,1,1,1,1), -- Tarnished Plate Pants +(@GreyTBC,25388,0,1,1,1,1), -- Tarnished Plate Shoulderpads +-- level 64 Greys, ilvl 69 (10 items) +(@GreyTBC+1,25397,0,1,1,1,1), -- Eroded Axe +(@GreyTBC+1,25398,0,1,1,1,1), -- Stone Reaper +(@GreyTBC+1,25399,0,1,1,1,1), -- Deteriorating Blade +(@GreyTBC+1,25400,0,1,1,1,1), -- Tarnished Claymore +(@GreyTBC+1,25401,0,1,1,1,1), -- Corroded Mace +(@GreyTBC+1,25402,0,1,1,1,1), -- The Stoppable Force +(@GreyTBC+1,25403,0,1,1,1,1), -- Sharpened Stilleto +(@GreyTBC+1,25404,0,1,1,1,1), -- Dense War Staff +(@GreyTBC+1,25405,0,1,1,1,1), -- Rusted Musket +(@GreyTBC+1,25406,0,1,1,1,1), -- Broken Longbow +-- lvl 67 Greys, ilvl 72 (32 items) +(@GreyTBC+2,25341,0,1,1,1,1), -- Dilapidated Cloth Belt +(@GreyTBC+2,25342,0,1,1,1,1), -- Dilapidated Cloth Boots +(@GreyTBC+2,25343,0,1,1,1,1), -- Dilapidated Cloth Bracers +(@GreyTBC+2,25344,0,1,1,1,1), -- Dilapidated Cloth Gloves +(@GreyTBC+2,25345,0,1,1,1,1), -- Dilapidated Cloth Hat +(@GreyTBC+2,25346,0,1,1,1,1), -- Dilapidated Cloth Pants +(@GreyTBC+2,25347,0,1,1,1,1), -- Dilapidated Cloth Shoulderpads +(@GreyTBC+2,25348,0,1,1,1,1), -- Dilapidated Cloth Vest +(@GreyTBC+2,25357,0,1,1,1,1), -- Decaying Leather Armor +(@GreyTBC+2,25358,0,1,1,1,1), -- Decaying Leather Belt +(@GreyTBC+2,25359,0,1,1,1,1), -- Decaying Leather Boots +(@GreyTBC+2,25360,0,1,1,1,1), -- Decaying Leather Bracers +(@GreyTBC+2,25361,0,1,1,1,1), -- Decaying Leather Gloves +(@GreyTBC+2,25362,0,1,1,1,1), -- Decaying Leather Helmet +(@GreyTBC+2,25363,0,1,1,1,1), -- Decaying Leather Pants +(@GreyTBC+2,25364,0,1,1,1,1), -- Decaying Leather Shoulderpads +(@GreyTBC+2,25373,0,1,1,1,1), -- Corroded Mail Armor +(@GreyTBC+2,25374,0,1,1,1,1), -- Corroded Mail Belt +(@GreyTBC+2,25375,0,1,1,1,1), -- Corroded Mail Boots +(@GreyTBC+2,25376,0,1,1,1,1), -- Corroded Mail Bracers +(@GreyTBC+2,25377,0,1,1,1,1), -- Corroded Mail Circlet +(@GreyTBC+2,25378,0,1,1,1,1), -- Corroded Mail Gloves +(@GreyTBC+2,25379,0,1,1,1,1), -- Corroded Mail Pants +(@GreyTBC+2,25380,0,1,1,1,1), -- Corroded Mail Shoulderpads +(@GreyTBC+2,25389,0,1,1,1,1), -- Deteriorating Plate Belt +(@GreyTBC+2,25390,0,1,1,1,1), -- Deteriorating Plate Boots +(@GreyTBC+2,25391,0,1,1,1,1), -- Deteriorating Plate Bracers +(@GreyTBC+2,25392,0,1,1,1,1), -- Deteriorating Plate Chestpiece +(@GreyTBC+2,25393,0,1,1,1,1), -- Deteriorating Plate Gloves +(@GreyTBC+2,25394,0,1,1,1,1), -- Deteriorating Plate Helmet +(@GreyTBC+2,25395,0,1,1,1,1), -- Deteriorating Plate Pants +(@GreyTBC+2,25396,0,1,1,1,1); -- Deteriorating Plate Shoulderpads +-- -------------------------------------------------------- +-- TBC_Greens_References +-- -------------------------------------------------------- +SET @GreenTBC := 4100; -- reference starting value TDB Field +DELETE FROM `reference_loot_template` WHERE `entry` BETWEEN @GreenTBC AND @GreenTBC+13; +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- lvl 57 ilvl 81 greens (55 items) TBC +(@GreenTBC,25296,0,1,1,1,1), -- Absorption Dagger +(@GreenTBC,25324,0,1,1,1,1), -- Angerstaff +(@GreenTBC,25058,0,1,1,1,1), -- Anglesite Choker +(@GreenTBC,25240,0,1,1,1,1), -- Azerothian Longbow +(@GreenTBC,28531,0,1,1,1,1), -- Barbed Shrike +(@GreenTBC,24700,0,1,1,1,1), -- Bonechewer Bands +(@GreenTBC,24695,0,1,1,1,1), -- Bonechewer Chestpiece +(@GreenTBC,24693,0,1,1,1,1), -- Bonechewer Pelt-Girdle +(@GreenTBC,24698,0,1,1,1,1), -- Bonechewer Ripleggings +(@GreenTBC,24699,0,1,1,1,1), -- Bonechewer Shoulderguards +(@GreenTBC,24694,0,1,1,1,1), -- Bonechewer Shredboots +(@GreenTBC,24697,0,1,1,1,1), -- Bonechewer Skincloak +(@GreenTBC,24696,0,1,1,1,1), -- Bonechewer Spikegloves +(@GreenTBC,25114,0,1,1,1,1), -- Doomsayer's Mace +(@GreenTBC,25086,0,1,1,1,1), -- Dreamseeker Dandelion +(@GreenTBC,24920,0,1,1,1,1), -- Grimscale Armor +(@GreenTBC,24918,0,1,1,1,1), -- Grimscale Belt +(@GreenTBC,24921,0,1,1,1,1), -- Grimscale Gauntlets +(@GreenTBC,24922,0,1,1,1,1), -- Grimscale Helm +(@GreenTBC,24923,0,1,1,1,1), -- Grimscale Legguards +(@GreenTBC,24924,0,1,1,1,1), -- Grimscale Pauldrons +(@GreenTBC,24919,0,1,1,1,1), -- Grimscale Sabatons +(@GreenTBC,24925,0,1,1,1,1), -- Grimscale Vambraces +(@GreenTBC,25198,0,1,1,1,1), -- Karaborian Battle Axe +(@GreenTBC,25268,0,1,1,1,1), -- Lead-Slug Shotgun +(@GreenTBC,25100,0,1,1,1,1), -- Liege Blade +(@GreenTBC,25212,0,1,1,1,1), -- Lucky Strike Axe +(@GreenTBC,25282,0,1,1,1,1), -- Mahogany Wand +(@GreenTBC,25310,0,1,1,1,1), -- Naaru Lightmace +(@GreenTBC,25072,0,1,1,1,1), -- Northman's Shield +(@GreenTBC,24582,0,1,1,1,1), -- Outlander's Boots +(@GreenTBC,24588,0,1,1,1,1), -- Outlander's Bracers +(@GreenTBC,24585,0,1,1,1,1), -- Outlander's Facewrap +(@GreenTBC,24575,0,1,1,1,1), -- Outlander's Girdle +(@GreenTBC,24584,0,1,1,1,1), -- Outlander's Gloves +(@GreenTBC,24586,0,1,1,1,1), -- Outlander's Leggings +(@GreenTBC,24587,0,1,1,1,1), -- Outlander's Pauldrons +(@GreenTBC,24583,0,1,1,1,1), -- Outlander's Tunic +(@GreenTBC,25170,0,1,1,1,1), -- Rattan Bo Staff +(@GreenTBC,25184,0,1,1,1,1), -- Ravager Claws +(@GreenTBC,25156,0,1,1,1,1), -- Royal Crusader Sword +(@GreenTBC,25044,0,1,1,1,1), -- Rubellite Ring +(@GreenTBC,25128,0,1,1,1,1), -- Shining Mace +(@GreenTBC,25030,0,1,1,1,1), -- Silky Velvet Cloak +(@GreenTBC,25142,0,1,1,1,1), -- Telaari Longblade +(@GreenTBC,25254,0,1,1,1,1), -- Tower Crossbow +(@GreenTBC,24813,0,1,1,1,1), -- Unyielding Bindings +(@GreenTBC,24808,0,1,1,1,1), -- Unyielding Chain Vest +(@GreenTBC,24809,0,1,1,1,1), -- Unyielding Fists +(@GreenTBC,24807,0,1,1,1,1), -- Unyielding Footwraps +(@GreenTBC,24810,0,1,1,1,1), -- Unyielding Helm +(@GreenTBC,24811,0,1,1,1,1), -- Unyielding Leggings +(@GreenTBC,24812,0,1,1,1,1), -- Unyielding Spaulders +(@GreenTBC,24806,0,1,1,1,1), -- Unyielding Waistband +(@GreenTBC,25226,0,1,1,1,1), -- War Scythe +-- lvl 58 ilvl 84 greens (55 items) TBC +(@GreenTBC+1,24926,0,1,1,1,1), -- Ango'rosh Belt +(@GreenTBC+1,24928,0,1,1,1,1), -- Ango'rosh Breastplate +(@GreenTBC+1,24929,0,1,1,1,1), -- Ango'rosh Gauntlets +(@GreenTBC+1,24930,0,1,1,1,1), -- Ango'rosh Helm +(@GreenTBC+1,24931,0,1,1,1,1), -- Ango'rosh Legguards +(@GreenTBC+1,24932,0,1,1,1,1), -- Ango'rosh Pauldrons +(@GreenTBC+1,24927,0,1,1,1,1), -- Ango'rosh Sabatons +(@GreenTBC+1,24933,0,1,1,1,1), -- Ango'rosh Vambraces +(@GreenTBC+1,25241,0,1,1,1,1), -- Ashenvale Longbow +(@GreenTBC+1,25045,0,1,1,1,1), -- Azurite Ring +(@GreenTBC+1,25087,0,1,1,1,1), -- Bleeding Eye +(@GreenTBC+1,25325,0,1,1,1,1), -- Brutal Scar-Limb +(@GreenTBC+1,25101,0,1,1,1,1), -- Cross Pommel Dagger +(@GreenTBC+1,25283,0,1,1,1,1), -- Crystallized Ebony Wand +(@GreenTBC+1,25073,0,1,1,1,1), -- Emperor Shield +(@GreenTBC+1,24821,0,1,1,1,1), -- Felstone Bindings +(@GreenTBC+1,24816,0,1,1,1,1), -- Felstone Chain Vest +(@GreenTBC+1,24817,0,1,1,1,1), -- Felstone Gauntlets +(@GreenTBC+1,24815,0,1,1,1,1), -- Felstone Greaves +(@GreenTBC+1,24818,0,1,1,1,1), -- Felstone Helm +(@GreenTBC+1,24819,0,1,1,1,1), -- Felstone Leggings +(@GreenTBC+1,24820,0,1,1,1,1), -- Felstone Spaulders +(@GreenTBC+1,24814,0,1,1,1,1), -- Felstone Waistband +(@GreenTBC+1,25213,0,1,1,1,1), -- Fel-Touched Axe +(@GreenTBC+1,25059,0,1,1,1,1), -- Fire Opal Collar +(@GreenTBC+1,24590,0,1,1,1,1), -- Fireheart Boots +(@GreenTBC+1,24596,0,1,1,1,1), -- Fireheart Bracers +(@GreenTBC+1,24591,0,1,1,1,1), -- Fireheart Chestpiece +(@GreenTBC+1,24589,0,1,1,1,1), -- Fireheart Girdle +(@GreenTBC+1,24592,0,1,1,1,1), -- Fireheart Gloves +(@GreenTBC+1,24594,0,1,1,1,1), -- Fireheart Leggings +(@GreenTBC+1,24595,0,1,1,1,1), -- Fireheart Shoulderpads +(@GreenTBC+1,24593,0,1,1,1,1), -- Fireheart Skullcap +(@GreenTBC+1,25129,0,1,1,1,1), -- Giant's Leg Bone +(@GreenTBC+1,24708,0,1,1,1,1), -- Haal'eshi Bindings +(@GreenTBC+1,24702,0,1,1,1,1), -- Haal'eshi Boots +(@GreenTBC+1,24701,0,1,1,1,1), -- Haal'eshi Cord +(@GreenTBC+1,24704,0,1,1,1,1), -- Haal'eshi Gloves +(@GreenTBC+1,24705,0,1,1,1,1), -- Haal'eshi Hat +(@GreenTBC+1,24703,0,1,1,1,1), -- Haal'eshi Jerkin +(@GreenTBC+1,24706,0,1,1,1,1), -- Haal'eshi Leggings +(@GreenTBC+1,24707,0,1,1,1,1), -- Haal'eshi Pauldrons +(@GreenTBC+1,25199,0,1,1,1,1), -- Knight's War Axe +(@GreenTBC+1,25269,0,1,1,1,1), -- Longbeard Rifle +(@GreenTBC+1,25255,0,1,1,1,1), -- Ram's Head Crossbow +(@GreenTBC+1,25311,0,1,1,1,1), -- Revitalizing Hammer +(@GreenTBC+1,25115,0,1,1,1,1), -- Riversong Mace +(@GreenTBC+1,25157,0,1,1,1,1), -- Serpentlord Claymore +(@GreenTBC+1,25227,0,1,1,1,1), -- Sha'tari Longspear +(@GreenTBC+1,25143,0,1,1,1,1), -- Silver Hand Blade +(@GreenTBC+1,28532,0,1,1,1,1), -- Silver Throwing Knives +(@GreenTBC+1,25031,0,1,1,1,1), -- Silvermoon Royal Cloak +(@GreenTBC+1,25171,0,1,1,1,1), -- Straight Hardwood Staff +(@GreenTBC+1,25185,0,1,1,1,1), -- Thrasher Blades +(@GreenTBC+1,25297,0,1,1,1,1), -- Tuning Knife +-- lvl 59 ilvl 87 greens (55 items) TBC +(@GreenTBC+2,25298,0,1,1,1,1), -- Combustion Dagger +(@GreenTBC+2,24934,0,1,1,1,1), -- Darkcrest Belt +(@GreenTBC+2,24941,0,1,1,1,1), -- Darkcrest Bracers +(@GreenTBC+2,24936,0,1,1,1,1), -- Darkcrest Breastplate +(@GreenTBC+2,24937,0,1,1,1,1), -- Darkcrest Gauntlets +(@GreenTBC+2,24938,0,1,1,1,1), -- Darkcrest Helm +(@GreenTBC+2,24939,0,1,1,1,1), -- Darkcrest Legguards +(@GreenTBC+2,24940,0,1,1,1,1), -- Darkcrest Pauldrons +(@GreenTBC+2,24935,0,1,1,1,1), -- Darkcrest Sabatons +(@GreenTBC+2,25312,0,1,1,1,1), -- Glorious Scepter +(@GreenTBC+2,25270,0,1,1,1,1), -- Gnomish Assault Rifle +(@GreenTBC+2,25130,0,1,1,1,1), -- Gronn-Bone Club +(@GreenTBC+2,25228,0,1,1,1,1), -- Halberd Polearm +(@GreenTBC+2,25032,0,1,1,1,1), -- Hellfire Cloak +(@GreenTBC+2,25102,0,1,1,1,1), -- Jaedenis Dagger +(@GreenTBC+2,25200,0,1,1,1,1), -- Jagged Broadaxe +(@GreenTBC+2,25172,0,1,1,1,1), -- Jinbali Warp-Staff +(@GreenTBC+2,25088,0,1,1,1,1), -- Laughing Skull Orb +(@GreenTBC+2,25214,0,1,1,1,1), -- Mok'Nathal Battleaxe +(@GreenTBC+2,24824,0,1,1,1,1), -- Netherstalker Armor +(@GreenTBC+2,24822,0,1,1,1,1), -- Netherstalker Belt +(@GreenTBC+2,24829,0,1,1,1,1), -- Netherstalker Bracer +(@GreenTBC+2,24825,0,1,1,1,1), -- Netherstalker Gloves +(@GreenTBC+2,24823,0,1,1,1,1), -- Netherstalker Greaves +(@GreenTBC+2,24826,0,1,1,1,1), -- Netherstalker Helmet +(@GreenTBC+2,24827,0,1,1,1,1), -- Netherstalker Legguards +(@GreenTBC+2,24828,0,1,1,1,1), -- Netherstalker Mantle +(@GreenTBC+2,25116,0,1,1,1,1), -- Pneumatic War Hammer +(@GreenTBC+2,25326,0,1,1,1,1), -- Primal Lore-Staff +(@GreenTBC+2,25284,0,1,1,1,1), -- Purpleheart Wand +(@GreenTBC+2,25158,0,1,1,1,1), -- Skeletal Broadsword +(@GreenTBC+2,25144,0,1,1,1,1), -- Skettis Curved Blade +(@GreenTBC+2,25046,0,1,1,1,1), -- Spined Ring +(@GreenTBC+2,24601,0,1,1,1,1), -- Starfire Circlet +(@GreenTBC+2,24600,0,1,1,1,1), -- Starfire Gloves +(@GreenTBC+2,24603,0,1,1,1,1), -- Starfire Mantle +(@GreenTBC+2,24598,0,1,1,1,1), -- Starfire Sandals +(@GreenTBC+2,24597,0,1,1,1,1), -- Starfire Sash +(@GreenTBC+2,24602,0,1,1,1,1), -- Starfire Trousers +(@GreenTBC+2,24599,0,1,1,1,1), -- Starfire Vest +(@GreenTBC+2,24604,0,1,1,1,1), -- Starfire Wristwraps +(@GreenTBC+2,25256,0,1,1,1,1), -- Stronghold Crossbow +(@GreenTBC+2,25060,0,1,1,1,1), -- Sunstone Necklace +(@GreenTBC+2,25242,0,1,1,1,1), -- Telaari Longbow +(@GreenTBC+2,25074,0,1,1,1,1), -- Telaari Shield +(@GreenTBC+2,25186,0,1,1,1,1), -- Vampiric Handscythes +(@GreenTBC+2,24716,0,1,1,1,1), -- Vengeance Bands +(@GreenTBC+2,24709,0,1,1,1,1), -- Vengeance Belt +(@GreenTBC+2,24710,0,1,1,1,1), -- Vengeance Boots +(@GreenTBC+2,24711,0,1,1,1,1), -- Vengeance Chestpiece +(@GreenTBC+2,24712,0,1,1,1,1), -- Vengeance Gloves +(@GreenTBC+2,24713,0,1,1,1,1), -- Vengeance Helm +(@GreenTBC+2,24714,0,1,1,1,1), -- Vengeance Legguards +(@GreenTBC+2,24715,0,1,1,1,1), -- Vengeance Pauldrons +(@GreenTBC+2,28533,0,1,1,1,1), -- Wooden Boomerang +-- lvl 60 ilvl 90 greens (51 items) TBC +(@GreenTBC+3,24605,0,1,1,1,1), -- Laughing Skull Waistguard +(@GreenTBC+3,24606,0,1,1,1,1), -- Laughing Skull Boot +(@GreenTBC+3,24607,0,1,1,1,1), -- Laughing Skull Tunic +(@GreenTBC+3,24608,0,1,1,1,1), -- Laughing Skull Gloves +(@GreenTBC+3,24609,0,1,1,1,1), -- Laughing Skull Cap +(@GreenTBC+3,24610,0,1,1,1,1), -- Laughing Skull Pants +(@GreenTBC+3,24611,0,1,1,1,1), -- Laughing Skull Shoulderpads +(@GreenTBC+3,24612,0,1,1,1,1), -- Laughing Skull Bracelets +(@GreenTBC+3,24717,0,1,1,1,1), -- Dreghood Belt +(@GreenTBC+3,24718,0,1,1,1,1), -- Dreghood Boots +(@GreenTBC+3,24719,0,1,1,1,1), -- Dreghood Chestpiece +(@GreenTBC+3,24720,0,1,1,1,1), -- Dreghood Gloves +(@GreenTBC+3,24721,0,1,1,1,1), -- Dreghood Cowl +(@GreenTBC+3,24722,0,1,1,1,1), -- Dreghood Trousers +(@GreenTBC+3,24723,0,1,1,1,1), -- Dreghood Pauldrons +(@GreenTBC+3,24724,0,1,1,1,1), -- Dreghood Bands +(@GreenTBC+3,24830,0,1,1,1,1), -- Nexus-Strider Belt +(@GreenTBC+3,24831,0,1,1,1,1), -- Nexus-Strider Greaves +(@GreenTBC+3,24832,0,1,1,1,1), -- Nexus-Strider Breastplate +(@GreenTBC+3,24833,0,1,1,1,1), -- Nexus-Strider Gloves +(@GreenTBC+3,24834,0,1,1,1,1), -- Nexus-Strider Helmet +(@GreenTBC+3,24835,0,1,1,1,1), -- Nexus-Strider Legwraps +(@GreenTBC+3,24836,0,1,1,1,1), -- Nexus-Strider Mantle +(@GreenTBC+3,24837,0,1,1,1,1), -- Nexus-Strider Bracer +(@GreenTBC+3,24942,0,1,1,1,1), -- Bloodscale Belt +(@GreenTBC+3,24943,0,1,1,1,1), -- Bloodscale Sabatons +(@GreenTBC+3,24944,0,1,1,1,1), -- Bloodscale Breastplate +(@GreenTBC+3,24945,0,1,1,1,1), -- Bloodscale Gauntlets +(@GreenTBC+3,24946,0,1,1,1,1), -- Bloodscale Helm +(@GreenTBC+3,24947,0,1,1,1,1), -- Bloodscale Legguards +(@GreenTBC+3,24948,0,1,1,1,1), -- Bloodscale Pauldrons +(@GreenTBC+3,24949,0,1,1,1,1), -- Bloodscale Bracers +(@GreenTBC+3,25033,0,1,1,1,1), -- Scavenger's Cloak +(@GreenTBC+3,25047,0,1,1,1,1), -- Tourmaline Loop +(@GreenTBC+3,25061,0,1,1,1,1), -- Hiddenite Necklace +(@GreenTBC+3,25075,0,1,1,1,1), -- Hardened Steel Shield +(@GreenTBC+3,25089,0,1,1,1,1), -- Supplicant's Rod +(@GreenTBC+3,25103,0,1,1,1,1), -- Nightstalker Dagger +(@GreenTBC+3,25117,0,1,1,1,1), -- Flanged Battle Mace +(@GreenTBC+3,25131,0,1,1,1,1), -- Hateful Bludgeon +(@GreenTBC+3,25187,0,1,1,1,1), -- Shekketh Talons +(@GreenTBC+3,25201,0,1,1,1,1), -- Reaver's Sickle +(@GreenTBC+3,25215,0,1,1,1,1), -- Spiked Battle Axe +(@GreenTBC+3,25229,0,1,1,1,1), -- Partisan Polearm +(@GreenTBC+3,25243,0,1,1,1,1), -- Windtalker Bow +(@GreenTBC+3,25257,0,1,1,1,1), -- Citadel Crossbow +(@GreenTBC+3,25271,0,1,1,1,1), -- Croc-Hunter's Rifle +(@GreenTBC+3,25299,0,1,1,1,1), -- Siphoning Dagger +(@GreenTBC+3,25313,0,1,1,1,1), -- Cold-Iron Scepter +(@GreenTBC+3,25327,0,1,1,1,1), -- Frenzied Staff +(@GreenTBC+3,28534,0,1,1,1,1), -- Fel Tipped Dart +-- lvl 61 ilvl 93 greens (55 items) TBC +(@GreenTBC+4,24613,0,1,1,1,1), -- Vindicator Belt +(@GreenTBC+4,24614,0,1,1,1,1), -- Vindicator Boots +(@GreenTBC+4,24615,0,1,1,1,1), -- Vindicator Tunic +(@GreenTBC+4,24616,0,1,1,1,1), -- Vindicator Gloves +(@GreenTBC+4,24617,0,1,1,1,1), -- Vindicator Cap +(@GreenTBC+4,24618,0,1,1,1,1), -- Vindicator Pants +(@GreenTBC+4,24619,0,1,1,1,1), -- Vindicator Shoulderpads +(@GreenTBC+4,24620,0,1,1,1,1), -- Vindicator Bracers +(@GreenTBC+4,24725,0,1,1,1,1), -- Dementia Cord +(@GreenTBC+4,24726,0,1,1,1,1), -- Dementia Boots +(@GreenTBC+4,24727,0,1,1,1,1), -- Dementia Vest +(@GreenTBC+4,24728,0,1,1,1,1), -- Dementia Gloves +(@GreenTBC+4,24729,0,1,1,1,1), -- Dementia Hood +(@GreenTBC+4,24730,0,1,1,1,1), -- Dementia Trousers +(@GreenTBC+4,24731,0,1,1,1,1), -- Dementia Shoulderguards +(@GreenTBC+4,24732,0,1,1,1,1), -- Dementia Armguards +(@GreenTBC+4,24838,0,1,1,1,1), -- Wrathfin Waistband +(@GreenTBC+4,24839,0,1,1,1,1), -- Wrathfin Greaves +(@GreenTBC+4,24840,0,1,1,1,1), -- Wrathfin Armor +(@GreenTBC+4,24841,0,1,1,1,1), -- Wrathfin Gloves +(@GreenTBC+4,24842,0,1,1,1,1), -- Wrathfin Helmet +(@GreenTBC+4,24843,0,1,1,1,1), -- Wrathfin Legguards +(@GreenTBC+4,24844,0,1,1,1,1), -- Wrathfin Mantle +(@GreenTBC+4,24845,0,1,1,1,1), -- Wrathfin Bindings +(@GreenTBC+4,24950,0,1,1,1,1), -- Bogslayer Belt +(@GreenTBC+4,24951,0,1,1,1,1), -- Bogslayer Sabatons +(@GreenTBC+4,24952,0,1,1,1,1), -- Bogslayer Breastplate +(@GreenTBC+4,24953,0,1,1,1,1), -- Bogslayer Gauntlets +(@GreenTBC+4,24954,0,1,1,1,1), -- Bogslayer Helm +(@GreenTBC+4,24955,0,1,1,1,1), -- Bogslayer Legplates +(@GreenTBC+4,24956,0,1,1,1,1), -- Bogslayer Pauldrons +(@GreenTBC+4,24957,0,1,1,1,1), -- Bogslayer Bracers +(@GreenTBC+4,25034,0,1,1,1,1), -- Elementalist Cloak +(@GreenTBC+4,25048,0,1,1,1,1), -- Smoky Quartz Ring +(@GreenTBC+4,25062,0,1,1,1,1), -- Zircon Amulet +(@GreenTBC+4,25076,0,1,1,1,1), -- Screaming Shield +(@GreenTBC+4,25090,0,1,1,1,1), -- Slavehandler Rod +(@GreenTBC+4,25104,0,1,1,1,1), -- Anzac Dagger +(@GreenTBC+4,25118,0,1,1,1,1), -- Battle Star +(@GreenTBC+4,25132,0,1,1,1,1), -- Thrallmar War Hammer +(@GreenTBC+4,25146,0,1,1,1,1), -- Light-Etched Longsword +(@GreenTBC+4,25160,0,1,1,1,1), -- Vengeance Blade +(@GreenTBC+4,25174,0,1,1,1,1), -- Hanbo Staff +(@GreenTBC+4,25188,0,1,1,1,1), -- Spleenripper Claws +(@GreenTBC+4,25202,0,1,1,1,1), -- Kingly Axe +(@GreenTBC+4,25216,0,1,1,1,1), -- Ogre Splitting Axe +(@GreenTBC+4,25230,0,1,1,1,1), -- Voulge Blade +(@GreenTBC+4,25244,0,1,1,1,1), -- Viper Bow +(@GreenTBC+4,25258,0,1,1,1,1), -- Repeater Crossbow +(@GreenTBC+4,25272,0,1,1,1,1), -- PC-54 Shotgun +(@GreenTBC+4,25286,0,1,1,1,1), -- Yew Wand +(@GreenTBC+4,25300,0,1,1,1,1), -- Lightning Dagger +(@GreenTBC+4,25314,0,1,1,1,1), -- Ceremonial Hammer +(@GreenTBC+4,25328,0,1,1,1,1), -- Faerie-Kind Staff +(@GreenTBC+4,28535,0,1,1,1,1), -- Amani Throwing Axe +-- lvl 62 ilvl 96 greens (55 items) TBC +(@GreenTBC+5,24621,0,1,1,1,1), -- Slavehandler Belt +(@GreenTBC+5,24622,0,1,1,1,1), -- Slavehandler Footpads +(@GreenTBC+5,24623,0,1,1,1,1), -- Slavehandler Jerkin +(@GreenTBC+5,24624,0,1,1,1,1), -- Slavehandler Handwraps +(@GreenTBC+5,24625,0,1,1,1,1), -- Slavehandler Cap +(@GreenTBC+5,24626,0,1,1,1,1), -- Slavehandler Pants +(@GreenTBC+5,24627,0,1,1,1,1), -- Slavehandler Amice +(@GreenTBC+5,24628,0,1,1,1,1), -- Slavehandler Wristguards +(@GreenTBC+5,24733,0,1,1,1,1), -- Sunroc Waistband +(@GreenTBC+5,24734,0,1,1,1,1), -- Sunroc Boots +(@GreenTBC+5,24735,0,1,1,1,1), -- Sunroc Chestpiece +(@GreenTBC+5,24736,0,1,1,1,1), -- Sunroc Gloves +(@GreenTBC+5,24737,0,1,1,1,1), -- Sunroc Mask +(@GreenTBC+5,24738,0,1,1,1,1), -- Sunroc Pants +(@GreenTBC+5,24739,0,1,1,1,1), -- Sunroc Shoulderguards +(@GreenTBC+5,24740,0,1,1,1,1), -- Sunroc Armguards +(@GreenTBC+5,24846,0,1,1,1,1), -- Fenclaw Waistband +(@GreenTBC+5,24847,0,1,1,1,1), -- Fenclaw Footwraps +(@GreenTBC+5,24848,0,1,1,1,1), -- Fenclaw Armor +(@GreenTBC+5,24849,0,1,1,1,1), -- Fenclaw Fists +(@GreenTBC+5,24850,0,1,1,1,1), -- Fenclaw Helm +(@GreenTBC+5,24851,0,1,1,1,1), -- Fenclaw Legguards +(@GreenTBC+5,24852,0,1,1,1,1), -- Fenclaw Mantle +(@GreenTBC+5,24853,0,1,1,1,1), -- Fenclaw Bindings +(@GreenTBC+5,24958,0,1,1,1,1), -- Khan'aish Girdle +(@GreenTBC+5,24959,0,1,1,1,1), -- Khan'aish Greaves +(@GreenTBC+5,24960,0,1,1,1,1), -- Khan'aish Breastplate +(@GreenTBC+5,24961,0,1,1,1,1), -- Khan'aish Gloves +(@GreenTBC+5,24962,0,1,1,1,1), -- Khan'aish Helmet +(@GreenTBC+5,24963,0,1,1,1,1), -- Khan'aish Legplates +(@GreenTBC+5,24964,0,1,1,1,1), -- Khan'aish Epaulets +(@GreenTBC+5,24965,0,1,1,1,1), -- Khan'aish Bracers +(@GreenTBC+5,25035,0,1,1,1,1), -- Silver-Lined Cloak +(@GreenTBC+5,25049,0,1,1,1,1), -- Scheelite Ring +(@GreenTBC+5,25063,0,1,1,1,1), -- Multi-Colored Beads +(@GreenTBC+5,25077,0,1,1,1,1), -- Modani War-Shield +(@GreenTBC+5,25091,0,1,1,1,1), -- Mistyreed Torch +(@GreenTBC+5,25105,0,1,1,1,1), -- Arachnid Dagger +(@GreenTBC+5,25119,0,1,1,1,1), -- Silvermoon War-Mace +(@GreenTBC+5,25133,0,1,1,1,1), -- Stormwind Maul +(@GreenTBC+5,25147,0,1,1,1,1), -- Skystrider Katana +(@GreenTBC+5,25161,0,1,1,1,1), -- Dragon Wing Blade +(@GreenTBC+5,25175,0,1,1,1,1), -- Demoniac Longstaff +(@GreenTBC+5,25189,0,1,1,1,1), -- Ironspine Point +(@GreenTBC+5,25203,0,1,1,1,1), -- Chipped Woodchopper +(@GreenTBC+5,25217,0,1,1,1,1), -- Sundering Axe +(@GreenTBC+5,25231,0,1,1,1,1), -- Fel-Wrought Halberd +(@GreenTBC+5,25245,0,1,1,1,1), -- Razorsong Bow +(@GreenTBC+5,25259,0,1,1,1,1), -- Collapsible Crossbow +(@GreenTBC+5,25273,0,1,1,1,1), -- Sawed-Off Shotgun +(@GreenTBC+5,25287,0,1,1,1,1), -- Magician's Wand +(@GreenTBC+5,25301,0,1,1,1,1), -- Shattering Dagger +(@GreenTBC+5,25315,0,1,1,1,1), -- Restorative Mace +(@GreenTBC+5,25329,0,1,1,1,1), -- Tranquility Staff +(@GreenTBC+5,28536,0,1,1,1,1), -- Jagged Guillotine +-- lvl 63 ilvl 99 greens (55 items) TBC +(@GreenTBC+6,24629,0,1,1,1,1), -- Feralfen Sash +(@GreenTBC+6,24630,0,1,1,1,1), -- Feralfen Sandals +(@GreenTBC+6,24631,0,1,1,1,1), -- Feralfen Jerkin +(@GreenTBC+6,24632,0,1,1,1,1), -- Feralfen Hand +(@GreenTBC+6,24633,0,1,1,1,1), -- Feralfen Hood +(@GreenTBC+6,24634,0,1,1,1,1), -- Feralfen Pants +(@GreenTBC+6,24635,0,1,1,1,1), -- Feralfen Amice +(@GreenTBC+6,24636,0,1,1,1,1), -- Feralfen Cuffs +(@GreenTBC+6,24741,0,1,1,1,1), -- Ranger Belt +(@GreenTBC+6,24742,0,1,1,1,1), -- Ranger Boots +(@GreenTBC+6,24743,0,1,1,1,1), -- Ranger Jerkin +(@GreenTBC+6,24744,0,1,1,1,1), -- Ranger Gloves +(@GreenTBC+6,24745,0,1,1,1,1), -- Ranger Hat +(@GreenTBC+6,24746,0,1,1,1,1), -- Ranger Pants +(@GreenTBC+6,24747,0,1,1,1,1), -- Ranger Pauldrons +(@GreenTBC+6,24748,0,1,1,1,1), -- Ranger Armguards +(@GreenTBC+6,24854,0,1,1,1,1), -- Marshcreeper Belt +(@GreenTBC+6,24855,0,1,1,1,1), -- Marshcreeper Sludgeboots +(@GreenTBC+6,24856,0,1,1,1,1), -- Marshcreeper Fen-Vest +(@GreenTBC+6,24857,0,1,1,1,1), -- Marshcreeper Gloves +(@GreenTBC+6,24858,0,1,1,1,1), -- Marshcreeper Helm +(@GreenTBC+6,24859,0,1,1,1,1), -- Marshcreeper Leggings +(@GreenTBC+6,24860,0,1,1,1,1), -- Marshcreeper Mantle +(@GreenTBC+6,24861,0,1,1,1,1), -- Marshcreeper Bracelets +(@GreenTBC+6,24966,0,1,1,1,1), -- Talonguard Girdle +(@GreenTBC+6,24967,0,1,1,1,1), -- Talonguard Greaves +(@GreenTBC+6,24968,0,1,1,1,1), -- Talonguard Armor +(@GreenTBC+6,24969,0,1,1,1,1), -- Talonguard Gloves +(@GreenTBC+6,24970,0,1,1,1,1), -- Talonguard Helmet +(@GreenTBC+6,24971,0,1,1,1,1), -- Talonguard Legplates +(@GreenTBC+6,24972,0,1,1,1,1), -- Talonguard Epaulets +(@GreenTBC+6,24973,0,1,1,1,1), -- Talonguard Bracers +(@GreenTBC+6,25036,0,1,1,1,1), -- Boulderfist Cloak +(@GreenTBC+6,25050,0,1,1,1,1), -- Moldavite Ring +(@GreenTBC+6,25064,0,1,1,1,1), -- Amethyst Pendant +(@GreenTBC+6,25078,0,1,1,1,1), -- Zangari Shield +(@GreenTBC+6,25092,0,1,1,1,1), -- Consortium Crystal +(@GreenTBC+6,25106,0,1,1,1,1), -- Cobra Shortblade +(@GreenTBC+6,25120,0,1,1,1,1), -- Rockshard Club +(@GreenTBC+6,25134,0,1,1,1,1), -- Highmountain Hammer +(@GreenTBC+6,25148,0,1,1,1,1), -- Bone Collector Sword +(@GreenTBC+6,25162,0,1,1,1,1), -- Darkened Broadsword +(@GreenTBC+6,25176,0,1,1,1,1), -- Taiji Quarterstaff +(@GreenTBC+6,25190,0,1,1,1,1), -- Wight's Claws +(@GreenTBC+6,25204,0,1,1,1,1), -- Colossal War Axe +(@GreenTBC+6,25218,0,1,1,1,1), -- Silver-Edged Axe +(@GreenTBC+6,25232,0,1,1,1,1), -- War Glaive +(@GreenTBC+6,25246,0,1,1,1,1), -- Thalassian Compound Bow +(@GreenTBC+6,25260,0,1,1,1,1), -- Archer's Crossbow +(@GreenTBC+6,25274,0,1,1,1,1), -- Cliffjumper Shotgun +(@GreenTBC+6,25288,0,1,1,1,1), -- Conjurer's Wand +(@GreenTBC+6,25302,0,1,1,1,1), -- Soul-Drain Dagger +(@GreenTBC+6,25316,0,1,1,1,1), -- Spirit-Clad Mace +(@GreenTBC+6,25330,0,1,1,1,1), -- Starshine Staff +(@GreenTBC+6,28537,0,1,1,1,1), -- Wildhammer Throwing Axe +-- lvl 67 ilvl 111 greens (55 items) TBC +(@GreenTBC+10,24661,0,1,1,1,1), -- Shadow Council Chain +(@GreenTBC+10,24662,0,1,1,1,1), -- Shadow Council Boots +(@GreenTBC+10,24663,0,1,1,1,1), -- Shadow Council Tunic +(@GreenTBC+10,24664,0,1,1,1,1), -- Shadow Council Gloves +(@GreenTBC+10,24665,0,1,1,1,1), -- Shadow Council Cowl +(@GreenTBC+10,24666,0,1,1,1,1), -- Shadow Council Pants +(@GreenTBC+10,24667,0,1,1,1,1), -- Shadow Council Mantle +(@GreenTBC+10,24668,0,1,1,1,1), -- Shadow Council Bracer +(@GreenTBC+10,24773,0,1,1,1,1), -- Boneshredder Belt +(@GreenTBC+10,24774,0,1,1,1,1), -- Boneshredder Boots +(@GreenTBC+10,24775,0,1,1,1,1), -- Boneshredder Jerkin +(@GreenTBC+10,24776,0,1,1,1,1), -- Boneshredder Gloves +(@GreenTBC+10,24777,0,1,1,1,1), -- Boneshredder Skullcap +(@GreenTBC+10,24778,0,1,1,1,1), -- Boneshredder Britches +(@GreenTBC+10,24779,0,1,1,1,1), -- Boneshredder Shoulderguards +(@GreenTBC+10,24780,0,1,1,1,1), -- Boneshredder Wristguards +(@GreenTBC+10,24886,0,1,1,1,1), -- Skettis Belt +(@GreenTBC+10,24887,0,1,1,1,1), -- Skettis Footwraps +(@GreenTBC+10,24888,0,1,1,1,1), -- Skettis Chestpiece +(@GreenTBC+10,24889,0,1,1,1,1), -- Skettis Gauntlets +(@GreenTBC+10,24890,0,1,1,1,1), -- Skettis Helmet +(@GreenTBC+10,24891,0,1,1,1,1), -- Skettis Legguards +(@GreenTBC+10,24892,0,1,1,1,1), -- Skettis Spaulders +(@GreenTBC+10,24893,0,1,1,1,1), -- Skettis Bracer +(@GreenTBC+10,24998,0,1,1,1,1), -- Bloodfist Girdle +(@GreenTBC+10,24999,0,1,1,1,1), -- Bloodfist Greaves +(@GreenTBC+10,25000,0,1,1,1,1), -- Bloodfist Breastplate +(@GreenTBC+10,25001,0,1,1,1,1), -- Bloodfist Gloves +(@GreenTBC+10,25002,0,1,1,1,1), -- Bloodfist Helmet +(@GreenTBC+10,25003,0,1,1,1,1), -- Bloodfist Legplates +(@GreenTBC+10,25004,0,1,1,1,1), -- Bloodfist Epaulets +(@GreenTBC+10,25005,0,1,1,1,1), -- Bloodfist Vambraces +(@GreenTBC+10,25040,0,1,1,1,1), -- Murkblood Cape +(@GreenTBC+10,25054,0,1,1,1,1), -- Sodalite Band +(@GreenTBC+10,25068,0,1,1,1,1), -- Kunzite Necklace +(@GreenTBC+10,25082,0,1,1,1,1), -- Fel-Iron Shield +(@GreenTBC+10,25096,0,1,1,1,1), -- Elementalist Star +(@GreenTBC+10,25110,0,1,1,1,1), -- Sharp Bowie Knife +(@GreenTBC+10,25124,0,1,1,1,1), -- Footman Mace +(@GreenTBC+10,25138,0,1,1,1,1), -- Blood Knight Maul +(@GreenTBC+10,25152,0,1,1,1,1), -- Howling Sword +(@GreenTBC+10,25166,0,1,1,1,1), -- Mok'Nathal Warblade +(@GreenTBC+10,25180,0,1,1,1,1), -- Calenda Fighting Stick +(@GreenTBC+10,25194,0,1,1,1,1), -- Serpent's Fangs +(@GreenTBC+10,25208,0,1,1,1,1), -- Bladespire Broadaxe +(@GreenTBC+10,25222,0,1,1,1,1), -- Ceremonial Slayer's Axe +(@GreenTBC+10,25236,0,1,1,1,1), -- Grim Scythe +(@GreenTBC+10,25250,0,1,1,1,1), -- Rocslayer Longbow +(@GreenTBC+10,25264,0,1,1,1,1), -- Pocket Ballista +(@GreenTBC+10,25278,0,1,1,1,1), -- Nesingwary Longrifle +(@GreenTBC+10,25292,0,1,1,1,1), -- Mechano-Wand +(@GreenTBC+10,25306,0,1,1,1,1), -- Permafrost Dagger +(@GreenTBC+10,25320,0,1,1,1,1), -- Queen's Insignia +(@GreenTBC+10,25334,0,1,1,1,1), -- Intimidating Greatstaff +(@GreenTBC+10,28541,0,1,1,1,1), -- Sawshrike +(@GreenTBC+10,30520,0,1,1,1,1), -- Gold-Trimmed Cuffs +(@GreenTBC+10,30986,0,1,1,1,1), -- Bloodforged Guard +-- lvl 68 ilvl 114 greens (55 items) TBC +(@GreenTBC+11,25055,0,1,1,1,1), -- Alexandrite Ring +(@GreenTBC+11,25139,0,1,1,1,1), -- Algaz Battle Hammer +(@GreenTBC+11,25209,0,1,1,1,1), -- Amani Tomahawk +(@GreenTBC+11,25041,0,1,1,1,1), -- Ambusher's Cloak +(@GreenTBC+11,25097,0,1,1,1,1), -- Astralaan Orb +(@GreenTBC+11,25265,0,1,1,1,1), -- Barreled Crossbow +(@GreenTBC+11,25008,0,1,1,1,1), -- Conqueror's Breastplate +(@GreenTBC+11,25012,0,1,1,1,1), -- Conqueror's Epaulets +(@GreenTBC+11,25009,0,1,1,1,1), -- Conqueror's Gauntlets +(@GreenTBC+11,25006,0,1,1,1,1), -- Conqueror's Girdle +(@GreenTBC+11,25007,0,1,1,1,1), -- Conqueror's Greaves +(@GreenTBC+11,25010,0,1,1,1,1), -- Conqueror's Helmet +(@GreenTBC+11,25011,0,1,1,1,1), -- Conqueror's Legplates +(@GreenTBC+11,25013,0,1,1,1,1), -- Conqueror's Vambraces +(@GreenTBC+11,25195,0,1,1,1,1), -- Diamond Tipped Claws +(@GreenTBC+11,25321,0,1,1,1,1), -- Divine Hammer +(@GreenTBC+11,25293,0,1,1,1,1), -- Draenethyst Wand +(@GreenTBC+11,24669,0,1,1,1,1), -- Eldr'naan Belt +(@GreenTBC+11,24670,0,1,1,1,1), -- Eldr'naan Boots +(@GreenTBC+11,24676,0,1,1,1,1), -- Eldr'naan Bracelets +(@GreenTBC+11,24672,0,1,1,1,1), -- Eldr'naan Gloves +(@GreenTBC+11,24673,0,1,1,1,1), -- Eldr'naan Hood +(@GreenTBC+11,24671,0,1,1,1,1), -- Eldr'naan Jerkin +(@GreenTBC+11,24674,0,1,1,1,1), -- Eldr'naan Pants +(@GreenTBC+11,24675,0,1,1,1,1), -- Eldr'naan Shoulderpads +(@GreenTBC+11,25069,0,1,1,1,1), -- Epidote Stone Necklace +(@GreenTBC+11,25335,0,1,1,1,1), -- Feral Warp-Staff +(@GreenTBC+11,25153,0,1,1,1,1), -- Gladiator Greatblade +(@GreenTBC+11,28542,0,1,1,1,1), -- Heartseeker Knives +(@GreenTBC+11,25111,0,1,1,1,1), -- Lionhead Dagger +(@GreenTBC+11,24781,0,1,1,1,1), -- Murkblood Belt +(@GreenTBC+11,24783,0,1,1,1,1), -- Murkblood Boots +(@GreenTBC+11,24789,0,1,1,1,1), -- Murkblood Bracers +(@GreenTBC+11,24784,0,1,1,1,1), -- Murkblood Chestpiece +(@GreenTBC+11,24786,0,1,1,1,1), -- Murkblood Cover +(@GreenTBC+11,24785,0,1,1,1,1), -- Murkblood Gloves +(@GreenTBC+11,24787,0,1,1,1,1), -- Murkblood Pants +(@GreenTBC+11,24788,0,1,1,1,1), -- Murkblood Shoulderguards +(@GreenTBC+11,25237,0,1,1,1,1), -- Nether Trident +(@GreenTBC+11,25167,0,1,1,1,1), -- Nethersteel Claymore +(@GreenTBC+11,25251,0,1,1,1,1), -- Orc Flatbow +(@GreenTBC+11,25125,0,1,1,1,1), -- Retro-Spike Club +(@GreenTBC+11,25279,0,1,1,1,1), -- Sen'jin Longrifle +(@GreenTBC+11,25307,0,1,1,1,1), -- Shadow Dagger +(@GreenTBC+11,25083,0,1,1,1,1), -- Smouldering Shield +(@GreenTBC+11,24896,0,1,1,1,1), -- Sundered Chestpiece +(@GreenTBC+11,24895,0,1,1,1,1), -- Sundered Footwraps +(@GreenTBC+11,24897,0,1,1,1,1), -- Sundered Gauntlets +(@GreenTBC+11,24898,0,1,1,1,1), -- Sundered Helmet +(@GreenTBC+11,24899,0,1,1,1,1), -- Sundered Legguards +(@GreenTBC+11,24900,0,1,1,1,1), -- Sundered Spaulders +(@GreenTBC+11,24894,0,1,1,1,1), -- Sundered Waistband +(@GreenTBC+11,25181,0,1,1,1,1), -- Tapered Staff +(@GreenTBC+11,24901,0,1,1,1,1), -- Tortured Bracer +(@GreenTBC+11,25223,0,1,1,1,1), -- Windcaller Hatchet +-- lvl 69 ilvl 117 greens (55 items) TBC +(@GreenTBC+12,25056,0,1,1,1,1), -- Almandine Ring +(@GreenTBC+12,25126,0,1,1,1,1), -- Anvilmar Hammer +(@GreenTBC+12,24677,0,1,1,1,1), -- Archmage Belt +(@GreenTBC+12,24684,0,1,1,1,1), -- Archmage Bracelets +(@GreenTBC+12,24680,0,1,1,1,1), -- Archmage Gloves +(@GreenTBC+12,24681,0,1,1,1,1), -- Archmage Headpiece +(@GreenTBC+12,24683,0,1,1,1,1), -- Archmage Mantle +(@GreenTBC+12,24682,0,1,1,1,1), -- Archmage Pants +(@GreenTBC+12,24679,0,1,1,1,1), -- Archmage Robe +(@GreenTBC+12,24678,0,1,1,1,1), -- Archmage Slippers +(@GreenTBC+12,25154,0,1,1,1,1), -- Blood Groove Blade +(@GreenTBC+12,25196,0,1,1,1,1), -- Boneshredder Claws +(@GreenTBC+12,25140,0,1,1,1,1), -- Commanding Mallet +(@GreenTBC+12,25070,0,1,1,1,1), -- Coral Beads +(@GreenTBC+12,25182,0,1,1,1,1), -- Crystal-Etched Warstaff +(@GreenTBC+12,25210,0,1,1,1,1), -- Double-Bladed Axe +(@GreenTBC+12,25294,0,1,1,1,1), -- Dragonscale Wand +(@GreenTBC+12,25252,0,1,1,1,1), -- Dream Catcher Bow +(@GreenTBC+12,28543,0,1,1,1,1), -- Dreghood Throwing Axe +(@GreenTBC+12,24791,0,1,1,1,1), -- Expedition Boots +(@GreenTBC+12,24797,0,1,1,1,1), -- Expedition Bracers +(@GreenTBC+12,24790,0,1,1,1,1), -- Expedition Girdle +(@GreenTBC+12,24793,0,1,1,1,1), -- Expedition Gloves +(@GreenTBC+12,24794,0,1,1,1,1), -- Expedition Hood +(@GreenTBC+12,24795,0,1,1,1,1), -- Expedition Pants +(@GreenTBC+12,24796,0,1,1,1,1), -- Expedition Shoulderguards +(@GreenTBC+12,24792,0,1,1,1,1), -- Expedition Tunic +(@GreenTBC+12,25112,0,1,1,1,1), -- Fel Ripper +(@GreenTBC+12,25280,0,1,1,1,1), -- Game Hunter Musket +(@GreenTBC+12,25238,0,1,1,1,1), -- Hellfire War Spear +(@GreenTBC+12,25322,0,1,1,1,1), -- Lordly Scepter +(@GreenTBC+12,25042,0,1,1,1,1), -- Nether Cloak +(@GreenTBC+12,25168,0,1,1,1,1), -- Sha'tari Longsword +(@GreenTBC+12,25014,0,1,1,1,1), -- Shattered Hand Belt +(@GreenTBC+12,25016,0,1,1,1,1), -- Shattered Hand Breastplate +(@GreenTBC+12,25020,0,1,1,1,1), -- Shattered Hand Epaulets +(@GreenTBC+12,25017,0,1,1,1,1), -- Shattered Hand Gauntlets +(@GreenTBC+12,25018,0,1,1,1,1), -- Shattered Hand Helmet +(@GreenTBC+12,25019,0,1,1,1,1), -- Shattered Hand Legplates +(@GreenTBC+12,25015,0,1,1,1,1), -- Shattered Hand Sabatons +(@GreenTBC+12,25021,0,1,1,1,1), -- Shattered Hand Vambraces +(@GreenTBC+12,25224,0,1,1,1,1), -- Slavemaster Axe +(@GreenTBC+12,25336,0,1,1,1,1), -- Splintering Greatstaff +(@GreenTBC+12,24904,0,1,1,1,1), -- Talhide Chestpiece +(@GreenTBC+12,24906,0,1,1,1,1), -- Talhide Helmet +(@GreenTBC+12,24903,0,1,1,1,1), -- Talhide Lined-Boots +(@GreenTBC+12,24909,0,1,1,1,1), -- Talhide Lined-Bracers +(@GreenTBC+12,24905,0,1,1,1,1), -- Talhide Lined-Gloves +(@GreenTBC+12,24907,0,1,1,1,1), -- Talhide Lined-Leggings +(@GreenTBC+12,24908,0,1,1,1,1), -- Talhide Shoulderguards +(@GreenTBC+12,24902,0,1,1,1,1), -- Talhide Stitched-Belt +(@GreenTBC+12,25308,0,1,1,1,1), -- Thunder Spike +(@GreenTBC+12,25098,0,1,1,1,1), -- Tuurik Torch +(@GreenTBC+12,25266,0,1,1,1,1), -- Well-Balanced Crossbow +(@GreenTBC+12,25084,0,1,1,1,1), -- Zeth'Gor Shield +-- lvl 70 ilvl 120 greens (55 items) TBC +(@GreenTBC+13,25057,0,1,1,1,1), -- Amber Band +(@GreenTBC+13,25043,0,1,1,1,1), -- Amber Cape +(@GreenTBC+13,25323,0,1,1,1,1), -- Ascendant's Scepter +(@GreenTBC+13,28544,0,1,1,1,1), -- Assassin's Shuriken +(@GreenTBC+13,25281,0,1,1,1,1), -- Big-Boar Battle Rifle +(@GreenTBC+13,25225,0,1,1,1,1), -- Deepforge Broadaxe +(@GreenTBC+13,25099,0,1,1,1,1), -- Draenei Crystal Rod +(@GreenTBC+13,24805,0,1,1,1,1), -- Dragonhawk Bands +(@GreenTBC+13,24798,0,1,1,1,1), -- Dragonhawk Belt +(@GreenTBC+13,24799,0,1,1,1,1), -- Dragonhawk Boots +(@GreenTBC+13,24801,0,1,1,1,1), -- Dragonhawk Gloves +(@GreenTBC+13,24802,0,1,1,1,1), -- Dragonhawk Hat +(@GreenTBC+13,24803,0,1,1,1,1), -- Dragonhawk Pants +(@GreenTBC+13,24804,0,1,1,1,1), -- Dragonhawk Shoulderguards +(@GreenTBC+13,24800,0,1,1,1,1), -- Dragonhawk Tunic +(@GreenTBC+13,25085,0,1,1,1,1), -- Dragonscale Shield +(@GreenTBC+13,24685,0,1,1,1,1), -- Elementalist Belt +(@GreenTBC+13,24686,0,1,1,1,1), -- Elementalist Boots +(@GreenTBC+13,24692,0,1,1,1,1), -- Elementalist Bracelets +(@GreenTBC+13,24688,0,1,1,1,1), -- Elementalist Gloves +(@GreenTBC+13,24690,0,1,1,1,1), -- Elementalist Leggings +(@GreenTBC+13,24691,0,1,1,1,1), -- Elementalist Mantle +(@GreenTBC+13,24689,0,1,1,1,1), -- Elementalist Skullcap +(@GreenTBC+13,24687,0,1,1,1,1), -- Elementalist Tunic +(@GreenTBC+13,25169,0,1,1,1,1), -- Fel Orc Brute Sword +(@GreenTBC+13,25295,0,1,1,1,1), -- Flawless Wand +(@GreenTBC+13,25141,0,1,1,1,1), -- Halaani Hammer +(@GreenTBC+13,25155,0,1,1,1,1), -- Iron Skull Sword +(@GreenTBC+13,25127,0,1,1,1,1), -- Knight's War Hammer +(@GreenTBC+13,25239,0,1,1,1,1), -- Legend's Glaive +(@GreenTBC+13,24910,0,1,1,1,1), -- Netherstorm Belt +(@GreenTBC+13,24917,0,1,1,1,1), -- Netherstorm Bracer +(@GreenTBC+13,24912,0,1,1,1,1), -- Netherstorm Chestpiece +(@GreenTBC+13,24913,0,1,1,1,1), -- Netherstorm Gauntlets +(@GreenTBC+13,24911,0,1,1,1,1), -- Netherstorm Greaves +(@GreenTBC+13,24914,0,1,1,1,1), -- Netherstorm Helm +(@GreenTBC+13,24915,0,1,1,1,1), -- Netherstorm Legguards +(@GreenTBC+13,24916,0,1,1,1,1), -- Netherstorm Shoulderguards +(@GreenTBC+13,25113,0,1,1,1,1), -- Phantom Dagger +(@GreenTBC+13,25267,0,1,1,1,1), -- Rampant Crossbow +(@GreenTBC+13,25197,0,1,1,1,1), -- Razor Scythes +(@GreenTBC+13,25211,0,1,1,1,1), -- Rockbiter Cutter +(@GreenTBC+13,25337,0,1,1,1,1), -- Swarming Sting-Staff +(@GreenTBC+13,25071,0,1,1,1,1), -- Tanzanite Pendant +(@GreenTBC+13,25183,0,1,1,1,1), -- Voodoo Hex-Staff +(@GreenTBC+13,25024,0,1,1,1,1), -- Warlord's Iron-Breastplate +(@GreenTBC+13,25028,0,1,1,1,1), -- Warlord's Iron-Epaulets +(@GreenTBC+13,25025,0,1,1,1,1), -- Warlord's Iron-Gauntlets +(@GreenTBC+13,25022,0,1,1,1,1), -- Warlord's Iron-Girdle +(@GreenTBC+13,25026,0,1,1,1,1), -- Warlord's Iron-Helm +(@GreenTBC+13,25027,0,1,1,1,1), -- Warlord's Iron-Legplates +(@GreenTBC+13,25029,0,1,1,1,1), -- Warlord's Iron-Vambraces +(@GreenTBC+13,25023,0,1,1,1,1), -- Warlord's Sabatons +(@GreenTBC+13,25309,0,1,1,1,1), -- Warpdagger +(@GreenTBC+13,25253,0,1,1,1,1); -- Windspear Longbow +-- -------------------------------------------------------- +-- TBC_Blues_References +-- -------------------------------------------------------- +SET @BlueTBC := 4200; -- reference starting value TDB Field +DELETE FROM `reference_loot_template` WHERE `entry` BETWEEN @BlueTBC AND @BlueTBC+10; +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +-- lvl 60 blues ilvl 85((6 items) +(@BlueTBC,31125,0,1,1,1,1), -- Boots of the Decimator +(@BlueTBC,31126,0,1,1,1,1), -- Gloves of Ferocity +(@BlueTBC,31127,0,1,1,1,1), -- Hauberk of Totemic Rage +(@BlueTBC,31131,0,1,1,1,1), -- Sash of Silent Blades +(@BlueTBC,31133,0,1,1,1,1), -- Leggings of Concentrated Darkness +(@BlueTBC,31134,0,1,1,1,1), -- Blade of Misfortune +-- lvl 61 blues ilvl 88 (6 items) +(@BlueTBC+1,31136,0,1,1,1,1), -- Breastplate of Blade Turning +(@BlueTBC+1,31137,0,1,1,1,1), -- Gauntlets of Purification +(@BlueTBC+1,31138,0,1,1,1,1), -- Storm Lord's Girdle +(@BlueTBC+1,31139,0,1,1,1,1), -- Fist of Reckoning +(@BlueTBC+1,31140,0,1,1,1,1), -- Cloak of Entropy +(@BlueTBC+1,31142,0,1,1,1,1), -- Blade of Trapped Knowledge +-- lvl 62 blues ilvl 91 (6 items) +(@BlueTBC+2,31143,0,1,1,1,1), -- Shroud of Frenzy +(@BlueTBC+2,31145,0,1,1,1,1), -- Headdress of the Sleeper +(@BlueTBC+2,31147,0,1,1,1,1), -- Pendant of Cunning +(@BlueTBC+2,31148,0,1,1,1,1), -- Demon Hide Spaulders +(@BlueTBC+2,31149,0,1,1,1,1), -- Gloves of Pandemonium +(@BlueTBC+2,31150,0,1,1,1,1), -- Gloves of Piety +-- lvl 63 blues ilvl 94 (6 items) +(@BlueTBC+3,31151,0,1,1,1,1), -- Girdle of Siege +(@BlueTBC+3,31152,0,1,1,1,1), -- Girdle of SiegeChestguard of Illumination +(@BlueTBC+3,31153,0,1,1,1,1), -- Girdle of SiegeAxe of the Legion +(@BlueTBC+3,31173,0,1,1,1,1), -- Girdle of SiegeBoots of Savagery +(@BlueTBC+3,31175,0,1,1,1,1), -- Girdle of SiegeBlade Dancer's Wristguards +(@BlueTBC+3,31178,0,1,1,1,1), -- Girdle of SiegeAmulet of Unstable Power +-- lvl 64 blues ilvl 97 (6 items) +(@BlueTBC+4,31180,0,1,1,1,1), -- Gauntlets of the Skullsplitter +(@BlueTBC+4,31186,0,1,1,1,1), -- Braxxis' Staff of Slumber +(@BlueTBC+4,31187,0,1,1,1,1), -- Boots of the Pathfinder +(@BlueTBC+4,31190,0,1,1,1,1), -- The Dreamer's Shoulderpads +(@BlueTBC+4,31193,0,1,1,1,1), -- Blade of Unquenched Thirst +(@BlueTBC+4,31196,0,1,1,1,1), -- Amulet of Sanctification +-- lvl 65 blues ilvl 100 (6 items) +(@BlueTBC+5,31200,0,1,1,1,1), -- Shield of the Wayward Footman +(@BlueTBC+5,31202,0,1,1,1,1), -- Girdle of Divine Blessing +(@BlueTBC+5,31204,0,1,1,1,1), -- The Gunblade +(@BlueTBC+5,31222,0,1,1,1,1), -- Headdress of Inner Rage +(@BlueTBC+5,31226,0,1,1,1,1), -- Leggings of the Sly +(@BlueTBC+5,31230,0,1,1,1,1), -- Abyss Walker's Boots +-- lvl 68 blues ilvl 109 (6 items) +(@BlueTBC+8,31284,0,1,1,1,1), -- Bracers of Recklessness +(@BlueTBC+8,31285,0,1,1,1,1), -- Chestguard of the Talon +(@BlueTBC+8,31286,0,1,1,1,1), -- Breastplate of Rapid Striking +(@BlueTBC+8,31287,0,1,1,1,1), -- Draenei Honor Guard Shield +(@BlueTBC+8,31288,0,1,1,1,1), -- The Master's Treads +(@BlueTBC+8,31289,0,1,1,1,1), -- Staff of Divine Infusion +-- lvl 69 blues ilvl 112 (6 items) +(@BlueTBC+9,31291,0,1,1,1,1), -- Crystalforged War Axe +(@BlueTBC+9,31292,0,1,1,1,1), -- Crystal Pulse Shield +(@BlueTBC+9,31293,0,1,1,1,1), -- Girdle of Gale Force +(@BlueTBC+9,31294,0,1,1,1,1), -- Pauldrons of Surging Mana +(@BlueTBC+9,31295,0,1,1,1,1), -- Chestguard of the Dark Stalker +(@BlueTBC+9,31297,0,1,1,1,1), -- Robe of the Crimson Order +-- lvl 70 blues ilvl 115 (7 items) +(@BlueTBC+10,31298,0,1,1,1,1), -- Legguards of the Shattered Hand +(@BlueTBC+10,31299,0,1,1,1,1), -- The Oathkeeper +(@BlueTBC+10,31303,0,1,1,1,1), -- Valanos' Longbow +(@BlueTBC+10,31304,0,1,1,1,1), -- The Essence Focuser +(@BlueTBC+10,31305,0,1,1,1,1), -- Ced's Carver +(@BlueTBC+10,31306,0,1,1,1,1), -- Leggings of the Sacred Crest +(@BlueTBC+10,31308,0,1,1,1,1); -- The Bringer of Death diff --git a/sql/updates/world/2012_06_02_04_world_reference_loot_template.sql b/sql/updates/world/2012_06_02_04_world_reference_loot_template.sql new file mode 100644 index 00000000000..57be9083048 --- /dev/null +++ b/sql/updates/world/2012_06_02_04_world_reference_loot_template.sql @@ -0,0 +1,11 @@ +DELETE FROM `reference_loot_template` WHERE `entry` IN (14011,14012); +INSERT INTO `reference_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +(14011,37759,0,1,1,1,1), -- Rhie-ay's Clutching Gauntlets +(14011,37768,0,1,1,1,1), -- Leggings of Violent Exsanguination +(14011,37790,0,1,1,1,1), -- Belt of Crystalline Tears +(14011,37806,0,1,1,1,1), -- Zabra's Misplaced Staff +(14011,37808,0,1,1,1,1), -- Dragonjaw Mauler +(14011,37809,0,1,1,1,1), -- Roc-Feather Longbow +(14012,3014,-70,1,0,1,1), -- Battleworn Axe +(14012,7906,-8,1,0,1,1); -- Horns of Nez'ra +UPDATE `creature_loot_template` SET `mincountOrRef`=14012 WHERE `mincountOrRef`=14011 AND `entry` IN (4464,436,437,440,485,615,4064,4065,4462,4463,435); diff --git a/sql/updates/world/2012_06_02_05_world_reference_loot_template.sql b/sql/updates/world/2012_06_02_05_world_reference_loot_template.sql new file mode 100644 index 00000000000..51dee84ad9b --- /dev/null +++ b/sql/updates/world/2012_06_02_05_world_reference_loot_template.sql @@ -0,0 +1,2 @@ +-- freaking -, im jumping from a cliff now... +UPDATE `creature_loot_template` SET `mincountOrRef`=-14012 WHERE `mincountOrRef`=-14011 AND `entry` IN (4464,436,437,440,485,615,4064,4065,4462,4463,435); diff --git a/sql/updates/world/2012_06_02_06_world_waypoints.sql b/sql/updates/world/2012_06_02_06_world_waypoints.sql new file mode 100644 index 00000000000..65d5d43bad2 --- /dev/null +++ b/sql/updates/world/2012_06_02_06_world_waypoints.sql @@ -0,0 +1,1343 @@ +-- Azure Drake +-- Delete old spawns +DELETE FROM `creature` WHERE `id` IN (27682,27608); +UPDATE `creature_template` SET `speed_walk`=9/2,`speed_run`=17/7,`InhabitType`=4 WHERE `entry`=26838; + +SET @NPC := 99078; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3433.348,274.121,192.7347,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3441.997,218.066,169.347,0,0,0,100,0), +(@PATH,2,3495.446,178.1635,169.347,0,0,0,100,0), +(@PATH,3,3562.124,172.6228,169.347,0,0,0,100,0), +(@PATH,4,3645.859,193.9786,169.347,0,0,0,100,0), +(@PATH,5,3689.068,295.8872,169.347,0,0,0,100,0), +(@PATH,6,3624.446,375.1689,169.347,0,0,0,100,0), +(@PATH,7,3510.095,372.0045,169.347,0,0,0,100,0), +(@PATH,8,3446.488,300.4381,169.347,0,0,0,100,0), +(@PATH,9,3420.008,195.1058,169.347,0,0,0,100,0), +(@PATH,10,3474.376,103.4208,169.347,0,0,0,100,0), +(@PATH,11,3587.787,78.41341,169.347,0,0,0,100,0), +(@PATH,12,3680.552,168.1343,169.347,0,0,0,100,0), +(@PATH,13,3682.222,340.8562,169.347,0,0,0,100,0), +(@PATH,14,3563.545,458.4753,169.347,0,0,0,100,0), +(@PATH,15,3452.104,480.9653,169.347,0,0,0,100,0), +(@PATH,16,3344.437,382.5979,169.347,0,0,0,100,0), +(@PATH,17,3232.114,340.6778,169.347,0,0,0,100,0), +(@PATH,18,3127.326,347.8484,169.347,0,0,0,100,0), +(@PATH,19,3027.017,384.9972,169.347,0,0,0,100,0), +(@PATH,20,2989.474,458.5701,169.347,0,0,0,100,0), +(@PATH,21,3013.37,539.2202,169.347,0,0,0,100,0), +(@PATH,22,3066.603,566.7353,169.347,0,0,0,100,0), +(@PATH,23,3134.078,551.7691,169.347,0,0,0,100,0), +(@PATH,24,3244.26,486.8306,169.347,0,0,0,100,0), +(@PATH,25,3327.64,383.2903,169.347,0,0,0,100,0), +(@PATH,26,3382.149,279.6307,169.347,0,0,0,100,0); + +SET @NPC := 99079; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3434.632,268.5218,212.5722,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3449.962,350.2704,185.3083,0,0,0,100,0), +(@PATH,2,3546.571,399.454,185.3083,0,0,0,100,0), +(@PATH,3,3649.095,344.2626,185.3083,0,0,0,100,0), +(@PATH,4,3648.6,203.3825,185.3083,0,0,0,100,0), +(@PATH,5,3557.447,156.6613,185.3083,0,0,0,100,0), +(@PATH,6,3438.763,197.2433,185.3083,0,0,0,100,0), +(@PATH,7,3364.301,251.3537,185.3083,0,0,0,100,0), +(@PATH,8,3245.05,295.2606,185.3083,0,0,0,100,0), +(@PATH,9,3127.677,330.6631,185.3083,0,0,0,100,0), +(@PATH,10,3045.42,426.6257,185.3083,0,0,0,100,0), +(@PATH,11,3033.423,500.1823,185.3083,0,0,0,100,0), +(@PATH,12,3074.555,584.5701,185.3083,0,0,0,100,0), +(@PATH,13,3167.413,579.3245,185.3083,0,0,0,100,0), +(@PATH,14,3254.766,477.3121,185.3083,0,0,0,100,0), +(@PATH,15,3328.997,355.7176,185.3083,0,0,0,100,0), +(@PATH,16,3403.051,340.1719,185.3083,0,0,0,100,0), +(@PATH,17,3446.086,384.896,185.3083,0,0,0,100,0), +(@PATH,18,3503.323,407.0888,185.3083,0,0,0,100,0), +(@PATH,19,3593.65,392.4026,185.3083,0,0,0,100,0), +(@PATH,20,3658.26,283.8229,185.3083,0,0,0,100,0), +(@PATH,21,3604.809,176.3996,185.3083,0,0,0,100,0), +(@PATH,22,3500.686,159.6379,185.3083,0,0,0,100,0), +(@PATH,23,3441.441,249.5543,185.3083,0,0,0,100,0); + +SET @NPC := 99083; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3639.789,321.911,195.744,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3654.995,228.2284,204.7075,0,0,0,100,0), +(@PATH,2,3750.065,190.3719,204.7075,0,0,0,100,0), +(@PATH,3,3793.781,239.5784,204.7075,0,0,0,100,0), +(@PATH,4,3793.007,322.9862,204.7075,0,0,0,100,0), +(@PATH,5,3712.435,337.7213,204.7075,0,0,0,100,0), +(@PATH,6,3649.212,273.7653,204.7075,0,0,0,100,0), +(@PATH,7,3627.809,181.2728,204.7075,0,0,0,100,0), +(@PATH,8,3575.202,116.1518,204.7075,0,0,0,100,0), +(@PATH,9,3452.9,157.833,204.7075,0,0,0,100,0), +(@PATH,10,3395.156,279.1096,204.7075,0,0,0,100,0), +(@PATH,11,3459.034,403.4866,204.7075,0,0,0,100,0), +(@PATH,12,3610.543,437.9186,204.7075,0,0,0,100,0), +(@PATH,13,3715.638,355.6098,204.7075,0,0,0,100,0), +(@PATH,14,3721.246,203.5534,204.7075,0,0,0,100,0), +(@PATH,15,3583.16,147.8227,204.7075,0,0,0,100,0), +(@PATH,16,3467.958,184.451,204.7075,0,0,0,100,0), +(@PATH,17,3341.041,241.3563,204.7075,0,0,0,100,0), +(@PATH,18,3259.652,326.3573,204.7075,0,0,0,100,0), +(@PATH,19,3325.962,453.1619,204.7075,0,0,0,100,0), +(@PATH,20,3430.271,470.1731,204.7075,0,0,0,100,0), +(@PATH,21,3474.818,389.2108,204.7075,0,0,0,100,0), +(@PATH,22,3422.128,277.9353,204.7075,0,0,0,100,0), +(@PATH,23,3278.513,235.3488,204.7075,0,0,0,100,0), +(@PATH,24,3139.333,309.1593,204.7075,0,0,0,100,0), +(@PATH,25,3124.315,442.8726,204.7075,0,0,0,100,0), +(@PATH,26,3166.636,500.1602,204.7075,0,0,0,100,0), +(@PATH,27,3252.777,537.1607,204.7075,0,0,0,100,0), +(@PATH,28,3365.404,500.6408,204.7075,0,0,0,100,0), +(@PATH,29,3497.347,437.8124,204.7075,0,0,0,100,0), +(@PATH,30,3610.069,345.1742,204.7075,0,0,0,100,0); + +SET @NPC := 99084; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3419.562,219.4669,185.8007,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3476.15,177.9767,151.9461,0,0,0,100,0), +(@PATH,2,3545.193,113.4851,151.9461,0,0,0,100,0), +(@PATH,3,3639.261,157.7231,151.9461,0,0,0,100,0), +(@PATH,4,3676.142,330.9362,151.9461,0,0,0,100,0), +(@PATH,5,3568.025,452.4464,151.9461,0,0,0,100,0), +(@PATH,6,3440.924,381.5191,151.9461,0,0,0,100,0), +(@PATH,7,3406.76,247.0661,151.9461,0,0,0,100,0), +(@PATH,8,3489.703,142.3122,151.9461,0,0,0,100,0), +(@PATH,9,3573.337,130.2329,151.9461,0,0,0,100,0), +(@PATH,10,3668.767,202.5275,151.9461,0,0,0,100,0), +(@PATH,11,3660.667,365.0258,151.9461,0,0,0,100,0), +(@PATH,12,3546.228,441.4885,151.9461,0,0,0,100,0), +(@PATH,13,3414.354,479.1683,151.9461,0,0,0,100,0), +(@PATH,14,3298.711,513.6075,151.9461,0,0,0,100,0), +(@PATH,15,3152.929,563.3295,151.9461,0,0,0,100,0), +(@PATH,16,3061.01,598.1893,151.9461,0,0,0,100,0), +(@PATH,17,3028.564,548.2512,151.9461,0,0,0,100,0), +(@PATH,18,3066.851,499.9897,151.9461,0,0,0,100,0), +(@PATH,19,3126.102,457.3964,151.9461,0,0,0,100,0), +(@PATH,20,3209.258,379.5157,151.9461,0,0,0,100,0), +(@PATH,21,3290.067,313.6936,151.9461,0,0,0,100,0), +(@PATH,22,3381.995,245.4414,151.9461,0,0,0,100,0); + +SET @NPC := 99085; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3431.814,203.5959,199.4538,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3469.755,211.1012,252.1057,0,0,0,100,0), +(@PATH,2,3543.436,184.6182,282.9112,0,0,0,100,0), +(@PATH,3,3605.144,211.1016,313.2445,0,0,0,100,0), +(@PATH,4,3629.088,281.4026,342.355,0,0,0,100,0), +(@PATH,5,3586.889,335.8259,342.355,0,0,0,100,0), +(@PATH,6,3534.959,340.7828,342.355,0,0,0,100,0), +(@PATH,7,3488.181,299.2897,342.355,0,0,0,100,0), +(@PATH,8,3490.962,242.9244,342.355,0,0,0,100,0), +(@PATH,9,3544.176,216.1916,342.355,0,0,0,100,0), +(@PATH,10,3607.393,238.2059,342.355,0,0,0,100,0), +(@PATH,11,3606.415,315.159,342.355,0,0,0,100,0), +(@PATH,12,3529.92,347.5442,342.355,0,0,0,100,0), +(@PATH,13,3442.581,379.9305,309.9662,0,0,0,100,0), +(@PATH,14,3363.314,409.6005,272.7996,0,0,0,100,0), +(@PATH,15,3271.624,451.7768,231.7996,0,0,0,100,0), +(@PATH,16,3222.875,508.5536,210.5774,0,0,0,100,0), +(@PATH,17,3178.339,552.9731,195.4663,0,0,0,100,0), +(@PATH,18,3119.579,592.5015,182.2996,0,0,0,100,0), +(@PATH,19,3079.527,558.9856,175.383,0,0,0,100,0), +(@PATH,20,3110.969,495.2063,173.9941,0,0,0,100,0), +(@PATH,21,3133.366,466.6834,176.5779,0,0,0,100,0), +(@PATH,22,3236.847,383.9943,176.5779,0,0,0,100,0), +(@PATH,23,3382.743,269.2179,222.0501,0,0,0,100,0); + +SET @NPC := 99086; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3408.915,276.3928,180.561,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3451.428,175.6206,154.7629,0,0,0,100,0), +(@PATH,2,3461.289,67.8521,154.7629,0,0,0,100,0), +(@PATH,3,3401.216,31.08062,154.7629,0,0,0,100,0), +(@PATH,4,3348.744,62.37424,154.7629,0,0,0,100,0), +(@PATH,5,3352.888,148.2122,154.7629,0,0,0,100,0), +(@PATH,6,3405.2,335.0623,154.7629,0,0,0,100,0), +(@PATH,7,3399.393,397.5138,154.7629,0,0,0,100,0), +(@PATH,8,3346.986,426.0631,154.7629,0,0,0,100,0), +(@PATH,9,3262.085,383.6502,154.7629,0,0,0,100,0), +(@PATH,10,3156.926,352.7438,154.7629,0,0,0,100,0), +(@PATH,11,3057.544,393.0464,154.7629,0,0,0,100,0), +(@PATH,12,3000.647,466.7132,154.7629,0,0,0,100,0), +(@PATH,13,2989.147,516.5572,154.7629,0,0,0,100,0), +(@PATH,14,3049.945,587.7933,154.7629,0,0,0,100,0), +(@PATH,15,3160.802,556.4007,154.7629,0,0,0,100,0), +(@PATH,16,3268.329,422.1047,154.7629,0,0,0,100,0); + +SET @NPC := 99087; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3748.954,236.7544,178.6408,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3712.221,418.183,178.6408,0,0,0,100,0), +(@PATH,2,3540.502,499.2345,178.6408,0,0,0,100,0), +(@PATH,3,3358.373,445.1452,178.6408,0,0,0,100,0), +(@PATH,4,3200.13,472.7363,178.6408,0,0,0,100,0), +(@PATH,5,3101.38,584.3835,178.6408,0,0,0,100,0), +(@PATH,6,3040.255,596.7429,178.6408,0,0,0,100,0), +(@PATH,7,2997.37,550.3453,178.6408,0,0,0,100,0), +(@PATH,8,2999.847,500.0373,178.6408,0,0,0,100,0), +(@PATH,9,3048.254,460.723,178.6408,0,0,0,100,0), +(@PATH,10,3140.818,390.9225,178.6408,0,0,0,100,0), +(@PATH,11,3219.294,333.4928,178.6408,0,0,0,100,0), +(@PATH,12,3318.04,264.8529,178.6408,0,0,0,100,0), +(@PATH,13,3436.765,193.0778,178.6408,0,0,0,100,0), +(@PATH,14,3552.843,154.3912,178.6408,0,0,0,100,0), +(@PATH,15,3668.381,197.8079,178.6408,0,0,0,100,0), +(@PATH,16,3711.96,284.6768,178.6408,0,0,0,100,0), +(@PATH,17,3627.375,410.4442,178.6408,0,0,0,100,0), +(@PATH,18,3466.029,404.0347,178.6408,0,0,0,100,0), +(@PATH,19,3375.764,293.2045,178.6408,0,0,0,100,0), +(@PATH,20,3426.16,142.911,178.6408,0,0,0,100,0), +(@PATH,21,3611.036,90.26421,178.6408,0,0,0,100,0), +(@PATH,22,3748.954,236.7544,178.6408,0,0,0,100,0); + + +SET @NPC := 99088; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3412.463,216.0972,212.123,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3412.65,215.8015,241.2928,0,0,0,100,0), +(@PATH,2,3544.712,83.40093,241.2928,0,0,0,100,0), +(@PATH,3,3729.527,148.4322,241.2928,0,0,0,100,0), +(@PATH,4,3770.91,456.7697,241.2928,0,0,0,100,0), +(@PATH,5,3592.973,601.0773,241.2928,0,0,0,100,0), +(@PATH,6,3431.349,566.7643,241.2928,0,0,0,100,0), +(@PATH,7,3298.04,548.691,241.2928,0,0,0,100,0), +(@PATH,8,3180.431,663.6898,241.2928,0,0,0,100,0), +(@PATH,9,3069.867,677.9128,241.2928,0,0,0,100,0), +(@PATH,10,2984.272,605.6987,241.2928,0,0,0,100,0), +(@PATH,11,3000.096,533.4483,241.2928,0,0,0,100,0), +(@PATH,12,3144.4,405.446,241.2928,0,0,0,100,0), +(@PATH,13,3301.554,308.331,241.2928,0,0,0,100,0); + +SET @NPC := 99089; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3100.95,567.1441,118.4118,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3100.912,567.1385,122.3331,0,0,0,100,0), +(@PATH,2,3214.064,524.5076,122.3331,0,0,0,100,0), +(@PATH,3,3307.77,498.1685,122.3331,0,0,0,100,0), +(@PATH,4,3399.335,473.5195,122.3331,0,0,0,100,0), +(@PATH,5,3545.675,446.1954,122.3331,0,0,0,100,0), +(@PATH,6,3631.807,357.087,122.3331,0,0,0,100,0), +(@PATH,7,3640.708,229.0423,122.3331,0,0,0,100,0), +(@PATH,8,3616.36,137.7545,122.3331,0,0,0,100,0), +(@PATH,9,3558.458,113.3069,122.3331,0,0,0,100,0), +(@PATH,10,3457.288,142.8311,122.3331,0,0,0,100,0), +(@PATH,11,3387.124,248.1035,122.3331,0,0,0,100,0), +(@PATH,12,3419.464,398.1638,122.3331,0,0,0,100,0), +(@PATH,13,3366.308,507.4259,122.3331,0,0,0,100,0), +(@PATH,14,3243.456,494.2254,122.3331,0,0,0,100,0), +(@PATH,15,3121.018,428.1757,122.3331,0,0,0,100,0), +(@PATH,16,3003.428,487.8239,122.3331,0,0,0,100,0), +(@PATH,17,3001.53,566.4896,122.3331,0,0,0,100,0), +(@PATH,18,3059.883,577.261,122.3331,0,0,0,100,0); + +-- static +DELETE FROM `creature` WHERE `guid` IN (99090,99091); +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(99090,27682,571,1,1,24743,0,2954.845,625.8646,146.2928,2.094395,120,0,0,38440,0,0), +(99091,27682,571,1,1,24743,0,3256.357,585.8403,136.8419,0.4363323,120,0,0,38440,0,0); + +-- waypoints +SET @NPC := 99092; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3017.465,301.0079,204.943,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3014.38,371.552,204.943,0,0,0,100,0), +(@PATH,2,3066.132,433.5229,204.943,0,0,0,100,0), +(@PATH,3,3168.017,532.116,204.943,0,0,0,100,0), +(@PATH,4,3341.228,644.3932,204.943,0,0,0,100,0), +(@PATH,5,3480.533,600.2273,204.943,0,0,0,100,0), +(@PATH,6,3485.514,465.1431,204.943,0,0,0,100,0), +(@PATH,7,3362.191,369.4394,204.943,0,0,0,100,0), +(@PATH,8,3193.452,330.4968,204.943,0,0,0,100,0), +(@PATH,9,3117.152,256.1553,204.943,0,0,0,100,0), +(@PATH,10,3017.465,301.0079,204.943,0,0,0,100,0); + +SET @NPC := 99094; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3138.133,520.6823,53.44044,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3120.694,487.4651,73.32948,0,0,0,100,0), +(@PATH,2,3094.569,488.8283,89.30162,0,0,0,100,0), +(@PATH,3,3076.394,504.3694,101.9128,0,0,0,100,0), +(@PATH,4,3073.121,536.1434,118.3021,0,0,0,100,0), +(@PATH,5,3100.686,550.8791,135.0522,0,0,0,100,0), +(@PATH,6,3133.567,533.2503,156.4133,0,0,0,100,0), +(@PATH,7,3128.940,498.2000,185.3022,0,0,0,100,0), +(@PATH,8,3104.875,485.1591,211.9410,0,0,0,100,0), +(@PATH,9,3078.965,493.2044,233.2187,0,0,0,100,0), +(@PATH,10,3077.378,529.8601,246.1916,0,0,0,100,0), +(@PATH,11,3104.640,532.739,246.1916,0,0,0,100,0), +(@PATH,12,3124.398,511.3354,246.1916,0,0,0,100,0), +(@PATH,13,3106.461,485.7477,246.1916,0,0,0,100,0), +(@PATH,14,3074.75,501.1113,246.1916,0,0,0,100,0), +(@PATH,15,3080.605,533.5042,222.6366,0,0,0,100,0), +(@PATH,16,3108.456,548.174,194.8869,0,0,0,100,0), +(@PATH,17,3138.865,510.0685,159.4426,0,0,0,100,0), +(@PATH,18,3107.084,484.058,121.3038,0,0,0,100,0), +(@PATH,19,3066.059,511.5332,94.97042,0,0,0,100,0), +(@PATH,20,3084.679,555.8902,74.52598,0,0,0,100,0), +(@PATH,21,3128.865,543.4575,51.55369,0,0,0,100,0), +(@PATH,22,3132.671,497.0408,51.55369,0,0,0,100,0), +(@PATH,23,3083.713,484.3025,51.55369,0,0,0,100,0), +(@PATH,24,3062.465,530.1815,51.55369,0,0,0,100,0), +(@PATH,25,3100.407,561.9063,51.55369,0,0,0,100,0), +(@PATH,26,3138.133,520.6823,53.44044,0,0,0,100,0); + +SET @NPC := 99095; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3199.019,490.8836,212.5729,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3131.874,451.6094,212.5729,0,0,0,100,0), +(@PATH,2,3066.175,466.9917,212.5729,0,0,0,100,0), +(@PATH,3,3015.529,515.9183,212.5729,0,0,0,100,0), +(@PATH,4,3032.398,624.4706,212.5729,0,0,0,100,0), +(@PATH,5,3123.448,648.5508,212.5729,0,0,0,100,0), +(@PATH,6,3201.826,572.715,212.5729,0,0,0,100,0), +(@PATH,7,3199.019,490.8836,212.5729,0,0,0,100,0); + +SET @NPC := 99096; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3214.422,579.9131,196.0033,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3133.856,625.1009,196.0033,0,0,0,100,0), +(@PATH,2,3066.991,599.8026,196.0033,0,0,0,100,0), +(@PATH,3,3045.829,536.076,196.0033,0,0,0,100,0), +(@PATH,4,3064.8,436.205,196.0033,0,0,0,100,0), +(@PATH,5,3149.34,424.2586,196.0033,0,0,0,100,0), +(@PATH,6,3217.921,481.3083,196.0033,0,0,0,100,0), +(@PATH,7,3214.422,579.9131,196.0033,0,0,0,100,0); + +SET @NPC := 99097; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3106.429,348.3322,212.4711,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3184.002,431.2766,212.4711,0,0,0,100,0), +(@PATH,2,3166.134,532.8875,212.4711,0,0,0,100,0), +(@PATH,3,3080.641,574.7059,212.4711,0,0,0,100,0), +(@PATH,4,2963.504,564.834,212.4711,0,0,0,100,0), +(@PATH,5,2918.588,502.0504,212.4711,0,0,0,100,0), +(@PATH,6,2949.235,405.6514,212.4711,0,0,0,100,0), +(@PATH,7,3106.429,348.3322,212.4711,0,0,0,100,0); + +SET @NPC := 99098; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3129.027,582.4556,247.3863,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3188.686,528.622,247.3863,0,0,0,100,0), +(@PATH,2,3166.479,466.4643,247.3863,0,0,0,100,0), +(@PATH,3,3107.782,429.4197,247.3863,0,0,0,100,0), +(@PATH,4,3030.916,459.3344,247.3863,0,0,0,100,0), +(@PATH,5,3014.312,531.3731,247.3863,0,0,0,100,0), +(@PATH,6,3058.55,581.8262,247.3863,0,0,0,100,0), +(@PATH,7,3129.027,582.4556,247.3863,0,0,0,100,0); + +SET @NPC := 99099; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3691.676,352.0933,342.2254,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3662.692,328.2304,338.4197,0,0,0,100,0), +(@PATH,2,3648.806,293.8063,321.0587,0,0,0,100,0), +(@PATH,3,3677.441,213.8859,320.1976,0,0,0,100,0), +(@PATH,4,3615.31,209.5691,324.1698,0,0,0,100,0), +(@PATH,5,3637.643,254.0089,332.7251,0,0,0,100,0), +(@PATH,6,3699.886,260.6509,327.8641,0,0,0,100,0), +(@PATH,7,3720.373,308.941,337.7808,0,0,0,100,0), +(@PATH,8,3691.676,352.0933,342.2254,0,0,0,100,0); + +SET @NPC := 99093; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3036.494,602.2036,179.671,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3100.145,600.0773,179.671,0,0,0,100,0), +(@PATH,2,3230.972,531.9783,179.671,0,0,0,100,0), +(@PATH,3,3261.28,445.4492,179.671,0,0,0,100,0), +(@PATH,4,3185.334,349.6381,179.671,0,0,0,100,0), +(@PATH,5,3031.361,375.153,179.671,0,0,0,100,0), +(@PATH,6,2951.565,490.5297,179.671,0,0,0,100,0), +(@PATH,7,3006.273,602.823,179.671,0,0,0,100,0), +(@PATH,8,3140.882,604.8052,179.671,0,0,0,100,0), +(@PATH,9,3279.177,536.7864,179.671,0,0,0,100,0), +(@PATH,10,3342.035,451.1805,179.671,0,0,0,100,0), +(@PATH,11,3373.871,409.5802,179.671,0,0,0,100,0), +(@PATH,12,3418.399,323.2935,179.671,0,0,0,100,0), +(@PATH,13,3432.266,253.5685,179.671,0,0,0,100,0), +(@PATH,14,3376.006,177.8496,179.671,0,0,0,100,0), +(@PATH,15,3328.437,226.3789,179.671,0,0,0,100,0), +(@PATH,16,3336.244,307.4113,179.671,0,0,0,100,0), +(@PATH,17,3381.182,333.7066,179.671,0,0,0,100,0), +(@PATH,18,3478.52,398.1222,179.671,0,0,0,100,0), +(@PATH,19,3574.011,383.5956,179.671,0,0,0,100,0), +(@PATH,20,3661.792,400.2125,179.671,0,0,0,100,0), +(@PATH,21,3700.764,494.1714,179.671,0,0,0,100,0), +(@PATH,22,3602.784,552.9866,179.671,0,0,0,100,0), +(@PATH,23,3539.342,521.9033,179.671,0,0,0,100,0), +(@PATH,24,3523.356,456.0128,179.671,0,0,0,100,0), +(@PATH,25,3618.041,362.6289,179.671,0,0,0,100,0), +(@PATH,26,3723.684,327.7586,179.671,0,0,0,100,0), +(@PATH,27,3773.446,249.6754,179.671,0,0,0,100,0), +(@PATH,28,3749.611,152.5128,179.671,0,0,0,100,0), +(@PATH,29,3695.312,141.0493,179.671,0,0,0,100,0), +(@PATH,30,3651.431,217.0924,179.671,0,0,0,100,0), +(@PATH,31,3683.438,319.0038,179.671,0,0,0,100,0), +(@PATH,32,3748.601,338.1269,179.671,0,0,0,100,0), +(@PATH,33,3792.042,245.4839,179.671,0,0,0,100,0), +(@PATH,34,3735.548,180.4323,179.671,0,0,0,100,0), +(@PATH,35,3618.281,171.1228,179.671,0,0,0,100,0), +(@PATH,36,3474.684,137.1242,179.671,0,0,0,100,0), +(@PATH,37,3479.782,49.90799,179.671,0,0,0,100,0), +(@PATH,38,3558.278,30.76975,179.671,0,0,0,100,0), +(@PATH,39,3629.689,60.77876,179.671,0,0,0,100,0), +(@PATH,40,3630.145,127.0798,179.671,0,0,0,100,0), +(@PATH,41,3490.695,175.1472,179.671,0,0,0,100,0), +(@PATH,42,3366.718,224.9415,179.671,0,0,0,100,0), +(@PATH,43,3212.591,294.8876,179.671,0,0,0,100,0), +(@PATH,44,3076.071,364.5977,179.671,0,0,0,100,0), +(@PATH,45,2990.75,457.3708,179.671,0,0,0,100,0), +(@PATH,46,2984.907,530.0489,179.671,0,0,0,100,0), +(@PATH,47,3036.494,602.2036,179.671,0,0,0,100,0); + +SET @NPC := 99103; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3065.57,646.0688,229.7383,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3133.651,599.4818,229.7383,0,0,0,100,0), +(@PATH,2,3196.173,510.7455,229.7383,0,0,0,100,0), +(@PATH,3,3310.401,346.2189,229.7383,0,0,0,100,0), +(@PATH,4,3407.27,144.2138,229.7383,0,0,0,100,0), +(@PATH,5,3526.717,72.89225,229.7383,0,0,0,100,0), +(@PATH,6,3672.079,141.219,229.7383,0,0,0,100,0), +(@PATH,7,3713.506,314.0188,229.7383,0,0,0,100,0), +(@PATH,8,3602.6,431.6985,229.7383,0,0,0,100,0), +(@PATH,9,3408.532,364.4567,229.7383,0,0,0,100,0), +(@PATH,10,3217.656,309.1964,229.7383,0,0,0,100,0), +(@PATH,11,3061.193,324.0175,229.7383,0,0,0,100,0), +(@PATH,12,2959.836,412.4154,229.7383,0,0,0,100,0), +(@PATH,13,2945.925,545.2357,229.7383,0,0,0,100,0), +(@PATH,14,3065.57,646.0688,229.7383,0,0,0,100,0); + +SET @NPC := 99104; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3112.661,560.2861,197.5214,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3166.947,533.783,197.5214,0,0,0,100,0), +(@PATH,2,3204.218,503.2988,197.5214,0,0,0,100,0), +(@PATH,3,3258.251,466.3165,197.5214,0,0,0,100,0), +(@PATH,4,3367.959,364.4092,197.5214,0,0,0,100,0), +(@PATH,5,3407.955,305.4363,197.5214,0,0,0,100,0), +(@PATH,6,3451.267,201.594,197.5214,0,0,0,100,0), +(@PATH,7,3508.874,166.8426,197.5214,0,0,0,100,0), +(@PATH,8,3633.496,151.127,197.5214,0,0,0,100,0), +(@PATH,9,3678.77,73.99848,197.5214,0,0,0,100,0), +(@PATH,10,3653.132,23.86263,197.5214,0,0,0,100,0), +(@PATH,11,3582.038,62.69965,197.5214,0,0,0,100,0), +(@PATH,12,3586.156,134.1242,197.5214,0,0,0,100,0), +(@PATH,13,3645.95,187.412,197.5214,0,0,0,100,0), +(@PATH,14,3699.768,345.5867,197.5214,0,0,0,100,0), +(@PATH,15,3755.733,466.6079,197.5214,0,0,0,100,0), +(@PATH,16,3695.944,599.8013,197.5214,0,0,0,100,0), +(@PATH,17,3631.838,570.2178,197.5214,0,0,0,100,0), +(@PATH,18,3620.732,470.3869,197.5214,0,0,0,100,0), +(@PATH,19,3653.033,441.836,197.5214,0,0,0,100,0), +(@PATH,20,3726.417,408.7439,197.5214,0,0,0,100,0), +(@PATH,21,3768.67,340.4243,197.5214,0,0,0,100,0), +(@PATH,22,3734.631,281.2856,197.5214,0,0,0,100,0), +(@PATH,23,3670.002,288.5108,197.5214,0,0,0,100,0), +(@PATH,24,3637.37,399.2112,197.5214,0,0,0,100,0), +(@PATH,25,3572.382,439.8372,197.5214,0,0,0,100,0), +(@PATH,26,3485.629,383.2211,197.5214,0,0,0,100,0), +(@PATH,27,3408.692,361.6136,197.5214,0,0,0,100,0), +(@PATH,28,3363.01,438.3368,197.5214,0,0,0,100,0), +(@PATH,29,3435.608,478.5367,197.5214,0,0,0,100,0), +(@PATH,30,3498.484,443.0669,197.5214,0,0,0,100,0), +(@PATH,31,3470.396,344.2875,197.5214,0,0,0,100,0), +(@PATH,32,3372.963,191.8817,197.5214,0,0,0,100,0), +(@PATH,33,3290.335,164.9094,197.5214,0,0,0,100,0), +(@PATH,34,3226.219,218.6132,197.5214,0,0,0,100,0), +(@PATH,35,3232.448,290.6222,197.5214,0,0,0,100,0), +(@PATH,36,3304.077,350.0902,197.5214,0,0,0,100,0), +(@PATH,37,3418.385,307.068,197.5214,0,0,0,100,0), +(@PATH,38,3440.642,196.0552,197.5214,0,0,0,100,0), +(@PATH,39,3388.76,137.5194,197.5214,0,0,0,100,0), +(@PATH,40,3299.691,166.3526,197.5214,0,0,0,100,0), +(@PATH,41,3197.989,286.0815,197.5214,0,0,0,100,0), +(@PATH,42,3124.057,342.0608,197.5214,0,0,0,100,0), +(@PATH,43,3029.794,412.821,197.5214,0,0,0,100,0), +(@PATH,44,3027.204,518.2308,197.5214,0,0,0,100,0), +(@PATH,45,3112.661,560.2861,197.5214,0,0,0,100,0); + +SET @NPC := 99105; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27682,571,1,1,24743,0,3040.376,545.7573,223.7107,1.91463,120,0,0,38440,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3066.4,533.701,223.7107,0,0,0,100,0), +(@PATH,2,3184.873,458.7727,223.7107,0,0,0,100,0), +(@PATH,3,3308.346,361.982,223.7107,0,0,0,100,0), +(@PATH,4,3472.517,346.546,223.7107,0,0,0,100,0), +(@PATH,5,3580.564,383.8688,223.7107,0,0,0,100,0), +(@PATH,6,3656.45,349.4831,223.7107,0,0,0,100,0), +(@PATH,7,3671.57,291.0071,223.7107,0,0,0,100,0), +(@PATH,8,3637.499,197.3902,223.7107,0,0,0,100,0), +(@PATH,9,3527.828,157.279,223.7107,0,0,0,100,0), +(@PATH,10,3449.215,208.4113,223.7107,0,0,0,100,0), +(@PATH,11,3406.054,178.4773,223.7107,0,0,0,100,0), +(@PATH,12,3456.503,129.8825,223.7107,0,0,0,100,0), +(@PATH,13,3570.421,124.2369,223.7107,0,0,0,100,0), +(@PATH,14,3636.482,214.1168,223.7107,0,0,0,100,0), +(@PATH,15,3649.198,312.7206,223.7107,0,0,0,100,0), +(@PATH,16,3584.864,367.9254,223.7107,0,0,0,100,0), +(@PATH,17,3498.865,377.1867,223.7107,0,0,0,100,0), +(@PATH,18,3446.663,323.5181,223.7107,0,0,0,100,0), +(@PATH,19,3418.987,266.998,223.7107,0,0,0,100,0), +(@PATH,20,3325.219,278.7927,223.7107,0,0,0,100,0), +(@PATH,21,3246.293,325.4047,223.7107,0,0,0,100,0), +(@PATH,22,3136.991,394.2709,223.7107,0,0,0,100,0), +(@PATH,23,3057.987,457.7468,223.7107,0,0,0,100,0), +(@PATH,24,3007.479,511.7082,223.7107,0,0,0,100,0), +(@PATH,25,3012.345,538.7167,223.7107,0,0,0,100,0), +(@PATH,26,3040.376,545.7573,223.7107,0,0,0,100,0); + +-- Azure Dragon +UPDATE `creature_template` SET `speed_walk`=7/2,`speed_run`=15/7,`InhabitType`=4 WHERE `entry`=27608; + +SET @NPC := 99105; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3177.857,623.9463,234.0692,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3062.52,435.5133,234.0692,0,0,0,100,0), +(@PATH,2,3125.572,288.5948,234.0692,0,0,0,100,0), +(@PATH,3,3411.13,158.2311,234.0692,0,0,0,100,0), +(@PATH,4,3681.013,161.0803,234.0692,0,0,0,100,0), +(@PATH,5,3815.275,311.0847,234.0692,0,0,0,100,0), +(@PATH,6,3773.807,472.041,234.0692,0,0,0,100,0), +(@PATH,7,3576.037,531.0521,234.0692,0,0,0,100,0), +(@PATH,8,3435.667,344.3725,234.0692,0,0,0,100,0), +(@PATH,9,3480.011,109.5501,234.0692,0,0,0,100,0), +(@PATH,10,3702.724,-30.66547,234.0692,0,0,0,100,0), +(@PATH,11,3889.816,54.52344,234.0692,0,0,0,100,0), +(@PATH,12,3914.841,319.0804,234.0692,0,0,0,100,0), +(@PATH,13,3695.273,610.4755,234.0692,0,0,0,100,0), +(@PATH,14,3389.431,691.5984,234.0692,0,0,0,100,0), +(@PATH,15,3177.857,623.9463,234.0692,0,0,0,100,0); + +SET @NPC := 99106; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,2980.341,629.1049,218.5251,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3128.300,641.3470,218.5251,0,0,0,100,0), +(@PATH,2,3231.236,534.2712,218.5251,0,0,0,100,0), +(@PATH,3,3229.198,417.0781,218.5251,0,0,0,100,0), +(@PATH,4,3131.435,332.9997,218.5251,0,0,0,100,0), +(@PATH,5,2990.912,336.3741,206.4763,0,0,0,100,0), +(@PATH,6,2871.583,422.1004,206.4763,0,0,0,100,0), +(@PATH,7,2881.663,578.8079,206.4763,0,0,0,100,0), +(@PATH,8,2980.341,629.1049,218.5251,0,0,0,100,0); + +SET @NPC := 99107; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3488.651,-5.619141,169.4104,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3338.837,206.9924,169.4104,0,0,0,100,0), +(@PATH,2,3077.402,282.2865,169.4104,0,0,0,100,0), +(@PATH,3,2799.517,249.9982,169.4104,0,0,0,100,0), +(@PATH,4,2641.98,389.0734,169.4104,0,0,0,100,0), +(@PATH,5,2739.034,565.4708,169.4104,0,0,0,100,0), +(@PATH,6,3044.569,485.4482,169.4104,0,0,0,100,0), +(@PATH,7,3169.199,460.6385,169.4104,0,0,0,100,0), +(@PATH,8,3336.106,465.7545,169.4104,0,0,0,100,0), +(@PATH,9,3630.246,386.4513,169.4104,0,0,0,100,0), +(@PATH,10,3803.202,250.7272,169.4104,0,0,0,100,0), +(@PATH,11,3770.406,24.9643,169.4104,0,0,0,100,0), +(@PATH,12,3488.651,-5.619141,169.4104,0,0,0,100,0); + +SET @NPC := 99108; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3542.247,134.1484,169.6936,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3506.288,141.7649,169.6936,0,0,0,100,0), +(@PATH,2,3378.177,251.381,169.6936,0,0,0,100,0), +(@PATH,3,3448.559,417.0887,169.6936,0,0,0,100,0), +(@PATH,4,3659.633,429.129,169.6936,0,0,0,100,0), +(@PATH,5,3726.806,236.8274,169.6936,0,0,0,100,0), +(@PATH,6,3554.261,69.58746,169.6936,0,0,0,100,0), +(@PATH,7,3337.373,175.2911,169.6936,0,0,0,100,0), +(@PATH,8,3292.872,421.84,169.6936,0,0,0,100,0), +(@PATH,9,3355.351,609.4697,169.6936,0,0,0,100,0), +(@PATH,10,3233.689,777.6954,207.249,0,0,0,100,0), +(@PATH,11,3049.014,721.6703,224.4991,0,0,0,100,0), +(@PATH,12,3044.268,566.5984,169.6936,0,0,0,100,0), +(@PATH,13,3142.397,481.2142,169.6936,0,0,0,100,0), +(@PATH,14,3328.336,435.8111,169.6936,0,0,0,100,0), +(@PATH,15,3583.232,539.7742,169.6936,0,0,0,100,0), +(@PATH,16,3799.81,460.638,169.6936,0,0,0,100,0), +(@PATH,17,3717.946,244.38,169.6936,0,0,0,100,0), +(@PATH,18,3542.247,134.1484,169.6936,0,0,0,100,0); + +SET @NPC := 99109; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3590.88,69.88932,149.1064,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3349.674,233.3671,149.1064,0,0,0,100,0), +(@PATH,2,3050.534,331.2801,149.1064,0,0,0,100,0), +(@PATH,3,2982.76,530.9803,149.1064,0,0,0,100,0), +(@PATH,4,3091.488,621.5792,149.1064,0,0,0,100,0), +(@PATH,5,3227.927,595.5925,149.1064,0,0,0,100,0), +(@PATH,6,3467.181,481.7014,149.1064,0,0,0,100,0), +(@PATH,7,3708.623,396.748,149.1064,0,0,0,100,0), +(@PATH,8,3763.585,194.9491,149.1064,0,0,0,100,0), +(@PATH,9,3590.88,69.88932,149.1064,0,0,0,100,0); + +SET @NPC := 99110; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3424.549,257.6351,132.4231,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3523.625,148.6501,132.4231,0,0,0,100,0), +(@PATH,2,3671.965,176.3331,132.4231,0,0,0,100,0), +(@PATH,3,3721.304,302.0294,132.4231,0,0,0,100,0), +(@PATH,4,3586.378,436.0151,132.4231,0,0,0,100,0), +(@PATH,5,3398.783,363.715,132.4231,0,0,0,100,0), +(@PATH,6,3201.002,184.2853,132.4231,0,0,0,100,0), +(@PATH,7,3033.273,261.4108,132.4231,0,0,0,100,0), +(@PATH,8,3020.73,417.366,132.4231,0,0,0,100,0), +(@PATH,9,3134.54,559.4572,132.4231,0,0,0,100,0), +(@PATH,10,3286.472,590.3685,132.4231,0,0,0,100,0), +(@PATH,11,3370.537,476.4369,132.4231,0,0,0,100,0), +(@PATH,12,3424.549,257.6351,132.4231,0,0,0,100,0); + +SET @NPC := 99111; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3485.543,172.4427,356.9669,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3617.296,247.1156,357.3557,0,0,0,100,0), +(@PATH,2,3589.83,487.236,356.9669,0,0,0,100,0), +(@PATH,3,3417.021,598.9542,356.9669,0,0,0,100,0), +(@PATH,4,3230.356,615.1475,346.9949,0,0,0,100,0), +(@PATH,5,3061.912,567.3838,332.8835,0,0,0,100,0), +(@PATH,6,2990.214,429.7983,332.8835,0,0,0,100,0), +(@PATH,7,3203.85,198.3223,332.8835,0,0,0,100,0), +(@PATH,8,3485.543,172.4427,356.9669,0,0,0,100,0); + +SET @NPC := 99112; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3037.007,696.7842,221.9052,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3232.783,646.5775,221.9052,0,0,0,100,0), +(@PATH,2,3397.601,486.7037,221.9052,0,0,0,100,0), +(@PATH,3,3619.899,375.7408,221.9052,0,0,0,100,0), +(@PATH,4,3828.234,403.8529,221.9052,0,0,0,100,0), +(@PATH,5,3950.75,272.4162,221.9052,0,0,0,100,0), +(@PATH,6,3930.549,80.84885,221.9052,0,0,0,100,0), +(@PATH,7,3731.407,15.2053,221.9052,0,0,0,100,0), +(@PATH,8,3520.57,124.0501,221.9052,0,0,0,100,0), +(@PATH,9,3319.81,205.5578,221.9052,0,0,0,100,0), +(@PATH,10,3141.857,364.067,221.9052,0,0,0,100,0), +(@PATH,11,3020.412,487.4164,211.0165,0,0,0,100,0), +(@PATH,12,2956.715,583.454,211.0165,0,0,0,100,0), +(@PATH,13,3037.007,696.7842,221.9052,0,0,0,100,0); + +SET @NPC := 99113; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3723.934,203.8074,149.416,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3679.447,16.12554,149.416,0,0,0,100,0), +(@PATH,2,3507.391,-64.8457,149.416,0,0,0,100,0), +(@PATH,3,3313.535,24.35514,149.416,0,0,0,100,0), +(@PATH,4,3106.862,208.8542,149.416,0,0,0,100,0), +(@PATH,5,2972.297,312.9027,149.416,0,0,0,100,0), +(@PATH,6,2980.743,486.7836,149.416,0,0,0,100,0), +(@PATH,7,3066.302,566.5879,149.416,0,0,0,100,0), +(@PATH,8,3202.917,598.3837,149.416,0,0,0,100,0), +(@PATH,9,3404.993,515.3446,149.416,0,0,0,100,0), +(@PATH,10,3425.663,255.2629,149.416,0,0,0,100,0), +(@PATH,11,3211.951,114.9269,149.416,0,0,0,100,0), +(@PATH,12,3000.342,217.3278,149.416,0,0,0,100,0), +(@PATH,13,2963.022,422.1858,149.416,0,0,0,100,0), +(@PATH,14,3166.04,544.8924,149.416,0,0,0,100,0), +(@PATH,15,3358.634,487.4157,149.416,0,0,0,100,0), +(@PATH,16,3582.295,398.5222,149.416,0,0,0,100,0), +(@PATH,17,3723.934,203.8074,149.416,0,0,0,100,0); + +SET @NPC := 99114; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3737.246,441.4471,163.1518,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3681.252,275.5609,163.1518,0,0,0,100,0), +(@PATH,2,3715.161,150.0893,163.1518,0,0,0,100,0), +(@PATH,3,3533.266,-10.55339,163.1518,0,0,0,100,0), +(@PATH,4,3173.073,184.9491,151.4297,0,0,0,100,0), +(@PATH,5,2936.554,340.61,144.8464,0,0,0,100,0), +(@PATH,6,2956.506,455.4837,133.5686,0,0,0,100,0), +(@PATH,7,3032.773,515.5552,122.4019,0,0,0,100,0), +(@PATH,8,3178.638,523.1923,126.2074,0,0,0,100,0), +(@PATH,9,3413.29,470.1859,126.2074,0,0,0,100,0), +(@PATH,10,3572.062,487.1479,144.1519,0,0,0,100,0), +(@PATH,11,3523.323,611.9957,144.1519,0,0,0,100,0), +(@PATH,12,3655.581,727.4493,168.9574,0,0,0,100,0), +(@PATH,13,3772.614,626.3416,163.1518,0,0,0,100,0), +(@PATH,14,3737.246,441.4471,163.1518,0,0,0,100,0); + +SET @NPC := 99115; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3490.259,76.95345,197.2588,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3733.682,129.7717,197.2588,0,0,0,100,0), +(@PATH,2,3864.96,508.5689,197.2588,0,0,0,100,0), +(@PATH,3,3552.458,522.002,197.2588,0,0,0,100,0), +(@PATH,4,3285.309,616.7151,197.2588,0,0,0,100,0), +(@PATH,5,3036.671,572.0858,197.2588,0,0,0,100,0), +(@PATH,6,2932.137,492.1258,197.2588,0,0,0,100,0), +(@PATH,7,2908.21,365.3067,197.2588,0,0,0,100,0), +(@PATH,8,3001.178,249.2961,197.2588,0,0,0,100,0), +(@PATH,9,3292.851,156.1309,197.2588,0,0,0,100,0), +(@PATH,10,3490.259,76.95345,197.2588,0,0,0,100,0); + +SET @NPC := 99116; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3484.9,77.65061,181.4013,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3231.553,144.962,181.4013,0,0,0,100,0), +(@PATH,2,3093.218,232.0598,181.4013,0,0,0,100,0), +(@PATH,3,3055.291,416.8134,181.4013,0,0,0,100,0), +(@PATH,4,3167.159,544.8934,181.4013,0,0,0,100,0), +(@PATH,5,3351.382,640.3859,181.4013,0,0,0,100,0), +(@PATH,6,3588.236,561.4211,181.4013,0,0,0,100,0), +(@PATH,7,3702.199,377.5353,181.4013,0,0,0,100,0), +(@PATH,8,3664.586,182.5018,181.4013,0,0,0,100,0), +(@PATH,9,3484.9,77.65061,181.4013,0,0,0,100,0); + +SET @NPC := 99117; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,2938.209,403.6825,200.0642,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3000.396,533.5293,200.0642,0,0,0,100,0), +(@PATH,2,3148.834,635.804,200.0642,0,0,0,100,0), +(@PATH,3,3307.068,630.108,200.0642,0,0,0,100,0), +(@PATH,4,3393.553,425.3046,200.0642,0,0,0,100,0), +(@PATH,5,3413.431,212.6353,200.0642,0,0,0,100,0), +(@PATH,6,3566.631,98.43479,200.0642,0,0,0,100,0), +(@PATH,7,3729.045,218.3996,200.0642,0,0,0,100,0), +(@PATH,8,3698.444,417.5869,200.0642,0,0,0,100,0), +(@PATH,9,3524.363,494.4065,200.0642,0,0,0,100,0), +(@PATH,10,3335.302,374.7052,200.0642,0,0,0,100,0), +(@PATH,11,3255.138,189.5002,200.0642,0,0,0,100,0), +(@PATH,12,3111.794,148.6386,200.0642,0,0,0,100,0), +(@PATH,13,2979.718,214.2472,200.0642,0,0,0,100,0), +(@PATH,14,2938.209,403.6825,200.0642,0,0,0,100,0); + +SET @NPC := 99118; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,27608,571,1,1,24140,0,3756.611,216.3398,142.0742,1.91463,120,0,0,92538,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3746.663,468.0216,142.0742,0,0,0,100,0), +(@PATH,2,3489.741,512.316,142.0742,0,0,0,100,0), +(@PATH,3,3277.682,558.9236,142.0742,0,0,0,100,0), +(@PATH,4,3152.218,477.8159,142.0742,0,0,0,100,0), +(@PATH,5,3082.888,432.7688,142.0742,0,0,0,100,0), +(@PATH,6,3016.838,481.925,142.0742,0,0,0,100,0), +(@PATH,7,3033.647,560.426,142.0742,0,0,0,100,0), +(@PATH,8,3162.152,562.8186,142.0742,0,0,0,100,0), +(@PATH,9,3240.709,468.0213,142.0742,0,0,0,100,0), +(@PATH,10,3371.026,259.9583,142.0742,0,0,0,100,0), +(@PATH,11,3535.323,122.4076,142.0742,0,0,0,100,0), +(@PATH,12,3756.611,216.3398,142.0742,0,0,0,100,0); + +-- Wyrmrest Temple Drake + +DELETE FROM `creature` WHERE `guid` IN (100170,100206,100207,100208,100209,100210,100213,100215,100216,100226,130999,131000,131001,131002,131003,131006,131004,131005,131007,131008,131009); + +UPDATE `creature_template` SET `speed_walk`=9/2,`speed_run`=17/7,`InhabitType`=4 WHERE `entry`=26925; + +SET @NPC := 100170; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3423.212,279.9993,128.0342,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3423.212,279.9993,128.0342,0,0,0,100,0), +(@PATH,2,3452.103,334.373,128.0342,0,0,0,100,0), +(@PATH,3,3463.885,390.2345,128.0342,0,0,0,100,0), +(@PATH,4,3459.316,448.6561,128.0342,0,0,0,100,0), +(@PATH,5,3390.542,472.8465,128.0342,0,0,0,100,0), +(@PATH,6,3343.515,429.0621,128.0342,0,0,0,100,0), +(@PATH,7,3319.781,350.6016,128.0342,0,0,0,100,0), +(@PATH,8,3342.761,276.0052,128.0342,0,0,0,100,0), +(@PATH,9,3381.065,257.5826,128.0342,0,0,0,100,0); + +SET @NPC := 100206; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3662.692,328.2304,338.4197,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3662.692,328.2304,338.4197,0,0,0,100,0), +(@PATH,2,3648.806,293.8063,321.0587,0,0,0,100,0), +(@PATH,3,3677.441,213.8859,320.1976,0,0,0,100,0), +(@PATH,4,3615.31,209.5691,324.1698,0,0,0,100,0), +(@PATH,5,3637.643,254.0089,332.7251,0,0,0,100,0), +(@PATH,6,3699.886,260.6509,327.8641,0,0,0,100,0), +(@PATH,7,3720.373,308.941,337.7808,0,0,0,100,0), +(@PATH,8,3691.676,352.0933,342.2254,0,0,0,100,0); + +SET @NPC := 100207; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3657.962,213.0957,169.3146,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3657.962,213.0957,169.3146,0,0,0,100,0), +(@PATH,2,3667.34,194.262,169.3146,0,0,0,100,0), +(@PATH,3,3675.021,149.4151,169.3146,0,0,0,100,0), +(@PATH,4,3676.687,103.2968,169.3146,0,0,0,100,0), +(@PATH,5,3657.863,59.17426,169.3146,0,0,0,100,0), +(@PATH,6,3622.093,33.20833,169.3146,0,0,0,100,0), +(@PATH,7,3595.094,36.79308,169.3146,0,0,0,100,0), +(@PATH,8,3578.594,58.34657,169.3146,0,0,0,100,0), +(@PATH,9,3553.642,84.92133,169.3146,0,0,0,100,0), +(@PATH,10,3558.182,112.2144,169.3146,0,0,0,100,0), +(@PATH,11,3570.514,135.5537,169.3146,0,0,0,100,0), +(@PATH,12,3596.293,162.6956,169.3146,0,0,0,100,0), +(@PATH,13,3618.115,186.3872,169.3146,0,0,0,100,0), +(@PATH,14,3648.757,225.0738,169.3146,0,0,0,100,0); + +SET @NPC := 100208; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3606.596,396.9579,205.5612,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3606.596,396.9579,205.5612,0,0,0,100,0), +(@PATH,2,3633.08,397.3744,205.5612,0,0,0,100,0), +(@PATH,3,3650.996,425.418,205.5612,0,0,0,100,0), +(@PATH,4,3610.396,457.8707,205.5612,0,0,0,100,0), +(@PATH,5,3510.082,450.9809,205.5612,0,0,0,100,0), +(@PATH,6,3435.127,411.1036,205.5612,0,0,0,100,0), +(@PATH,7,3388.161,429.3571,205.5612,0,0,0,100,0), +(@PATH,8,3406.552,481.8189,205.5612,0,0,0,100,0), +(@PATH,9,3518.298,499.1305,205.5612,0,0,0,100,0), +(@PATH,10,3568.027,418.6763,205.5612,0,0,0,100,0); + +SET @NPC := 100209; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3648.806,293.8063,321.0587,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3648.806,293.8063,321.0587,0,0,0,100,0), +(@PATH,2,3677.441,213.8859,320.1976,0,0,0,100,0), +(@PATH,3,3615.31,209.5691,324.1698,0,0,0,100,0), +(@PATH,4,3637.643,254.0089,332.7251,0,0,0,100,0), +(@PATH,5,3699.886,260.6509,327.8641,0,0,0,100,0), +(@PATH,6,3720.373,308.941,337.7808,0,0,0,100,0), +(@PATH,7,3691.676,352.0933,342.2254,0,0,0,100,0), +(@PATH,8,3662.692,328.2304,338.4197,0,0,0,100,0); + +SET @NPC := 100210; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3452.103,334.373,128.0342,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3452.103,334.373,128.0342,0,0,0,100,0), +(@PATH,2,3334.853,530.1229,197.2842,0,0,0,100,0), +(@PATH,3,3325.103,359.123,195.7842,0,0,0,100,0), +(@PATH,4,3499.853,334.623,195.0342,0,0,0,100,0), +(@PATH,5,3263.353,527.8729,197.2842,0,0,0,100,0), +(@PATH,6,3706.853,80.87296,195.7842,0,0,0,100,0), +(@PATH,7,3499.853,334.623,195.0342,0,0,0,100,0), +(@PATH,8,3495.603,493.623,197.2842,0,0,0,100,0), +(@PATH,9,3218.353,177.623,195.7842,0,0,0,100,0); + +SET @NPC := 100213; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3648.806,293.8063,321.0587,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3648.806,293.8063,321.0587,0,0,0,100,0), +(@PATH,2,3588.806,84.30627,390.3087,0,0,0,100,0), +(@PATH,3,3827.556,468.8063,388.3087,0,0,0,100,0), +(@PATH,4,3731.556,38.55627,388.5587,0,0,0,100,0), +(@PATH,5,3454.556,53.30627,390.3087,0,0,0,100,0), +(@PATH,6,3756.306,434.3063,388.3087,0,0,0,100,0), +(@PATH,7,3503.556,54.30627,388.5587,0,0,0,100,0), +(@PATH,8,3795.056,64.55627,390.3087,0,0,0,100,0); + +SET @NPC := 100215; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3606.596,396.9579,205.5612,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3606.596,396.9579,205.5612,0,0,0,100,0), +(@PATH,2,3688.846,165.4579,274.8112,0,0,0,100,0), +(@PATH,3,3601.846,450.2079,273.3112,0,0,0,100,0), +(@PATH,4,3585.346,505.2079,272.8112,0,0,0,100,0), +(@PATH,5,3602.096,174.2079,274.8112,0,0,0,100,0), +(@PATH,6,3446.596,562.4579,273.3112,0,0,0,100,0), +(@PATH,7,3585.346,505.2079,272.8112,0,0,0,100,0), +(@PATH,8,3500.346,153.9579,274.8112,0,0,0,100,0), +(@PATH,9,3571.096,180.2079,273.3112,0,0,0,100,0), +(@PATH,10,3585.346,505.2079,272.8112,0,0,0,100,0); + +SET @NPC := 100216; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3772.475,266.6113,254.1891,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3772.475,266.6113,254.1891,0,0,0,100,0), +(@PATH,2,3887.975,92.86133,323.4391,0,0,0,100,0), +(@PATH,3,3532.475,436.8613,321.6891,0,0,0,100,0), +(@PATH,4,3798.725,252.1113,321.4391,0,0,0,100,0), +(@PATH,5,3886.225,81.11133,323.4391,0,0,0,100,0), +(@PATH,6,3636.975,32.11133,321.6891,0,0,0,100,0), +(@PATH,7,3798.725,252.1113,321.4391,0,0,0,100,0), +(@PATH,8,3747.725,77.61133,323.4391,0,0,0,100,0), +(@PATH,9,3772.475,165.6113,321.6891,0,0,0,100,0), +(@PATH,10,3798.725,252.1113,321.4391,0,0,0,100,0), +(@PATH,11,3899.725,81.86133,323.4391,0,0,0,100,0), +(@PATH,12,3936.975,216.1113,321.6891,0,0,0,100,0), +(@PATH,13,3798.725,252.1113,321.4391,0,0,0,100,0), +(@PATH,14,3755.975,93.86133,323.4391,0,0,0,100,0), +(@PATH,15,3785.475,362.1113,321.9391,0,0,0,100,0), +(@PATH,16,3798.725,252.1113,321.4391,0,0,0,100,0); + +SET @NPC := 100226; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3447.796,171.34,125.7842,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3447.796,171.34,125.7842,0,0,0,100,0), +(@PATH,2,3456.033,100.7345,125.7842,0,0,0,100,0), +(@PATH,3,3388.28,76.85818,125.7842,0,0,0,100,0), +(@PATH,4,3360.649,126.0434,125.7842,0,0,0,100,0), +(@PATH,5,3368.991,199.87,125.7842,0,0,0,100,0), +(@PATH,6,3432.052,296.2538,125.7842,0,0,0,100,0), +(@PATH,7,3465.493,406.8654,125.7842,0,0,0,100,0), +(@PATH,8,3397.028,457.6761,125.7842,0,0,0,100,0), +(@PATH,9,3354.537,408.359,125.7842,0,0,0,100,0), +(@PATH,10,3384.226,319.0551,125.7842,0,0,0,100,0), +(@PATH,11,3433.646,226.0049,125.7842,0,0,0,100,0); + +SET @NPC := 130999; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26925,571,1,1,6376,0,3750.984,407.8766,254.1891,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3750.984,407.8766,254.1891,0,0,0,100,0), +(@PATH,2,3786.711,439.0684,254.1891,0,0,0,100,0), +(@PATH,3,3830.952,442.1341,254.1891,0,0,0,100,0), +(@PATH,4,3862.503,430.8392,254.1891,0,0,0,100,0), +(@PATH,5,3882.549,422.6376,254.1891,0,0,0,100,0), +(@PATH,6,3890.228,394.8426,254.1891,0,0,0,100,0), +(@PATH,7,3871.091,383.1622,254.1891,0,0,0,100,0), +(@PATH,8,3860.575,369.1732,254.1891,0,0,0,100,0), +(@PATH,9,3840.769,340.5143,257.8279,0,0,0,100,0), +(@PATH,10,3832.232,320.8624,264.8557,0,0,0,100,0), +(@PATH,11,3801.307,290.9948,262.5502,0,0,0,100,0), +(@PATH,12,3775.203,268.874,254.1891,0,0,0,100,0), +(@PATH,13,3772.475,266.6113,254.1891,0,0,0,100,0), +(@PATH,14,3748.613,298.5957,254.1891,0,0,0,100,0), +(@PATH,15,3725.111,325.421,254.1891,0,0,0,100,0), +(@PATH,16,3718.476,358.75,254.1891,0,0,0,100,0), +(@PATH,17,3726.624,371.3951,254.1891,0,0,0,100,0); + +-- Wyrmrest Guardian + +DELETE FROM `creature` WHERE `guid` IN (100823,100824,100825,100826,131035,131036,131037,131038,131039,131040,131041,131042,131043,131044,131045,131046,131047,131048,131049,131050); +UPDATE `creature_template` SET `speed_walk`=7/2,`speed_run`=15/7,`InhabitType`=4 WHERE `entry`=26933; + +SET @NPC := 100823; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3791.882,255.4148,152.3366,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3791.882,255.4148,152.3366,0,0,0,100,0), +(@PATH,2,3834.405,230.3203,152.3366,0,0,0,100,0), +(@PATH,3,3876.825,233.7821,152.3366,0,0,0,100,0), +(@PATH,4,3900.443,242.9511,152.3366,0,0,0,100,0), +(@PATH,5,3916.114,280.9176,152.3366,0,0,0,100,0), +(@PATH,6,3906.543,328.6796,152.3366,0,0,0,100,0), +(@PATH,7,3897.018,362.4748,152.3366,0,0,0,100,0), +(@PATH,8,3881.718,402.3574,152.3366,0,0,0,100,0), +(@PATH,9,3858.27,431.4729,152.3366,0,0,0,100,0), +(@PATH,10,3816.65,448.8396,152.3366,0,0,0,100,0), +(@PATH,11,3767.092,457.8965,152.3366,0,0,0,100,0), +(@PATH,12,3720.177,443.4765,152.3366,0,0,0,100,0), +(@PATH,13,3699.901,410.0056,152.3366,0,0,0,100,0), +(@PATH,14,3723.531,374.0899,152.3366,0,0,0,100,0), +(@PATH,15,3739.026,327.0149,152.3366,0,0,0,100,0), +(@PATH,16,3762.99,312.7233,152.3366,0,0,0,100,0), +(@PATH,17,3774.031,299.9361,152.3366,0,0,0,100,0), +(@PATH,18,3786.234,277.9988,152.3366,0,0,0,100,0); + +SET @NPC := 100824; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3559.792,412.912,244.8625,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3559.792,412.912,244.8625,0,0,0,100,0), +(@PATH,2,3625.949,456.7731,244.8625,0,0,0,100,0), +(@PATH,3,3683.285,437.189,244.8625,0,0,0,100,0), +(@PATH,4,3727.341,385.3615,244.8625,0,0,0,100,0), +(@PATH,5,3786.656,388.9702,244.8625,0,0,0,100,0), +(@PATH,6,3811.097,463.1342,244.8625,0,0,0,100,0), +(@PATH,7,3769.007,516.1342,244.8625,0,0,0,100,0), +(@PATH,8,3685.209,493.7117,244.8625,0,0,0,100,0), +(@PATH,9,3589.482,475.7777,244.8625,0,0,0,100,0), +(@PATH,10,3491.84,496.9259,244.8625,0,0,0,100,0), +(@PATH,11,3406.895,485.8197,244.8625,0,0,0,100,0), +(@PATH,12,3370.333,427.0351,244.8625,0,0,0,100,0), +(@PATH,13,3411.417,366.7467,244.8625,0,0,0,100,0), +(@PATH,14,3479.214,376.5652,244.8625,0,0,0,100,0); + +SET @NPC := 100825; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3424.446,300.7501,194.3189,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3424.446,300.7501,194.3189,0,0,0,100,0), +(@PATH,2,3427.025,177.7048,194.3189,0,0,0,100,0), +(@PATH,3,3508.415,97.62153,194.3189,0,0,0,100,0), +(@PATH,4,3635.289,110.5046,194.3189,0,0,0,100,0), +(@PATH,5,3728.01,244.8104,194.3189,0,0,0,100,0), +(@PATH,6,3655.76,402.0861,194.3189,0,0,0,100,0), +(@PATH,7,3513.567,405.2664,194.3189,0,0,0,100,0); + +SET @NPC := 100826; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3457.605,232.8917,280.631,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3457.605,232.8917,280.631,0,0,0,100,0), +(@PATH,2,3414.099,307.4206,280.631,0,0,0,100,0), +(@PATH,3,3470.344,415.2286,280.631,0,0,0,100,0), +(@PATH,4,3607.002,418.6074,280.631,0,0,0,100,0), +(@PATH,5,3711.957,340.5557,280.631,0,0,0,100,0), +(@PATH,6,3720.49,226.3188,280.631,0,0,0,100,0), +(@PATH,7,3642.503,140.184,280.631,0,0,0,100,0), +(@PATH,8,3516.544,159.0889,280.631,0,0,0,100,0); + +SET @NPC := 131035; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3559.792,412.912,244.8625,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3559.792,412.912,244.8625,0,0,0,100,0), +(@PATH,2,3625.949,456.7731,244.8625,0,0,0,100,0), +(@PATH,3,3683.285,437.189,244.8625,0,0,0,100,0), +(@PATH,4,3727.341,385.3615,244.8625,0,0,0,100,0), +(@PATH,5,3786.656,388.9702,244.8625,0,0,0,100,0), +(@PATH,6,3811.097,463.1342,244.8625,0,0,0,100,0), +(@PATH,7,3769.007,516.1342,244.8625,0,0,0,100,0), +(@PATH,8,3685.209,493.7117,244.8625,0,0,0,100,0), +(@PATH,9,3589.482,475.7777,244.8625,0,0,0,100,0), +(@PATH,10,3491.84,496.9259,244.8625,0,0,0,100,0), +(@PATH,11,3406.895,485.8197,244.8625,0,0,0,100,0), +(@PATH,12,3370.333,427.0351,244.8625,0,0,0,100,0), +(@PATH,13,3411.417,366.7467,244.8625,0,0,0,100,0), +(@PATH,14,3479.214,376.5652,244.8625,0,0,0,100,0); + +SET @NPC := 131036; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3438.608,283.5485,224.3952,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3438.608,283.5485,224.3952,0,0,0,100,0), +(@PATH,2,3422.991,341.0565,224.3952,0,0,0,100,0), +(@PATH,3,3372.117,385.6395,224.3952,0,0,0,100,0), +(@PATH,4,3315.855,342.7029,224.3952,0,0,0,100,0), +(@PATH,5,3294.378,270.6668,224.3952,0,0,0,100,0), +(@PATH,6,3321.572,194.6726,224.3952,0,0,0,100,0), +(@PATH,7,3385.174,162.3308,224.3952,0,0,0,100,0), +(@PATH,8,3437.712,218.1042,224.3952,0,0,0,100,0); + +SET @NPC := 131037; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3337.373,175.2911,169.6936,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3337.373,175.2911,169.6936,0,0,0,100,0), +(@PATH,2,3292.872,421.84,169.6936,0,0,0,100,0), +(@PATH,3,3355.351,609.4697,169.6936,0,0,0,100,0), +(@PATH,4,3233.689,777.6954,207.249,0,0,0,100,0), +(@PATH,5,3049.014,721.6703,224.4991,0,0,0,100,0), +(@PATH,6,3044.268,566.5984,169.6936,0,0,0,100,0), +(@PATH,7,3142.397,481.2142,169.6936,0,0,0,100,0), +(@PATH,8,3328.336,435.8111,169.6936,0,0,0,100,0), +(@PATH,9,3583.232,539.7742,169.6936,0,0,0,100,0), +(@PATH,10,3799.81,460.638,169.6936,0,0,0,100,0), +(@PATH,11,3717.946,244.38,169.6936,0,0,0,100,0), +(@PATH,12,3542.247,134.1484,169.6936,0,0,0,100,0), +(@PATH,13,3378.177,251.381,169.6936,0,0,0,100,0), +(@PATH,14,3448.559,417.0887,169.6936,0,0,0,100,0), +(@PATH,15,3659.633,429.129,169.6936,0,0,0,100,0), +(@PATH,16,3726.806,236.8274,169.6936,0,0,0,100,0), +(@PATH,17,3554.261,69.58746,169.6936,0,0,0,100,0); + +SET @NPC := 131038; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26933,571,1,1,0,0,3738.288,310.6056,206.0655,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3738.288,310.6056,206.0655,0,0,0,100,0), +(@PATH,1,3775.943,320.1521,206.0655,0,0,0,100,0), +(@PATH,1,3791.984,364.0035,206.0655,0,0,0,100,0), +(@PATH,1,3821.821,375.4122,206.0655,0,0,0,100,0), +(@PATH,1,3862.769,402.7154,206.0655,0,0,0,100,0), +(@PATH,1,3833.872,426.7561,206.0655,0,0,0,100,0), +(@PATH,1,3796.899,413.8476,206.0655,0,0,0,100,0), +(@PATH,1,3780.125,433.8598,206.0655,0,0,0,100,0), +(@PATH,1,3736.043,443.3744,206.0655,0,0,0,100,0), +(@PATH,1,3713.603,445.3026,206.0655,0,0,0,100,0), +(@PATH,1,3683.613,406.9387,206.0655,0,0,0,100,0), +(@PATH,1,3706.474,364.4982,206.0655,0,0,0,100,0), +(@PATH,1,3712.073,324.8767,206.0655,0,0,0,100,0); diff --git a/sql/updates/world/2012_06_02_07_world_Misc.sql b/sql/updates/world/2012_06_02_07_world_Misc.sql new file mode 100644 index 00000000000..c541819841c --- /dev/null +++ b/sql/updates/world/2012_06_02_07_world_Misc.sql @@ -0,0 +1,6 @@ +-- Fix some Flying Stormpeaks Wyms +UPDATE `creature_addon` SET `bytes1`=50331648 WHERE `guid` IN (101109,101111,101112,101121,101123,101124); +-- Fix some Flying Wild Wyms +UPDATE `creature_addon` SET `bytes1`=50331648 WHERE `guid` IN (202972,202973,202974,202975,202976,202977); +-- remove some bad creature_addon records +DELETE FROM `creature_addon` WHERE `guid` NOT IN (SELECT `guid` FROM `creature`); diff --git a/sql/updates/world/2012_06_02_08_world_waypoints.sql b/sql/updates/world/2012_06_02_08_world_waypoints.sql new file mode 100644 index 00000000000..60b936a7f72 --- /dev/null +++ b/sql/updates/world/2012_06_02_08_world_waypoints.sql @@ -0,0 +1,256 @@ +-- Remove Brunnhildar Drakerider Spawns +DELETE FROM `creature` WHERE `guid` IN (97922,97923); +DELETE FROM `creature_addon` WHERE `guid` IN (97922,97923); + +-- Pathing for Frigid Proto-Drake +SET @NPC := 97991; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,29460,571,1,1,0,0,7138.47,-2166.756,798.66,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7138.47,-2166.756,798.66,0,0,0,100,0), +(@PATH,2,7137.982,-2206.665,805.7148,0,0,0,100,0), +(@PATH,3,7161.205,-2258.269,804.6854,0,0,0,100,0), +(@PATH,4,7192.208,-2308.688,803.2413,0,0,0,100,0), +(@PATH,5,7234.745,-2344.972,803.0753,0,0,0,100,0), +(@PATH,6,7274.754,-2385.471,791.2989,0,0,0,100,0), +(@PATH,7,7279.244,-2432.098,788.5766,0,0,0,100,0), +(@PATH,8,7287.073,-2487.045,787.2991,0,0,0,100,0), +(@PATH,9,7313.09,-2514.464,787.2991,0,0,0,100,0), +(@PATH,10,7371.793,-2525.992,787.2991,0,0,0,100,0), +(@PATH,11,7408.351,-2485.411,787.2991,0,0,0,100,0), +(@PATH,12,7420.525,-2414.975,787.2991,0,0,0,100,0), +(@PATH,13,7408.521,-2337.311,787.2991,0,0,0,100,0), +(@PATH,14,7349.138,-2289.91,787.2991,0,0,0,100,0), +(@PATH,15,7279.763,-2277.351,787.2991,0,0,0,100,0), +(@PATH,16,7206.917,-2239.987,787.2991,0,0,0,100,0), +(@PATH,17,7179.584,-2203.606,787.2991,0,0,0,100,0), +(@PATH,18,7160.147,-2169.823,787.2991,0,0,0,100,0), +(@PATH,19,7134.891,-2128.46,787.2991,0,0,0,100,0), +(@PATH,20,7122.673,-2069.597,787.2991,0,0,0,100,0), +(@PATH,21,7104.583,-2041.353,787.2991,0,0,0,100,0), +(@PATH,22,7060.176,-2045.798,787.2991,0,0,0,100,0), +(@PATH,23,7021.334,-2089.535,787.2991,0,0,0,100,0), +(@PATH,24,7021.683,-2123.516,787.2991,0,0,0,100,0), +(@PATH,25,7055.512,-2136.21,787.2991,0,0,0,100,0), +(@PATH,26,7096.39,-2139.124,787.2991,0,0,0,100,0), +(@PATH,27,7118.583,-2150.815,787.2991,0,0,0,100,0); + +SET @NPC := 97992; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,29460,571,1,1,0,0,7368.505,-2205.943,843.7172,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7368.505,-2205.943,843.7172,0,0,0,100,0), +(@PATH,2,7368.349,-2206.931,843.7172,0,0,0,100,0), +(@PATH,3,7370.282,-2210.494,847.4096,0,0,0,100,0), +(@PATH,4,7355.707,-2244.806,829.2711,0,0,0,100,0), +(@PATH,5,7331.636,-2263.269,812.4655,0,0,0,100,0), +(@PATH,6,7302.835,-2255.226,790.5214,0,0,0,100,0); + +SET @NPC := 98025; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,29460,571,1,1,0,0,7139.471,-2158.159,806.128,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7139.471,-2158.159,806.128,0,0,0,100,0), +(@PATH,2,7174.096,-2197.912,799.7397,0,0,0,100,0), +(@PATH,3,7207.944,-2233.231,799.7397,0,0,0,100,0), +(@PATH,4,7270.875,-2270.113,799.7397,0,0,0,100,0), +(@PATH,5,7326.976,-2290.712,799.7397,0,0,0,100,0), +(@PATH,6,7398.354,-2307.759,858.0721,0,0,0,100,0), +(@PATH,7,7492.969,-2338.019,913.3103,0,0,0,100,0), +(@PATH,8,7516.403,-2341.424,929.4471,0,0,0,100,0), +(@PATH,9,7533.13,-2350.423,930.8928,0,0,0,100,0), +(@PATH,10,7542.375,-2369.76,924.0596,0,0,0,100,0), +(@PATH,11,7540.795,-2388.042,900.4768,0,0,0,100,0), +(@PATH,12,7520.372,-2426.235,856.811,0,0,0,100,0), +(@PATH,13,7490.571,-2460.841,825.395,0,0,0,100,0), +(@PATH,14,7433.976,-2476.923,806.3961,0,0,0,100,0), +(@PATH,15,7363.505,-2480.186,799.9239,0,0,0,100,0), +(@PATH,16,7322.222,-2455.095,799.9239,0,0,0,100,0), +(@PATH,17,7296.217,-2406.509,799.9239,0,0,0,100,0), +(@PATH,18,7250.124,-2348.116,796.2858,0,0,0,100,0), +(@PATH,19,7199.447,-2308.098,791.8962,0,0,0,100,0), +(@PATH,20,7165.64,-2260.306,794.3141,0,0,0,100,0), +(@PATH,21,7126.358,-2218.408,792.2291,0,0,0,100,0), +(@PATH,22,7101.756,-2200.451,797.7845,0,0,0,100,0), +(@PATH,23,7071.807,-2185.584,808.8121,0,0,0,100,0), +(@PATH,24,7043.711,-2175.546,825.1454,0,0,0,100,0), +(@PATH,25,7016.538,-2153.01,825.1454,0,0,0,100,0), +(@PATH,26,7010.379,-2118.062,825.1454,0,0,0,100,0), +(@PATH,27,7031.11,-2081.328,825.1454,0,0,0,100,0), +(@PATH,28,7067.889,-2058.581,825.1454,0,0,0,100,0), +(@PATH,29,7109.583,-2060.563,825.1454,0,0,0,100,0), +(@PATH,30,7129.145,-2089.288,825.1454,0,0,0,100,0), +(@PATH,31,7133.573,-2119.781,811.7565,0,0,0,100,0); + +SET @NPC := 98026; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,29460,571,1,1,0,0,7111.189,-2126.364,809.0059,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7111.189,-2126.364,809.0059,0,0,0,100,0), +(@PATH,2,7112.182,-2126.484,809.0059,0,0,0,100,0), +(@PATH,3,7148.073,-2168.365,801.1813,0,0,0,100,0), +(@PATH,4,7179.175,-2226.085,785.2094,0,0,0,100,0), +(@PATH,5,7223.947,-2286.013,782.9871,0,0,0,100,0), +(@PATH,6,7299.682,-2304.846,784.2374,0,0,0,100,0), +(@PATH,7,7379.366,-2316.926,796.4037,0,0,0,100,0), +(@PATH,8,7415.913,-2373.976,798.6256,0,0,0,100,0), +(@PATH,9,7412.545,-2436.63,796.9036,0,0,0,100,0), +(@PATH,10,7357.321,-2469.256,801.1813,0,0,0,100,0), +(@PATH,11,7324.498,-2460.21,801.1813,0,0,0,100,0), +(@PATH,12,7299.582,-2416.601,796.1536,0,0,0,100,0), +(@PATH,13,7311.903,-2374.752,787.5981,0,0,0,100,0), +(@PATH,14,7312.228,-2301.718,778.1539,0,0,0,100,0), +(@PATH,15,7277.36,-2261.898,778.1539,0,0,0,100,0), +(@PATH,16,7223.409,-2240.653,778.1539,0,0,0,100,0), +(@PATH,17,7146.638,-2228.195,778.1539,0,0,0,100,0), +(@PATH,18,7063.594,-2217.223,802.7003,0,0,0,100,0), +(@PATH,19,7018.785,-2211.49,814.2276,0,0,0,100,0), +(@PATH,20,6971.935,-2170.058,834.7831,0,0,0,100,0), +(@PATH,21,6970.746,-2108.841,872.616,0,0,0,100,0), +(@PATH,22,6991.211,-2071.003,882.1439,0,0,0,100,0), +(@PATH,23,7035.753,-2048.345,872.0881,0,0,0,100,0), +(@PATH,24,7091.613,-2053.953,852.9218,0,0,0,100,0), +(@PATH,25,7120.529,-2096.423,830.6169,0,0,0,100,0), +(@PATH,26,7139.663,-2146.639,806.1729,0,0,0,100,0); + +SET @NPC := 98027; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,29460,571,1,1,0,0,7325.084,-2259.102,789.8701,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7325.084,-2259.102,789.8701,0,0,0,100,0), +(@PATH,2,7324.438,-2258.339,789.8701,0,0,0,100,0), +(@PATH,3,7303.33,-2256.314,797.6193,0,0,0,100,0), +(@PATH,4,7267.175,-2247.528,794.2031,0,0,0,100,0), +(@PATH,5,7214.491,-2258.535,801.3693,0,0,0,100,0), +(@PATH,6,7172.046,-2253.232,805.3967,0,0,0,100,0), +(@PATH,7,7131.951,-2229.063,811.4247,0,0,0,100,0), +(@PATH,8,7094.743,-2214.779,814.9513,0,0,0,100,0), +(@PATH,9,7037.284,-2220.873,816.9806,0,0,0,100,0), +(@PATH,10,7001.552,-2206.268,815.3693,0,0,0,100,0), +(@PATH,11,6987.444,-2184.004,809.9804,0,0,0,100,0), +(@PATH,12,6978.424,-2132.038,810.9526,0,0,0,100,0), +(@PATH,13,7004.174,-2094.79,805.2302,0,0,0,100,0), +(@PATH,14,7061.313,-2081.083,794.8694,0,0,0,100,0), +(@PATH,15,7106.668,-2099.052,785.4243,0,0,0,100,0), +(@PATH,16,7138.966,-2157.915,783.5634,0,0,0,100,0), +(@PATH,17,7148.676,-2194.204,790.7584,0,0,0,100,0), +(@PATH,18,7161.454,-2233.868,796.2581,0,0,0,100,0), +(@PATH,19,7177.563,-2267.763,796.2305,0,0,0,100,0), +(@PATH,20,7208.712,-2314.157,792.0358,0,0,0,100,0), +(@PATH,21,7273.909,-2345.979,783.6465,0,0,0,100,0), +(@PATH,22,7368.229,-2329.532,782.4529,0,0,0,100,0), +(@PATH,23,7446.557,-2387.249,792.8419,0,0,0,100,0), +(@PATH,24,7464.88,-2459.651,777.7035,0,0,0,100,0), +(@PATH,25,7426.007,-2508.458,777.7035,0,0,0,100,0), +(@PATH,26,7367.409,-2517.811,777.7035,0,0,0,100,0), +(@PATH,27,7315.153,-2476.871,777.7035,0,0,0,100,0), +(@PATH,28,7324.871,-2419.788,787.8976,0,0,0,100,0), +(@PATH,29,7343.577,-2356.954,789.7312,0,0,0,100,0), +(@PATH,30,7355.857,-2295.399,785.1757,0,0,0,100,0), +(@PATH,31,7324.438,-2258.339,789.8701,0,0,0,100,0); + +SET @NPC := 97995; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,29460,571,1,1,0,0,7303.549,-2258.753,788.369,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7303.549,-2258.753,788.369,0,0,0,100,0), +(@PATH,2,7302.752,-2258.148,788.369,0,0,0,100,0), +(@PATH,3,7289.952,-2257.048,791.1975,0,0,0,100,0), +(@PATH,4,7258.658,-2235.294,791.1975,0,0,0,100,0), +(@PATH,5,7210.906,-2223.988,791.1975,0,0,0,100,0), +(@PATH,6,7167.373,-2232.4,791.1975,0,0,0,100,0), +(@PATH,7,7124.27,-2224.081,791.1975,0,0,0,100,0), +(@PATH,8,7086.96,-2192.181,791.1975,0,0,0,100,0), +(@PATH,9,7087.704,-2145.958,791.1975,0,0,0,100,0), +(@PATH,10,7127.069,-2118.094,791.1975,0,0,0,100,0), +(@PATH,11,7164.674,-2135.464,793.8918,0,0,0,100,0), +(@PATH,12,7182.364,-2192.978,791.1975,0,0,0,100,0), +(@PATH,13,7182.774,-2277.733,805.3915,0,0,0,100,0), +(@PATH,14,7229.842,-2333.471,805.3915,0,0,0,100,0), +(@PATH,15,7308.383,-2345.623,805.3915,0,0,0,100,0), +(@PATH,16,7376.758,-2335.746,805.3915,0,0,0,100,0), +(@PATH,17,7427.352,-2382.805,805.3915,0,0,0,100,0), +(@PATH,18,7432.168,-2464.934,805.3915,0,0,0,100,0), +(@PATH,19,7370.238,-2513.568,805.3915,0,0,0,100,0), +(@PATH,20,7321.452,-2503.377,805.3915,0,0,0,100,0), +(@PATH,21,7291.445,-2456.148,800.0583,0,0,0,100,0), +(@PATH,22,7306.158,-2414.508,794.0861,0,0,0,100,0), +(@PATH,23,7331.817,-2357.911,790.9471,0,0,0,100,0), +(@PATH,24,7331.193,-2296.791,790.9471,0,0,0,100,0), +(@PATH,25,7305.381,-2260.717,790.9471,0,0,0,100,0); + +SET @NPC := 98028; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,29460,571,1,1,0,0,7133.43,-2118.791,811.7565,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`) VALUES (@NPC,@PATH,50331648); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7133.43,-2118.791,811.7565,0,0,0,100,0), +(@PATH,2,7133.573,-2119.781,811.7565,0,0,0,100,0), +(@PATH,3,7119.039,-2128.233,806.786,0,0,0,100,0), +(@PATH,4,7129.032,-2143.773,806.786,0,0,0,100,0), +(@PATH,5,7131.506,-2163.489,806.786,0,0,0,100,0), +(@PATH,6,7125.905,-2198.75,806.786,0,0,0,100,0), +(@PATH,7,7133.987,-2234.428,806.786,0,0,0,100,0), +(@PATH,8,7170.914,-2282.005,806.786,0,0,0,100,0), +(@PATH,9,7236.963,-2311.655,806.786,0,0,0,100,0), +(@PATH,10,7279.574,-2311.321,806.786,0,0,0,100,0), +(@PATH,11,7320.696,-2339.429,806.786,0,0,0,100,0), +(@PATH,12,7334.366,-2379.159,806.786,0,0,0,100,0), +(@PATH,13,7321.908,-2419.639,819.0636,0,0,0,100,0), +(@PATH,14,7294.696,-2461.332,841.8126,0,0,0,100,0), +(@PATH,15,7277.729,-2494.843,861.1736,0,0,0,100,0), +(@PATH,16,7245.194,-2587.365,911.9794,0,0,0,100,0), +(@PATH,17,7235.221,-2664.447,911.9794,0,0,0,100,0), +(@PATH,18,7267.375,-2723.981,911.9794,0,0,0,100,0), +(@PATH,19,7364.385,-2762.505,956.4234,0,0,0,100,0), +(@PATH,20,7439.538,-2775.097,990.1998,0,0,0,100,0), +(@PATH,21,7538.208,-2706.511,1012.088,0,0,0,100,0), +(@PATH,22,7575.65,-2563.215,985.2554,0,0,0,100,0), +(@PATH,23,7521.32,-2414.249,933.5882,0,0,0,100,0), +(@PATH,24,7438.214,-2348.566,884.2285,0,0,0,100,0), +(@PATH,25,7349.768,-2296.647,830.8118,0,0,0,100,0), +(@PATH,26,7288.613,-2264.192,802.2007,0,0,0,100,0), +(@PATH,27,7231.5,-2246.911,802.2007,0,0,0,100,0), +(@PATH,28,7160.201,-2264.728,829.4783,0,0,0,100,0), +(@PATH,29,7110.628,-2294.354,859.3112,0,0,0,100,0), +(@PATH,30,7061.597,-2313.25,865.6166,0,0,0,100,0), +(@PATH,31,7008.405,-2309.793,865.6166,0,0,0,100,0), +(@PATH,32,6977.473,-2277.743,865.6166,0,0,0,100,0), +(@PATH,33,6976.358,-2204.402,846.9778,0,0,0,100,0), +(@PATH,34,7022.063,-2142,828.7004,0,0,0,100,0), +(@PATH,35,7070.062,-2121.369,822.228,0,0,0,100,0), +(@PATH,36,7112.182,-2126.484,809.0059,0,0,0,100,0); diff --git a/sql/updates/world/2012_06_02_09_world_creature_transport.sql b/sql/updates/world/2012_06_02_09_world_creature_transport.sql new file mode 100644 index 00000000000..9a0b062f9ea --- /dev/null +++ b/sql/updates/world/2012_06_02_09_world_creature_transport.sql @@ -0,0 +1,2 @@ +-- Remove dupe spawn from transport table +DELETE FROM `creature_transport` WHERE `guid`=35 AND `npc_entry`=30755; diff --git a/sql/updates/world/2012_06_03_00_world_sai.sql b/sql/updates/world/2012_06_03_00_world_sai.sql new file mode 100644 index 00000000000..7a5932e61fc --- /dev/null +++ b/sql/updates/world/2012_06_03_00_world_sai.sql @@ -0,0 +1,71 @@ +SET @YANNI := 25459; +SET @CARPET := 25460; +SET @Q_CarpetRide := 11636; + +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@YANNI,@CARPET) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@CARPET*100,@CARPET*100+1) AND `source_type`=9; +INSERT INTO `smart_scripts`(`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`)VALUES +(@YANNI,0,0,0,62,0,100,0,9162,0,0,0,11,45600,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Yanni - Cast Call of the Carpet on player'), +(@YANNI,0,1,0,62,0,100,0,9162,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Yanni - On Gossip option - Close gossip'), + +(@CARPET,0,0,0,25,0,100,0,0,0,0,0,80,@CARPET*100,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Amazing Carpet - Call actionlist 2546000 on spawn'), +(@CARPET,0,1,0,40,0,100,0,14,0,0,0,80,@CARPET*100+1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Amazing Carpet - On WP reach - Call actionlist 2546001'), + +(@CARPET*100,9,0,0,0,0,100,0,1000,1000,0,0,11,45603,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Amazing Carpet - Cast Ride Carpet on summoner'), +(@CARPET*100,9,1,0,0,0,100,0,100,100,0,0,53,0,@CARPET,0,0,0,0,1,0,0,0,0,0,0,0, 'Amazing Carpet - Load waypath'), + +(@CARPET*100+1,9,0,0,0,0,100,0,0,0,0,0,15,@Q_CarpetRide,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Amazing Carpet - Give quest credit'), +(@CARPET*100+1,9,1,0,0,0,100,0,500,500,0,0,28,45602,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Amazing Carpet - Remove aura 45602'), +(@CARPET*100+1,9,2,0,0,0,100,0,100,100,0,0,28,46598,0,0,0,0,0,23,0,0,0,0,0,0,0, 'Amazing Carpet - Remove aura 46598'), +(@CARPET*100+1,9,3,0,0,0,100,0,200,200,0,0,41,200,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Amazing Carpet - Despawn'); + +DELETE FROM `waypoints` WHERE `entry`=@CARPET; +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(@CARPET,1,2751.96,6133.514,214.3789, 'Start WP'), +(@CARPET,2,2728.81,6146.472,213.5733, ''), +(@CARPET,3,2634.248,6188.829,185.9068, ''), +(@CARPET,4,2597.958,6255.91,159.7123, ''), +(@CARPET,5,2538.717,6307.643,138.9901, ''), +(@CARPET,6,2393.912,6321.946,85.79566, ''), +(@CARPET,7,2420.326,6461.604,89.3512, ''), +(@CARPET,8,2439.194,6494.39,84.93455, ''), +(@CARPET,9,2496.371,6496.766,78.76788, ''), +(@CARPET,10,2567.008,6550.509,79.90676, ''), +(@CARPET,11,2652.553,6572.071,58.54562, ''), +(@CARPET,12,2725.122,6642.299,41.57339, ''), +(@CARPET,13,2773.236,6694.341,25.49007, ''), +(@CARPET,14,2797.658,6718.523,9.212306, 'Run SmartAI script 2546001'); + +DELETE FROM `creature_template_addon` WHERE `entry` IN (@CARPET,@YANNI); +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES +(@CARPET,257, '61307'), +(@YANNI,257,NULL); + +-- Update gossip_menu to proper entry from sniff (delete wrong one 21233) +UPDATE `creature_template` SET `gossip_menu_id`=9162,`AiName`= 'SmartAI' WHERE `entry`=@YANNI; +UPDATE `creature_template` SET `exp`=2,`minlevel`=72,`maxlevel`=72,`unit_flags`=`unit_flags`|520,`speed_run`=1.42857,`VehicleId`=317,`AiName`='SmartAI',`InhabitType`=5 WHERE `entry`=@CARPET; + +UPDATE `creature_model_info` SET `bounding_radius`=0.31,`combat_reach`=1,`gender`=2 WHERE `modelid`=28082; -- Amazing Flying Carpet + +DELETE FROM `gossip_menu` WHERE `entry` IN (21233,9162); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(9162,12417); + +UPDATE `quest_template` SET `SpecialFlags`=`SpecialFlags`|2 WHERE `Id`=@Q_CarpetRide; + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=9162; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=9162; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`Comment`) VALUES +(15,9162,0,0,9,@Q_CarpetRide,0,0,0,'Show gossip option 9162 if player has quest Carpet Ride'); + +DELETE FROM `spell_target_position` WHERE `id`=45601; +INSERT INTO `spell_target_position` (`id`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`) VALUES +(45601,571,2753.64,6131.41,210.4463,2.892622); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry`=45602; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,1,45602,0,0,31,0,3,@CARPET,0,0,0, '', 'Ride Carpet - Target Amazing Flying Carpet'); + +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=@CARPET; +INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES +(@CARPET,46598,1,0); diff --git a/sql/updates/world/2012_06_03_01_world_creature.sql b/sql/updates/world/2012_06_03_01_world_creature.sql new file mode 100644 index 00000000000..68448b31591 --- /dev/null +++ b/sql/updates/world/2012_06_03_01_world_creature.sql @@ -0,0 +1,16 @@ +-- Add more Domesticated Felboar Spawns +SET @GUID := 43456; +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID AND @GUID+11; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@GUID,21195,530,1,1,0,0,-2547.195,1426.521,65.57381,1.465101,300,5,0,1,0,1), +(@GUID+1,21195,530,1,1,0,0,-2585.524,1448.067,53.78493,2.973133,300,5,0,1,0,1), +(@GUID+2,21195,530,1,1,0,0,-2513.349,1387.699,66.09725,4.945046,300,5,0,1,0,1), +(@GUID+3,21195,530,1,1,0,0,-2629.757,1453.611,47.29396,4.210276,300,5,0,1,0,1), +(@GUID+4,21195,530,1,1,0,0,-2582.189,1378.531,82.12544,6.054177,300,5,0,1,0,1), +(@GUID+5,21195,530,1,1,0,0,-2478.125,1412.92,25.51498,1.570796,300,5,0,1,0,1), +(@GUID+6,21195,530,1,1,0,0,-2543.231,1349.134,80.78722,5.94909,300,5,0,1,0,1), +(@GUID+7,21195,530,1,1,0,0,-2646.627,1379.277,87.30627,5.863042,300,5,0,1,0,1), +(@GUID+8,21195,530,1,1,0,0,-2611.153,1345.497,84.32706,2.073398,300,5,0,1,0,1), +(@GUID+9,21195,530,1,1,0,0,-2518.199,1318.885,70.41351,1.823595,300,5,0,1,0,1), +(@GUID+10,21195,530,1,1,0,0,-2597.69,1311.426,80.75146,3.249409,300,5,0,1,0,1), +(@GUID+11,21195,530,1,1,0,0,-2545.57,1278.59,82.01826,4.833836,300,5,0,1,0,1); diff --git a/sql/updates/world/2012_06_03_02_world_misc.sql b/sql/updates/world/2012_06_03_02_world_misc.sql new file mode 100644 index 00000000000..69de8eacdf3 --- /dev/null +++ b/sql/updates/world/2012_06_03_02_world_misc.sql @@ -0,0 +1,6 @@ +-- Misc db updates +DELETE FROM `creature_template_addon` WHERE `entry`=30476; +INSERT INTO `creature_template_addon` (`entry`,`auras`) VALUES (30476,'56852'); +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128 WHERE `entry` IN (30476,30599,30640,32193,30343); +-- fix Sholazar Tickbird InhabitType +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`=28093; diff --git a/sql/updates/world/2012_06_03_03_world_quest_template.sql b/sql/updates/world/2012_06_03_03_world_quest_template.sql new file mode 100644 index 00000000000..023182aaf1b --- /dev/null +++ b/sql/updates/world/2012_06_03_03_world_quest_template.sql @@ -0,0 +1,603 @@ +-- OfferRewardText +UPDATE `quest_template` SET `OfferRewardText`='Ah yes, the delivery of herbs from Shadowglen. It is a shame Porthannius could not bring it himself, for we have much to discuss, he and I. But I am glad to get the herbs nonetheless, and I am glad you came.$B$BWhile you are here, please, rest yourself. Heroes must keep their strength and spirits high, and must find rest and solace whenever they may. For to neglect one''s peace of body and mind is a sure path to failure.$B$BSo... rest.' WHERE `Id`=2159; -- Dolanaar Delivery +UPDATE `quest_template` SET `OfferRewardText`='You saved my life up there, buddy. Nice flying!' WHERE `Id`=12671; -- Reconnaissance Flight +UPDATE `quest_template` SET `OfferRewardText`='Wow... S.T.O.U.T. didn''t break... Hmm... Who would have guessed?$b$bI mean, hey, you did it! Your aim is true, or at least true enough to help guard the camp. I think you''re ready now to take on the Dark Irons if they show up again.' WHERE `Id`=12191; -- Chug and Chuck! +UPDATE `quest_template` SET `OfferRewardText`='Not bad for a new overseer. I''ve another task for you if you''re feeling brave today.' WHERE `Id`=12906; -- Discipline +UPDATE `quest_template` SET `OfferRewardText`='If I had any reservations regarding your commitment when you first arrived, I no longer have any. With just a little more effort you could be a permanent member of my operation.' WHERE `Id`=12907; -- Examples to be Made +UPDATE `quest_template` SET `OfferRewardText`='I knew you''d be back! Get me out of these shackles and I''ll help you find the goblin.' WHERE `Id`=12908; -- A Certain Prisoner +UPDATE `quest_template` SET `OfferRewardText`='You''re here -- good. I think I know where your goblin is.' WHERE `Id`=12921; -- A Change of Scenery +UPDATE `quest_template` SET `OfferRewardText`='Well done, young one. It looks like our deal has been satisfied on both our ends.' WHERE `Id`=12969; -- Is That Your Goblin? +UPDATE `quest_template` SET `OfferRewardText`='It''s settled then. You will compete in the Hyldsmeet and with my help you''ll restore great Thorim to his rightful place.' WHERE `Id`=12970; -- The Hyldsmeet +UPDATE `quest_template` SET `OfferRewardText`='Ah, the furs I was expecting. Thank you.$B$BThese came faster than I had expected. They will make good blankets for anyone who wishes to stay here.$B$BPlease feel free to stay as long as you like. My inn is always open and all of our people are welcome here. And don''t underestimate a good night''s rest, it can make a great difference while you''re out traveling.' WHERE `Id`=1656; -- A Task Unfinished +UPDATE `quest_template` SET `OfferRewardText`='Ah, $n! I didn''t think you''d have much trouble finding the place, my directions are excellent, you know...$b$bLet me just finish up my report then.$b$b<He brings out some paper and scribbles on it momentarily.>$b$bThere! Well, haha, now this certainly is funny... I don''t suppose, $n, that you would mind doing one last favor for me?' WHERE `Id`=287; -- Frostmane Hold +UPDATE `quest_template` SET `OfferRewardText`='<Thassarian takes the crystal shards from you and speaks in a quiet voice.>$B$BI remember these...$B$BLesser men would easily crumble beneath their assault. You have done well in removing their threat.' WHERE `Id`=13339; -- Shatter the Shards +UPDATE `quest_template` SET `OfferRewardText`='You did it! Our boys are back!' WHERE `Id`=12843; -- They Took Our Men! +UPDATE `quest_template` SET `OfferRewardText`='You''re definitely not with the Hyldnir... so what are you here for? Ah... you must be looking for the new prisoner!' WHERE `Id`=12846; -- Leave No Goblin Behind +UPDATE `quest_template` SET `OfferRewardText`='I wasn''t sure you were coming back. I dread to think what will happen to me if I stay here for much longer.' WHERE `Id`=12841; -- The Crone's Bargain +UPDATE `quest_template` SET `OfferRewardText`='I was expecting a replacement for one of my overseers. It''s about time you showed up.$B$BLet''s put you to work.' WHERE `Id`=12905; -- Mildred the Cruel +UPDATE `quest_template` SET `OfferRewardText`='Dahlia was taken by the Scourge? This is a sad day for all of us.$B$BI will look to finding a new keeper once the shrine is retaken. Thank you for your efforts... the Ruby Dragonshrine is a sacred place to us, and the sacrifices your kind have made will not be easily forgotten.$B$BIt is good to know there are still heroes such as you - I will call upon you one day. Until that day comes, may your adventures be fruitful.' WHERE `Id`=12419; -- The Fate of the Ruby Dragonshrine +UPDATE `quest_template` SET `OfferRewardText`='<Another wave of euphoria, mixed with some pain, crashes through your mind as you approach the creature.>$B$BGood... good! So that you know I am being fair, I will first give you your reward as promised.$B$BAnd then you will willingly hand me the key.' WHERE `Id`=13308; -- Mind Tricks +UPDATE `quest_template` SET `OfferRewardText`='They''re being driven insane? Voices in their heads?$B$BVoices in your head?!$B$BI want you to clear your mind of the taint that has crept into that place, $g boy : girl;.$B$BWe''ll try to get the remainder of them out of there again tomorrow when you''ve had a chance to rest.' WHERE `Id`=13300; -- Slaves to Saronite +UPDATE `quest_template` SET `OfferRewardText`='Well done. Training against the other valiants is one of the best ways to prepare yourself for tournament competition. I know you''ll make Stormwind proud, $N.' WHERE `Id`=13665; -- The Grand Melee +UPDATE `quest_template` SET `OfferRewardText`='Well done, $N! You demonstrated uncanny courage on the battlefield. Our war against the Troggs will be won with efforts such as yours. You have served King Magni well.$b$bIf you fancy yourself well-suited for this kind of adventuring, I suggest you speak with Mountaineer Gravelgaw. The Captain has him assigned to a rough patrol that I am sure he can use some help with. Check with Gravelgaw just inside the tower.' WHERE `Id`=224; -- In Defense of the King's Lands +UPDATE `quest_template` SET `OfferRewardText`='I am quite impressed, $N. You have done the Dwarven race a great favor by defending our lands. King Magni Bronzebeard himself would be proud!' WHERE `Id`=267; -- The Trogg Threat +UPDATE `quest_template` SET `OfferRewardText`='Hey, that wasn''t too bad... are you sure you''re not a dwarf?$b$bSo there''s plenty more racing to be had and it''s not just from me. All over the Brewfest grounds you''ll find people in need of a decent ram racer. So go and make yourself useful.$b$bOh and don''t forget, these rams were legally obtained. I just want to make sure we''re clear.' WHERE `Id`=11409; -- Now This is Ram Racing... Almost. +UPDATE `quest_template` SET `OfferRewardText`='You are a kind and compassionate $r, friend.' WHERE `Id`=10804; -- Kindness +UPDATE `quest_template` SET `OfferRewardText`='My children have told me of your heroic deeds, $r. There is more that you can do.' WHERE `Id`=10811; -- Seek Out Neltharaku +UPDATE `quest_template` SET `OfferRewardText`='I am free! You have saved us, $N!' WHERE `Id`=10872; -- Zuluhed the Whacked +UPDATE `quest_template` SET `OfferRewardText`='You have proven yourself as an ally of the Netherwing. My mother is free and my brothers and sisters are saved!$B$BPerhaps someday, we will call for you again. When that day comes, know that you will be welcomed with open arms - a $g brother:sister; to the Netherwing Dragonflight.' WHERE `Id`=10871; -- Ally of the Netherwing +UPDATE `quest_template` SET `OfferRewardText`='You''ve done it, $N. You''ve bested some of the fiercest fighters the Hyldnir race has to offer.' WHERE `Id`=12971; -- Taking on All Challengers +UPDATE `quest_template` SET `OfferRewardText`='Think we''ll give you your own bear just like that? You''ll have to prove yourself before you get anything from us.$B$BDo not think too highly of yourself just because you bested a few challengers in the Hyldsmeet.' WHERE `Id`=12972; -- You'll Need a Bear +UPDATE `quest_template` SET `OfferRewardText`='You have shown yourself a capable combatant, $N and you will serve as an example to the rest of the aspirants who clamor to compete on behalf of the Alliance.' WHERE `Id`=13671; -- Training In The Field +UPDATE `quest_template` SET `OfferRewardText`='<Chief Rageclaw cries.>$B$BHad Ragemane since pup. Sad day for Rageclaw. First troll attack Rageclaw, then troll make Ragemane bad. Rageclaw never trade with troll again!' WHERE `Id`=12857; -- Wanted: Ragemane's Flipper +UPDATE `quest_template` SET `OfferRewardText`='You place the egg... distress beacon... inside the chicken... homing robot.$B$BHums and whirs are heard from inside the robot as it struggles to stand up. After the robot comes to life, Oglethorpe''s voice is heard once more, but now from inside the robot:$B$B\"OOX-17/TN is working at least, but it needs major repairs! It is much too heavy for you to carry it... but I think I have an idea. Are you up for watching over it some more?\"' WHERE `Id`=351; -- Find OOX-17/TN! +UPDATE `quest_template` SET `OfferRewardText`='Excellent - the more water pouches we are able to reclaim, the further away from disaster we''ll all be! Keep ''em coming, and I will be sure to reward you for every five water pouches you bring me.' WHERE `Id`=1707; -- Water Pouch Bounty +UPDATE `quest_template` SET `OfferRewardText`='Now that''s what I call efficiency! You''ve helped thin out the nomad''s numbers enough now that we can start to think about how we can win back those water wells.$B$BThe Gadgetzan Water Company thanks you for your help, but we''re far from done in dealing with those foul nomads. Listen close - here''s what we need next...' WHERE `Id`=1690; -- Wastewander Justice +UPDATE `quest_template` SET `OfferRewardText`='Finally - justice is served! You have struck a mighty blow against those vile nomads! With Scorpidsting''s demise, this might be just the thing to finally push those squatters off of Gadgetzan''s water wells!$B$BBy the authority of the Gadgetzan Water Company, I gladly award you with this bounty. You''ve done a great service for us all.' WHERE `Id`=2781; -- WANTED: Caliph Scorpidsting +UPDATE `quest_template` SET `OfferRewardText`='$N! You are the $g man:woman;!!!$B$BI''m sure that the Cartel will ease up on me now that you''ve dealt with those Southsea scum. Let''s see, what can I give you as a reward? How about a little coin and you choose from one of these for your trouble?' WHERE `Id`=8366; -- Southsea Shakedown +UPDATE `quest_template` SET `OfferRewardText`='Ah, Andre''s head. So I guess he''ll make his trial after all!$B$BMuch appreciated, $N. Now if you''ll just sign here, I can issue you payment for services rendered.$B$BDon''t worry about the small print. It''s harmless, and... I don''t think there''s a magnifying glass small enough to read it anyway.' WHERE `Id`=2875; -- WANTED: Andre Firebeard +UPDATE `quest_template` SET `OfferRewardText`='Great, thanks for the shipment! Now MacKinley and I can finally settle our wager.' WHERE `Id`=2873; -- Stoley's Shipment +UPDATE `quest_template` SET `OfferRewardText`='You have my sincere thanks for your efforts, $N. Though much remains to be done, it gladdens me to know we have helped some find their long-deserved rest.' WHERE `Id`=10047; -- The Path of Glory +UPDATE `quest_template` SET `OfferRewardText`='Well, I must say, I am impressed, $N. I didn''t think you had the mettle for this mission. Well done. Well done, indeed. +' WHERE `Id`=10394; -- Disruption - Forge Camp: Mageddon +UPDATE `quest_template` SET `OfferRewardText`='It worked! You got the essence! Well done, $N! Well done!$B$BThis essence will be invaluable in my research. I hope to one day learn how to capture living dragon whelps, or perhaps capture their eggs. If I could find a way to do that, then I would be the envy of dragon scholars around the world!$B$BMy employer would also be happy, and as I said before, he''s someone you want to keep happy...' WHERE `Id`=4726; -- Broodling Essence +UPDATE `quest_template` SET `OfferRewardText`='There is no doubt, this is raw saronite. We''ve seen weapons made from it in the hands of the Lich King''s chosen before, but this is the first time it''s been used to arm anything else. The scale of that mining operation must be huge.' WHERE `Id`=13138; -- I'm Smelting... Smelting! +UPDATE `quest_template` SET `OfferRewardText`='<Crusader Olakin Sainrith listens solemnly to your report.>$B$BIt is not the burial they deserved, but it is better than nothing, and better for those who yet live. Thank you, $N.' WHERE `Id`=13211; -- By Fire Be Purged +UPDATE `quest_template` SET `OfferRewardText`='<Dakrider Arly throws her head back and laughs darkly.>$B$BA fitting end for the ''good'' doctor, wouldn''t you say?' WHERE `Id`=13152; -- A Visit to the Doctor +UPDATE `quest_template` SET `OfferRewardText`='You have proven yourself worthy of the title of champion, $N. You will compete at the tournament''s highest level on behalf of Stormwind, riding in the grand melee with your weapon at the ready and our mighty pennant at your back.' WHERE `Id`=13699; -- The Valiant's Challenge +UPDATE `quest_template` SET `OfferRewardText`='I welcome you as a champion of the tournament, $N. As a champion, you will be able to compete for the grand championship of the tournament. You may also choose to become a valiant with another Alliance city''s delegation and in time, a champion for that city as well.$B$BAll champions must have the assistance of a squire, $N, and you are no exception. Allow me to appoint one of ours to accompany you in battle. He will proudly carry the banner of any city that has named you a champion.' WHERE `Id`=13702; -- A Champion Rises +UPDATE `quest_template` SET `OfferRewardText`='Ah yes, these manes will work great! You show a lot of grit, $C - I wager we''ll see great things from you.' WHERE `Id`=313; -- The Grizzled Den +UPDATE `quest_template` SET `OfferRewardText`='By Magni''s beard, you sure did a lot of hunting!! Thank you, $N.' WHERE `Id`=317; -- Stocking Jetsteam +UPDATE `quest_template` SET `OfferRewardText`='Bellowfiz needs some of my Evershine? Hm...all right.' WHERE `Id`=318; -- Evershine +UPDATE `quest_template` SET `OfferRewardText`='Thank you, $N. It''ll be nice to work our crafts without hearing so many growls and snorts outside the village.' WHERE `Id`=319; -- A Favor for Evershine +UPDATE `quest_template` SET `OfferRewardText`='For me? You''re a true hero, $N!' WHERE `Id`=308; -- Distracting Jarven +UPDATE `quest_template` SET `OfferRewardText`='Yes, this will do just fine. I think I''ll open a bottle right now and have a taste...' WHERE `Id`=320; -- Return to Bellowfiz +UPDATE `quest_template` SET `OfferRewardText`='Not bad, $N! Did you have a hard time getting past their guard?$B$BNo matter - many thanks, and if you''re ever in need of stout with a kick, don''t forget the Barleybrews!' WHERE `Id`=311; -- Return to Marleth +UPDATE `quest_template` SET `OfferRewardText`='Great! I can''t wait to use these in some of my recipes. There''s one in particular I think it''ll work great in...' WHERE `Id`=315; -- The Perfect Stout +UPDATE `quest_template` SET `OfferRewardText`='These Gyromechanic Gears and Restabilization Cogs are in perfect accordance with Ozzie''s schematics for the Recombobulation Device. Once I add some hydrolubricant to the inner combustion pistons, adjust the crank-o-ratchet and increase of the viscosity of the electrogum gel, the gnomish race will be as good as new.' WHERE `Id`=412; -- Operation Recombobulation +UPDATE `quest_template` SET `OfferRewardText`='<Mountaineer Barleybrew tastes the Shimmer Stout...>$B$BOh. Whoa! This stuff really puts a shine in your eyes. I feel like I can see in the dark!' WHERE `Id`=413; -- Shimmer Stout +UPDATE `quest_template` SET `OfferRewardText`='The horns of war will soon echo across this land, waking the dead and calling forth the Scourge war machine. Woe unto those that would stand in our way!$B$BYou and your brethren will lead the charge, $N. When next I look upon the Scarlet lands, my sight will be obscured by the legions of Acherus. The march upon New Avalon begins now.' WHERE `Id`=12657; -- The Might Of The Scourge +UPDATE `quest_template` SET `OfferRewardText`='The war has begun, death knight! I shall place you upon my finest gryphon and deliver you to Death''s Breach. Chaos, death, destruction! You will herald in all of this and more! +' WHERE `Id`=12850; -- Report To Scourge Commander Thalanor +UPDATE `quest_template` SET `OfferRewardText`='Do you smell it?$B$B<Valanar sniffs at the air.>$B$BFresh meat... The scent of Scarlet Crusader wafts through the air.$B$B<Valanar salivates.>$B$BApologies, death knight, I''m sure you''re not interested in my choice of fine cuisine. You are here to work! To lead the charge! Yes... I know. The Lich King has told me all that I need to know about you, $N.$B$BThe time for bloodshed is now. +' WHERE `Id`=12670; -- The Scarlet Harvest +UPDATE `quest_template` SET `OfferRewardText`='Do you feel it, $N? That sensation is raw power coursing through your body. Such a thing cannot exist for mortals.$B$BThe front lines are now dismantled. The geist will finish the job and prepare the grounds for Razuvious. We turn our attention now to more tactical targets. +' WHERE `Id`=12678; -- If Chaos Drives, Let Suffering Hold The Reins +UPDATE `quest_template` SET `OfferRewardText`='To the victor goes the glory, death knight! Well done! The Lich King looks favorably upon you on this day. +' WHERE `Id`=12733; -- Death's Challenge +UPDATE `quest_template` SET `OfferRewardText`='Glad to see the Reclaimers aren''t in short supply of work, or adventurers willing to help out.$B$BI''m Kreldig, $N. You''ve made a smart move helpin'' out the Reclaimers. Everyone needs something these days: they''ve lost a family heirloom, a magic item, a loved one. You never can tell. But with the Reclaimers around, there''s no reason, for the right price, everyone can''t find what they''ve lost. ' WHERE `Id`=1453; -- Reclaimers' Business in Desolace +UPDATE `quest_template` SET `OfferRewardText`='I have entered your name in the rolls, $N. As an aspirant you will train with others who wish to compete in the tournament and hone your mounted combat skills. Once you have proven yourself, you will be allowed to enter the lowest rank of competition on behalf of your capital city.' WHERE `Id`=13667; -- The Argent Tournament +UPDATE `quest_template` SET `OfferRewardText`='Commit Valis''s lesson to memory, $N. It will mean the difference between winning and losing your mounted combat matches.' WHERE `Id`=13835; -- Mastery Of The Shield-Breaker +UPDATE `quest_template` SET `OfferRewardText`='So you''re saying this knight''s story is a sham? Most suspicious. Dishonorable at the least, and murderous at the worst. Still, we can''t confront him until we know for certain whether he was involved in these murders.$B$BDo nothing to arouse his suspicions, $N. Discretion will serve us well as we continue to investigate.' WHERE `Id`=13633; -- The Black Knight of Westfall? +UPDATE `quest_template` SET `OfferRewardText`='So there is some truth to those old tales? It seems they did not lie about the quality of the blade. Well done, $N. The champion who wields it will be a lucky man, indeed.' WHERE `Id`=13666; -- A Blade Fit For A Champion +UPDATE `quest_template` SET `OfferRewardText`='So you say Lorien Sunblaze was done in by poison and Sir Wendell was burnt alive? Dreadful ways to die, both of them. Only Conall was killed by cold steel, and from your description, it was a coward''s strike, not honorable combat that laid him in his grave.$B$BAll three sparred with and were scheduled to fight the Black Knight. This cannot be a coincidence. Now, we must find a way to prove it was the Black Knight''s work.' WHERE `Id`=13643; -- The Stories Dead Men Tell +UPDATE `quest_template` SET `OfferRewardText`='<Crusader Rhydalla examines the bag''s contents with a look of disgust on her face.>$B$BIt''s all here, $N: the poison that killed Lorien, a collection of knives, torches, and oil. No man has cause to possess these things here and no squire would do so without orders from his knightly master. We''ve found our murderer, $N, but who is he working for?' WHERE `Id`=13654; -- There's Something About the Squire +UPDATE `quest_template` SET `OfferRewardText`='<Crusader Rhydalla''s face pales as she reads the orders.>$B$BThis can only mean one thing, $N. The Black Knight is a member of the Cult of the Damned and has been sent by Arthas to disrupt the tournament!$B$BThe Black Knight has proven himself a fearsome combatant, and you will need to be every bit as good if you wish to face him. When you are a champion, return to me and we''ll find a way to ensure his defeat.' WHERE `Id`=13663; -- The Black Knight's Orders +UPDATE `quest_template` SET `OfferRewardText`='Grrr. I knew it! He''s sooooo over-protective! This is just embarassing.$B$BNot that I''m not happy to see you... I am! We all are. We can use your help!' WHERE `Id`=11175; -- My Daughter +UPDATE `quest_template` SET `OfferRewardText`='Good job, though I think ye might be wanting a refresher course in basic piloting.$B$BWell, no matter, one warm body''s as good as another. Here''s yer haul for the day. ' WHERE `Id`=11390; -- I've Got a Flying Machine! +UPDATE `quest_template` SET `OfferRewardText`='<The explorer beams a smile as you tell him who sent you. He continues in hushed tones.>$B$BIrena was concerned about me? She gets that from her father you know.' WHERE `Id`=11393; -- Where is Explorer Jaren? +UPDATE `quest_template` SET `OfferRewardText`='Without Thredd to lead them, hopefully the riots will be more controllable. We shall see.$B$BI must say, after a half hour, I hardly expected you to come out, but it seems I misjudged you.$B$BI''d guess, then, that you didn''t get much useful information out of him? But I know a thing or two that might be of interest to you about Thredd''s activities.' WHERE `Id`=391; -- The Stockade Riots +UPDATE `quest_template` SET `OfferRewardText`='So these bandanas -- filthy tokens of corruption -- are what my Mac had to die for? Such a waste. Such a tragic sacrifice. $b$bBut alas, I cannot return to the past. Just know, $N, that you have brought my family justice through your deeds.' WHERE `Id`=388; -- The Color of Blood +UPDATE `quest_template` SET `OfferRewardText`='That''s right. I have a task that I can''t do while I''m guarding. In fact, it''ll take you far from Loch Modan.$B$BYour perfect chance for adventure!' WHERE `Id`=1339; -- Mountaineer Stormpike's Task +UPDATE `quest_template` SET `OfferRewardText`='You accomplished your mission well, $r. The King himself would be proud.$b$bThe reinforcements promised to us never showed, however. Apparently the Alliance front is a sea of crimson from the blood of our fallen brethren. The news of the losses leaves a bitter taste in one''s mouth. But we must not let their deaths go for naught. We must rally in these grim times and bring glory back to the Alliance.$b$bSpeak with Mountaineer Wallbang for reassignment. You''re needed now more than ever.' WHERE `Id`=237; -- In Defense of the King's Lands +UPDATE `quest_template` SET `OfferRewardText`='Congratulations are in order, $N. You have bested your challenger and earned the right to advance to the rank of valiant.' WHERE `Id`=13679; -- The Aspirant's Challenge +UPDATE `quest_template` SET `OfferRewardText`='Welcome aboard then, Valiant $N. The Stormwind delegation is proud to count you among its members.' WHERE `Id`=13684; -- A Valiant Of Stormwind +UPDATE `quest_template` SET `OfferRewardText`='My nephew said you aided him with his research in Dustwallow, and that you helped his associate out of a tight spot. Well, we Sterns stick together and we don''t ignore our friends!$B$BSo wash your hands, $N, because we''re about to throw a party in your honor!' WHERE `Id`=1271; -- Feast at the Blue Recluse +UPDATE `quest_template` SET `OfferRewardText`='Thanks for helping out our miner back there, $n! I should be able to put together an antidote no problem.$B$BIf you stumble into Tore again, tell her that she''s a jerk for me, will ya?' WHERE `Id`=12832; -- Bitter Departure +UPDATE `quest_template` SET `OfferRewardText`='And it''s already well-done! I outdo myself sometimes.$B$BThanks much, friend!' WHERE `Id`=12828; -- Ample Inspiration +UPDATE `quest_template` SET `OfferRewardText`='Ha ha! Good to see you''re up for some dirty work.$B$BMuch appreciated there, pal!' WHERE `Id`=12829; -- Moving In +UPDATE `quest_template` SET `OfferRewardText`='Woo! That''s a ripe stench right there! You had to get hands-on with some of those snobolds, didn''t ya?$B$BI do appreciate it though!' WHERE `Id`=12830; -- Ore Repossession +UPDATE `quest_template` SET `OfferRewardText`='With the death of the Black Knight, the tournament may once again serve its purpose. The champions of the Horde and Alliance may demonstrate their skill at arms and train for the day when Arthas and his minions will no longer threaten us.$B$BYou have the thanks of the Argent Crusade, $N, and that of all who have answered our call.' WHERE `Id`=13664; -- The Black Knight's Fall +UPDATE `quest_template` SET `OfferRewardText`='<Crusader Rhydalla frowns.>$B$BDo you think they''ve been planning this? I suppose it doesn''t matter, but I don''t like the implication that we''ve been playing into their hands. Whatever is going on, we have to stop it.' WHERE `Id`=14016; -- The Black Knight's Curse +UPDATE `quest_template` SET `OfferRewardText`='The doctor will not have time to complete his work, but his plan is already in motion. From what you''ve reported, the Lich King''s servants have reanimated and empowered the Black Knight and there''s no telling what the knight''s master has in mind. You have done well in uncovering this plot. I will tell High Crusader Adelard of your findings and together, we will alert the tournament''s participants.' WHERE `Id`=14017; -- The Black Knight's Fate +UPDATE `quest_template` SET `OfferRewardText`='You are a true champion, $N, both inside the ring and on the field. We must all be vigilant against the Scourge and you are a great example to our brethren and your own people.' WHERE `Id`=13789; -- Taking Battle To The Enemy +UPDATE `quest_template` SET `OfferRewardText`='Well done. Training against the other champions is one of the best ways to prepare yourself for tournament competition. I know you''ll make the Alliance proud, $N.' WHERE `Id`=13790; -- Among the Champions +UPDATE `quest_template` SET `OfferRewardText`='It seems things are worse than we initially thought. You still made a valiant effort and saved many of The Wavecrest''s crew''s lives.' WHERE `Id`=14152; -- Rescue at Sea +UPDATE `quest_template` SET `OfferRewardText`='Oh, hello there $N. Marcia said you''d be coming by with that poor man''s missing arm.$b$bShe also gave me this bag to give you as a reward. It smells horrible, and I''m anxious to make the trade if you don''t mind.' WHERE `Id`=13836; -- Disarmed! +UPDATE `quest_template` SET `OfferRewardText`='Just what I wanted to hear! A victory in Lake Wintergrasp - even a temporary one - is crucial to our overall strategy against the Horde.' WHERE `Id`=13181; -- Victory in Wintergrasp +UPDATE `quest_template` SET `OfferRewardText`='How many of them could there possibly be? We''ve killed enough to fill ten graveyards and still they come. The situation looks grim, friend.' WHERE `Id`=13039; -- Defending The Vanguard +UPDATE `quest_template` SET `OfferRewardText`='Thank you, $N. I will begin the tests on these samples immediately. It is my hope that a cure will be found soon.' WHERE `Id`=13040; -- Curing The Incurable +UPDATE `quest_template` SET `OfferRewardText`='There are still many Argent Crusade soldiers out on that field and in Scourgeholme, $N. While your help is appreciated, there is still much left to be done.' WHERE `Id`=13008; -- Scourge Tactics +UPDATE `quest_template` SET `OfferRewardText`='<Penumbrius nods.>$B$BMy kin will help. Together we will battle the Lich King and his undead legions. +' WHERE `Id`=13044; -- If There Are Survivors... +UPDATE `quest_template` SET `OfferRewardText`='Arthas... He strikes recklessly - without care or caution. We have caught him off guard.$B$B<Highlord Tirion Fordring pauses, lost in thought for a moment.>$B$BWe will bolster our defenses and weather the storm.$B$BHow good are you with a cannon, $N?' WHERE `Id`=13045; -- Into The Wild Green Yonder +UPDATE `quest_template` SET `OfferRewardText`='My knowledge of Scourge tactics is without equal.$B$B<The Ebon Watcher peers at you.>$B$BBefore the battle for Light''s Hope Chapel, my knights and I served under the Lich King - his icy grasp controlling our every action. The light of dawn changed everything...' WHERE `Id`=13104; -- Once More Unto The Breach, Hero +UPDATE `quest_template` SET `OfferRewardText`='You have done well, $N. Keeping their numbers down will give the Argent Crusade the time that they need to set a foundation.' WHERE `Id`=13118; -- The Purging Of Scourgeholme +UPDATE `quest_template` SET `OfferRewardText`='A hard fought victory, $N! The lieutenants will be replaced, but at least for today the air about Scourgeholme stands still.' WHERE `Id`=13125; -- The Air Stands Still +UPDATE `quest_template` SET `OfferRewardText`='Heartwood by nature is resistant to disease, rot and plague. This heartwood, however, goes so far as to repel such things! The masonry, affected by the fallout of the Unbound Thicket, will work in much the same way.$B$BSoon we will break ground. ' WHERE `Id`=13130; -- The Stone That Started A Revolution +UPDATE `quest_template` SET `OfferRewardText`='Your assistance has been integral in securing the front. The first true victory of this war is close at hand - which is why our next step is the most crucial.$B$BRest assured, $N, the Scourge will not give up without a fight. Your most difficult challenge awaits.' WHERE `Id`=13139; -- Into The Frozen Heart Of Northrend +UPDATE `quest_template` SET `OfferRewardText`='Blessed Light! We have taken the pinnacle! Finally, construction of Justice Keep can begin. Highlord Fordring and the knights are already en route to our new base. You must meet them there, $N!' WHERE `Id`=13141; -- The Battle For Crusaders' Pinnacle +UPDATE `quest_template` SET `OfferRewardText`='A long and arduous journey awaits us as we make our way to the gates of Icecrown Citadel. I, and the soldiers of the Argent Crusade, wish to thank you for all that you have done. We rest easier knowing that you will fight alongside us in this cursed place.$B$B<Highlord Tirion Fordring salutes.> +' WHERE `Id`=13157; -- The Crusaders' Pinnacle +UPDATE `quest_template` SET `OfferRewardText`='Bridenbrad has contracted the plague? I cannot imagine a worse fate for one who has devoted his life to the ways of light, nor can I fathom leaving him to die without lifting a finger to help.$B$BNo, undeath shall not be his fate. We shall find a way to aid this hero.' WHERE `Id`=13072; -- A Hero Remains +UPDATE `quest_template` SET `OfferRewardText`='Hello child.$B$BI understand Tirion''s request and trust in his judgment, we will see what we can do for this Crusader Bridenbrad. What you ask is no simple task - the Scourge are not of this world, and many have failed in attempting to strip their corruption over the years.$B$BIn a being of nobility and light, all is not without hope.' WHERE `Id`=13073; -- The Keeper's Favor +UPDATE `quest_template` SET `OfferRewardText`='Tirion sent you to Remulos? I''m... I''m flattered. One does not call favors in with beings of such power idly, no matter how noble or altruistic they might be. You too are kind to have gone to such lengths on my behalf. You have my thanks.$B$BPlant the seed - I am ready.' WHERE `Id`=13075; -- The Boon of Remulos +UPDATE `quest_template` SET `OfferRewardText`='Greetings to you, $r.$B$BThe concern is clear on your face. Please tell me what troubles you.' WHERE `Id`=13077; -- The Touch of an Aspect +UPDATE `quest_template` SET `OfferRewardText`='The breath of Alexstrasza... you have gone to the dragon-queen herself? I''m extremely grateful.$B$BI understand the risks of such cleansing and I am prepared. Proceed, $c.' WHERE `Id`=13079; -- The Boon of Alexstrasza +UPDATE `quest_template` SET `OfferRewardText`='The Scourge plague is no simple foe to defeat. Alexstrasza''s words suggest that perhaps we can yet save our Bridenbrad from the unimaginable fate of the unliving should he fall, but I will not give him up so easily.$B$BThere is yet one more path of light I would like to pursue. One more being who might avert this horrible fate.' WHERE `Id`=13080; -- Hope Yet Remains +UPDATE `quest_template` SET `OfferRewardText`='<Thassarian listens as you describe your successful tests.>$B$BSo the acid worked? Good. We''ll need it when the army goes up against the reavers in force.' WHERE `Id`=13335; -- Before the Gate of Horror +UPDATE `quest_template` SET `OfferRewardText`='I was worried for a while there, $N. When he busted out the seals and penguins... Well, I didn''t know what to think to be honest. It looked pretty damn ridiculous.' WHERE `Id`=12935; -- The Amphitheater of Anguish: Tuskarrmageddon! +UPDATE `quest_template` SET `OfferRewardText`='Damn, I remember Korrak from way back in my younger days when I used to work for the Frostwolf Clan. He would never shut up! I think you just did the world a great service, $N.' WHERE `Id`=12936; -- The Amphitheater of Anguish: Korrak the Bloodrager! +UPDATE `quest_template` SET `OfferRewardText`='You did it, $N! That was the most exciting fight yet! What are you going to do with your winnings? Me? I''m going to Dalaran and blowing it all in the Underbelly. Lot of hot action going on down there!' WHERE `Id`=12948; -- The Champion of Anguish +UPDATE `quest_template` SET `OfferRewardText`='I hope they weren''t too hesitant to share the wealth. We''ve been pretty forgiving with them picking through our leftovers thus far.' WHERE `Id`=12827; -- Reclaimed Rations +UPDATE `quest_template` SET `OfferRewardText`='These will do nicely, thanks!$B$BDid you happen to see Dim out there? I sent him out a long while back and he never came back. I hope he''s alright.$B$BSpeaking of which... I wonder where Janks is...' WHERE `Id`=12818; -- Clean Up +UPDATE `quest_template` SET `OfferRewardText`='Thanks, $N! We''ll see what we can do to salvage these parts!' WHERE `Id`=12844; -- Equipment Recovery +UPDATE `quest_template` SET `OfferRewardText`='I see that Skyhopper finally got around to sending help. And none too soon I might add!$B$BWelcome, $g brother : sister;, we need your help badly!' WHERE `Id`=11707; -- Distress Call +UPDATE `quest_template` SET `OfferRewardText`='Have you heard enough? Are you prepared to act? +' WHERE `Id`=3441; -- Divine Retribution +UPDATE `quest_template` SET `OfferRewardText`='$N, by my eternal soul, it is good to see you! I don''t know why the Exodar crashed. Only those of us that were in this part of the ship remain.$B$BThere''s not much time if we''re to save everyone that we can!' WHERE `Id`=9279; -- You Survived! +UPDATE `quest_template` SET `OfferRewardText`='Regrettable that those creatures had to die so that we might live - indiscriminate killing is not the draenei way. However, the blood you gathered will replenish our healing crystals, so their deaths will not be in vain.' WHERE `Id`=9280; -- Replenishing the Healing Crystals +UPDATE `quest_template` SET `OfferRewardText`='I am Firmanvaar and you are wise to seek me out. It is my calling to provide instruction to shaman, especially those who are just beginning to learn.$B$BShamanism is only now being relearned amongst the draenei, $N. You are brave to follow its path as it is not popular amongst your kind.$B$BI will be here when you feel you are ready for further training.' WHERE `Id`=9421; -- Shaman Training +UPDATE `quest_template` SET `OfferRewardText`='Oh, thank goodness you''ve come. We have much to do.' WHERE `Id`=9371; -- Botanist Taerix +UPDATE `quest_template` SET `OfferRewardText`='You''re finished? That''s good news. Hopefully, we can find a way to avoid the killing of these mutated beasts in the future.$b$bI believe I have formed a plan that might give us an alternative solution to this problem, but I will need your help.' WHERE `Id`=10302; -- Volatile Mutations +UPDATE `quest_template` SET `OfferRewardText`='These look like fine specimens. Thank you for performing the field work. Once I can find the time to analyze these, I should be able to tell what it will take to restore the fields.' WHERE `Id`=9799; -- Botanical Legwork +UPDATE `quest_template` SET `OfferRewardText`='These will do. Thank you, $c!$B$BWhile you were out, I managed to gather some equipment together to make an analysis of the samples. This should only take a moment.' WHERE `Id`=9293; -- What Must Be Done... +UPDATE `quest_template` SET `OfferRewardText`='The Light be praised! You''ve done what only a true $g hero : heroine; could have done, $N! The draenei you saved owes their continued life to your selflessness!$B$BPlease, take this supply pouch. You look like you can use it more than I.' WHERE `Id`=9283; -- Rescue the Survivors! +UPDATE `quest_template` SET `OfferRewardText`='With many of the owlkin now inoculated, we can focus on getting out of here and not have to worry about wiping out the owlkin population in the area.$B$BHere, choose from these. You''ve done good work, and you deserve to be rewarded!' WHERE `Id`=9303; -- Inoculation +UPDATE `quest_template` SET `OfferRewardText`='Let me take a look at those.$B$BYes, I think that these will do nicely; good job, $N. The emitter is rather complex so it may take some time to finish the repairs. I''ll let you know when it''s ready.$b$bIn the meantime, you might see if Vindicator Aldar has anything he could use you for.' WHERE `Id`=9305; -- Spare Parts +UPDATE `quest_template` SET `OfferRewardText`='You are bold to seek my wisdom after what your people have done to these islands, stranger! Still, there is much to be said for your bravery, so I will impart to you some knowledge.$B$BThe earth beneath your feet forms the foundation for all things. The sky, the waters, even great fire - all rest upon its shoulders. While those others often form chaotic tempests, the earth abides. It grants strength and fortitude to the core of your being.$B$BNow you will prove yourself, shaman.' WHERE `Id`=9449; -- Call of Earth +UPDATE `quest_template` SET `OfferRewardText`='You have done well. By thinning out the restless spirits you have helped to heal the imbalance between the elements, which your people inadvertently caused.$B$BThroughout your journey as a shaman you must keep this in mind when calling upon our power. The balance must be preserved.' WHERE `Id`=9450; -- Call of Earth +UPDATE `quest_template` SET `OfferRewardText`='You have done well, $N. In helping to restore the balance of the elements at the grove, you have also created a balance between the earth element of this world and the draenei. Perhaps this will help to bring understanding to those amongst us who do not approve of our ways?$B$BI will create for you a totem through which you will be able to call on the power of earth to do your bidding. And with time, more of the mysteries of earth will be revealed to you.$B$BNow, take your totem, shaman.' WHERE `Id`=9451; -- Call of Earth +UPDATE `quest_template` SET `OfferRewardText`='Help... blood elves! They... ambushed... me. Don''t have... long.' WHERE `Id`=9309; -- The Missing Scout +UPDATE `quest_template` SET `OfferRewardText`='I thank you for dealing with the blood elf surveyor. Surely she was their leader. Rest assured, we will deal with whatever remnant of them is still nearby.$B$BPlease, take one of these weapons as a sign of my gratitude.' WHERE `Id`=9311; -- Blood Elf Spy +UPDATE `quest_template` SET `OfferRewardText`='I got it, I got it! I think I managed to fix the emitter! Here, I''ll just activate this last crystal and that should do it.$B$BTake a look at the emitter, $N. It looks like it''s beginning to work... someone is appearing!' WHERE `Id`=9312; -- The Emitter +UPDATE `quest_template` SET `OfferRewardText`='Ah, good to see you again! I''m glad that we were both able to get our emitters fixed or we might never have found one another. And don''t worry, we''ll see to it that Ammen Vale gets help and supplies.$B$BSpeaking of assistance, now that you''re here, go around and introduce yourself to the others. I know that there''s plenty to do.' WHERE `Id`=9313; -- Travel to Azure Watch +UPDATE `quest_template` SET `OfferRewardText`='Oh, you must be one of the survivors we''ve been hearing about!$b$bI''m glad that you came. Don''t worry, we will send someone to see to Aeun''s injured leg.$B$BI''m most interested in hearing all about your harrowing story of survival. You''re a brave one to have made it all the way here.' WHERE `Id`=9314; -- Word from Azure Watch +UPDATE `quest_template` SET `OfferRewardText`='Well done, $n, well done!$b$bHere, I cooked up some tenderloins while you were gone. Maybe you''d like the recipe, too?' WHERE `Id`=9454; -- The Great Moongraze Hunt +UPDATE `quest_template` SET `OfferRewardText`='Wonderful! You''re turning into quite the hunter, $n.$b$bHow would you like to look more like me? Well here is your chance! While you were out hunting, I fashioned these items out of some buck hides I had laying around. Take your pick!' WHERE `Id`=10324; -- The Great Moongraze Hunt +UPDATE `quest_template` SET `OfferRewardText`='Very good. Your efforts do much to keep the Scourge at bay. A commendation will be sent to my superior, Executor Zygand.' WHERE `Id`=356; -- Rear Guard Patrol +UPDATE `quest_template` SET `OfferRewardText`='Good, I see Ageron managed to find you, $n. Let us waste little time with small talk and pleasantries and focus on your training. There is still much you have to learn.' WHERE `Id`=1478; -- Halgar's Summons +UPDATE `quest_template` SET `OfferRewardText`='Very good, $N. I will study this book and determine the identity of that lich. You have served your Queen well.$B$B<Bethor opens the book and stares intently at its glowing pages...>$B$BAstonishing! The book you retrieved belongs to no one other than Gunther Arcanus!$B$BGunther was a skilled Necromancer in life; he and I were friends and comrades-in-arms, before the Plague. And judging from his book he has grown even more powerful in death.$B$BHis skills would be a great boon to us.' WHERE `Id`=357; -- The Lich's Identity +UPDATE `quest_template` SET `OfferRewardText`='Well done. Training against the other valiants is one of the best ways to prepare yourself for tournament competition. I know you''ll make us proud, $N.' WHERE `Id`=13750; -- The Grand Melee +UPDATE `quest_template` SET `OfferRewardText`='All of Azeroth is fortunate that Timear foresaw the Eredar lord''s arrival and that you were there in time to slay him.' WHERE `Id`=24589; -- Lord Jaraxxus Must Die! +UPDATE `quest_template` SET `OfferRewardText`='This is in better condition than I thought it''d be. Sure, it''s going to take some time to work off all the rust, the char, and the like, but I''ll not complain.' WHERE `Id`=10055; -- Waste Not, Want Not +UPDATE `quest_template` SET `OfferRewardText`='Very good. I''m sure their loss will be felt in Hellfire Citadel. Although that dark bastion looms over us and seems nigh insurmountable, it is only with bold moves like you have made that we will find victory over the fel orcs!' WHERE `Id`=10482; -- Fel Orc Scavengers +UPDATE `quest_template` SET `OfferRewardText`='You''ve come to help my tribe, $r? How unusual. There aren''t many that care about the fate of the Broken in this land. ' WHERE `Id`=10403; -- Naladu +UPDATE `quest_template` SET `OfferRewardText`='Ah, this is very nice temper indeed! And so much of it! I''ll be at work for days before I use it all!$B$BThank you, $N. Please, take this as payment.' WHERE `Id`=3042; -- Troll Temper +UPDATE `quest_template` SET `OfferRewardText`='You found it! Well done, $N! Did you have to fight Bly for it? I hope you knocked him and his band down good and hard!' WHERE `Id`=2768; -- Divino-matic Rod +UPDATE `quest_template` SET `OfferRewardText`='What the vrykul did to our scouts was a gruesome display of savagery. It was a scare tactic, meant to weaken our resolve... to send us running in fear for our lives.$B$BIt failed.$B$BWe are going to show those monsters what it means to wage war against the Alliance!' WHERE `Id`=11244; -- Rescuing the Rescuers +UPDATE `quest_template` SET `OfferRewardText`='A bit worse for the wear but still functional.$B$B<Thoralius reaches into the pouch and removes some odd looking roots.>$B$BNow to place them in the fire and inhale!$B$B<Thoralius throws the roots into the smoldering incense burner.>$B$B<Thoralius inhales deeply. His body begins to quiver.>$B$BWha... What... It cannot be... I cannot...' WHERE `Id`=11333; -- Into the World of Spirits +UPDATE `quest_template` SET `OfferRewardText`='You''ve found Pulroy. A bit too late it seems.$B$BWhile looking over the corpse you see a journal clenched tightly in Pulroy''s death grip. Upon examining the journal you read what appears to be the scribbling of a dying dwarf.' WHERE `Id`=11273; -- The Human League +UPDATE `quest_template` SET `OfferRewardText`='You''ve found Zedd. You''re no doctor but the prognosis for Zedd is most assuredly negative.$B$BIt looks as if they were preparing to feed him to the worgs. Gruesome...' WHERE `Id`=11274; -- Zedd's Probably Dead +UPDATE `quest_template` SET `OfferRewardText`='About bloody time! Pulroy and Zedd are dead.$B$BAnd Daegarn...$B$B<Glorenfeld shakes his head.>$B$BTaken by the Dragonflayer chieftain into the depths of these catacombs. I overheard that oversized mongrel mention something ''bout a sacrifice to the \"Dread King.\"$B$BThe cipher is hidden away in Daegarn''s grimy beard.$B$BWhat? Dwarves hide things in their beards all the time!' WHERE `Id`=11276; -- And Then There Were Two... +UPDATE `quest_template` SET `OfferRewardText`='You feel compelled to place the sacred blade next to the body of Ares.$B$BUpon doing this you are once again blinded by light.' WHERE `Id`=11288; -- The Shining Light +UPDATE `quest_template` SET `OfferRewardText`='You''ve done well, mate. Now that we''ve secured the tablets we can try and save Daegarn''s life and recover the cipher that will help us decode the meaning behind these ancient relics!$B$BI''ll hold on to these tablets, you rescue Daegarn. + +' WHERE `Id`=11277; -- The Depths of Depravity +UPDATE `quest_template` SET `OfferRewardText`='<Vice Admiral Keller glances over the plans.>$B$BOutstanding! By the looks of things, there are many more vrykul villages in the fjord. A different tribe of vrykul is preparing an assault on Westguard Keep. Hell, for all I know it may already be too late. We haven''t heard from Westguard in days. Either way, we must alert Westguard!' WHERE `Id`=11290; -- Dragonflayer Battle Plans +UPDATE `quest_template` SET `OfferRewardText`='<Zorek flips through the manual.>$B$BHrm, interesting...$B$BAccording to the manual, the vrykul have a special tool that allows them to control the harpoon guns with deadly accuracy. It looks a bit like the wheel of one of our ships. Furthermore, it''s portable and seems to plug into the harpoon guns like a key. We need to get our hands on one of those!' WHERE `Id`=11420; -- The Path to Payback +UPDATE `quest_template` SET `OfferRewardText`='Many men and women died to recover this blade. Alas, I fear valiant Ares will not be the last.$B$BBut you do the Light''s work, hero. This sacred blade will be wielded by Lord Tirion Fordring himself. Even now the Argent Crusade works toward Icecrown. Lord Fordring has vowed that he will tear down the walls of the cursed place himself! And with the blade, he just might stand a chance against the Lich King.$B$BLord Fordring remains our greatest hope.' WHERE `Id`=11289; -- Guided by Honor +UPDATE `quest_template` SET `OfferRewardText`='Nicely done, $g old chap : m''lady;!' WHERE `Id`=194; -- Raptor Mastery +UPDATE `quest_template` SET `OfferRewardText`='Thank you, $c... thank you!$B$BYou''ve given me the satisfaction of knowing that the coward who made me into this will rot for all eternity as surely as I will.$B$BNow leave before I lose control of myself and cut you down.' WHERE `Id`=13059; -- Revenge for the Vargul +UPDATE `quest_template` SET `OfferRewardText`='You discovered and put an end to the doctor''s machinations.$B$B<The banshee-controlled witch smiles and places a large hand gently upon your shoulder.>$B$BThat''s a fine poke in the eye for the Lich King, but I think we can do better.' WHERE `Id`=13043; -- The Sum is Greater than the Parts +UPDATE `quest_template` SET `OfferRewardText`='$N is my bestest little $r!' WHERE `Id`=12992; -- Crush Dem Vrykuls! +UPDATE `quest_template` SET `OfferRewardText`='<The duke looks at you a moment and nods.>$B$BYou''re inflicting horrible mental trauma on the Jotunheim vrykul. This is where they were first reawakened. It is a place of significant importance to them, second only to Ymirheim.$B$BYou must keep up the pressure there while I hold the vault from the assault of the Lich King.' WHERE `Id`=13084; -- Vandalizing Jotunheim +UPDATE `quest_template` SET `OfferRewardText`='You got both our foodstuff AND our research equipment back! You''ve not only saved the expedition, you''ve also saved our lives. I and the rest of my team can''t thank you enough; we just might make it here for a while now thanks to you.$B$BWhile we don''t have much, I''m certainly not going to leave you high and dry for the invaluable help you''ve given us. Thank you, $N - you''ve got a friend in Marshal Expeditions! +' WHERE `Id`=3881; -- Expedition Salvation +UPDATE `quest_template` SET `OfferRewardText`='Yes, this will do nicely. You''ve been a great help... I wish I could give you more than this, but being virtually stranded in the middle of a savage land does limit what I can and cannot give. Rest assured though - the research done here would not have been possible without your assistance!' WHERE `Id`=3883; -- Alien Ecology +UPDATE `quest_template` SET `OfferRewardText`='This will do nicely, $N. It seems Lar''korwi eats well these days. Although, I wonder where he found a threshadon in this area. Odd.$B$BRegardless, I will hold onto this until you are ready for your confrontation with the beast. Do not worry for my safety--I am sure you''ve angered Lar''korwi enough that he will not kill me until after he''s tasted your flesh.' WHERE `Id`=4290; -- The Fare of Lar'korwi +UPDATE `quest_template` SET `OfferRewardText`='You did it! You actually found it!$B$BI don''t know... I don''t know how to thank you!' WHERE `Id`=12624; -- It Could Be Anywhere! +UPDATE `quest_template` SET `OfferRewardText`='What a relief to hear that the Venture Company will trouble us no more. You have my thanks, and that of Hemet for dealing with this problem. A game hunter cannot, in good conscience, lift her weapon against another person.' WHERE `Id`=12525; -- Wipe That Grin Off His Face +UPDATE `quest_template` SET `OfferRewardText`='The professor sent you my way? All right.' WHERE `Id`=12696; -- Aerial Surveillance +UPDATE `quest_template` SET `OfferRewardText`='Excellent! ' WHERE `Id`=12699; -- An Embarassing Incident +UPDATE `quest_template` SET `OfferRewardText`='Thank you, this will go far to treat our soldiers'' wounds.' WHERE `Id`=13201; -- Healing with Roses +UPDATE `quest_template` SET `OfferRewardText`='You are a brave one, $N. I hope you didn''t lose any extremities making your fishing spot. If you''ve still got the fishing bug, come back tomorrow and we''ll talk some more.' WHERE `Id`=13833; -- Blood Is Thicker +UPDATE `quest_template` SET `OfferRewardText`='<Mariel accepts the orders and the captured seeing crystal and examines both.>$B$BGood work, $N, and quick thinking. I''m sure the theft of this trinket won''t slow them down for long, but I think you''ve bought us time to warn the leaders of the Horde and Alliance about the impending attacks.' WHERE `Id`=24442; -- Battle Plans Of The Kvaldir +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=8676; -- Wildmane the Elder +UPDATE `quest_template` SET `OfferRewardText`='Wonderful! You found it! And what''s just as important--Velratha no longer has it! Thank you, $N. I am forever in your debt!$B$BAnd if I sounded a little... mean before, pay it no mind. You''ll find me a much nicer person to those who haven''t stolen from me.' WHERE `Id`=2846; -- Tiara of the Deep +UPDATE `quest_template` SET `OfferRewardText`='Ah! Longbeard sent you with a load of helmets! Hooray!$B$BNow maybe we can talk a pilot into driving our car...' WHERE `Id`=1179; -- The Brassbolts Brothers +UPDATE `quest_template` SET `OfferRewardText`='<A fierce glow emanantes from all of Kilix''s eyes as he stares at the husk.>$b$bIt is DONE!$b$b$R! Your name shall be recorded in the history of our people.$b$bI am in your debt....' WHERE `Id`=13167; -- Death to the Traitor King +UPDATE `quest_template` SET `OfferRewardText`='<A gentle ringing fills your head as you approach the naaru.>$B$BI know why you have come.' WHERE `Id`=13081; -- The Will of the Naaru +UPDATE `quest_template` SET `OfferRewardText`='<As you approach Crusader Bridenbrad, you cannot help but notice that his skin has taken on a pale hue and his breaths are shallow. It is clear that he has little time left.>$B$BYou have returned to me, $c. I must admit... it is good to see you again... your face renews my hope that this land will be free of Arthas''s grasp one day soon. I''m proud to have met you...$B$B<Bridenbrad''s words trail off, a dim smile on his face. As life seems to slip from him, a gentle ringing fills your ears.>' WHERE `Id`=13082; -- The Boon of A'dal +UPDATE `quest_template` SET `OfferRewardText`='<Captain Bartlett salutes.>$B$BHe was a damn fine soldier. Damn the Horde and damn the Scourge!' WHERE `Id`=13225; -- The Skybreaker +UPDATE `quest_template` SET `OfferRewardText`='Really, $c?$b$bNothing notable to report?$b$b<Thassarian notices the abomination remains splattered across your clothes and smiles.>$b$bI beg to differ...' WHERE `Id`=13287; -- Poke and Prod +UPDATE `quest_template` SET `OfferRewardText`='Yes, yes, yes! A thousand times, hello!' WHERE `Id`=13383; -- Killohertz +UPDATE `quest_template` SET `OfferRewardText`='I could hear your explosions from here, $N. How did the shields work? Did they keep your bomber intact?$B$BI hope they did, because now I have more missions for you....' WHERE `Id`=13380; -- Leading the Charge +UPDATE `quest_template` SET `OfferRewardText`='Welcome to hell, soldier.$B$BMy men are leading the assault on the gate from this position, and we''re dropping some infiltrators in the city via air - we need more people on both fronts. I have a feeling that this attack will be going on for some time.' WHERE `Id`=13341; -- Joining the Assault +UPDATE `quest_template` SET `OfferRewardText`='Hail, $N. Thassarian mentioned you''d be dropping by. Any friend of Thassarian''s is my friend. Well, any living friend of Thassarian, that is... He does keep odd company.' WHERE `Id`=13386; -- Exploiting an Opening +UPDATE `quest_template` SET `OfferRewardText`='You''re as good as Thassarian said. Good job!' WHERE `Id`=13387; -- Securing the Perimeter +UPDATE `quest_template` SET `OfferRewardText`='These bombs look pretty potent. They should at least put a dent in the surrounding structure.' WHERE `Id`=13388; -- Set it Off! +UPDATE `quest_template` SET `OfferRewardText`='This pulsing object is covered in a thick layer of ice. It shimmers strangely beneath the water.' WHERE `Id`=13389; -- A Short Fuse +UPDATE `quest_template` SET `OfferRewardText`='I saw him get rid of it, you know? He threw it all the way down here.$B$BSaid he wouldn''t need it anymore. Said it made him weak.' WHERE `Id`=13390; -- A Voice in the Dark +UPDATE `quest_template` SET `OfferRewardText`='What are you waiting for? You have to rub it on you!$B$BQuick! Or he''ll see you!' WHERE `Id`=13391; -- Time to Hide +UPDATE `quest_template` SET `OfferRewardText`='It''s you, $N! We thought you were a goner.$B$BThat explosion of yours put quite a bit of hurt on the Scourge. Nearly took Captain''s Kendall''s eyebrows off in the process...' WHERE `Id`=13392; -- Return to the Surface +UPDATE `quest_template` SET `OfferRewardText`='The demolisher has seen better days, but the structure hasn''t suffered any permanent damage. The parts you obtained should be enough to get it running again, at least temporarily.' WHERE `Id`=13393; -- Field Repairs +UPDATE `quest_template` SET `OfferRewardText`='You see? You killed your fair share, but for every one you destroyed, another rose from the dirt to take its place.$B$BYou don''t know what you''re up against, $N. Let me show you.' WHERE `Id`=13394; -- Do Your Worst +UPDATE `quest_template` SET `OfferRewardText`='The prince''s true power wasn''t his ability to make armies out of corpses... that was easy.$B$BBut killing his own men, with whom he''d shared many battles... the prince''s true power was his ability to do what had to be done.' WHERE `Id`=13395; -- Army of the Damned +UPDATE `quest_template` SET `OfferRewardText`='Nice shooting, $N. The Scourge never had a chance.$B$BAre you feeling okay? You look like you''ve seen a ghost. Not that it would be an unusual thing around these parts, now that I think about it.' WHERE `Id`=13396; -- Futility +UPDATE `quest_template` SET `OfferRewardText`='Nice job, $N. You make the rest of us look bad!' WHERE `Id`=13397; -- Sindragosa's Fall +UPDATE `quest_template` SET `OfferRewardText`='Nothing to it, eh? Any intelligent being should have little trouble controlling lesser undead. I suspect only the likes of a true necromancer could use these to sieze control of any of the more powerful undead. That won''t be a problem though - I can already think of quite a variety of destruction we can wreak with even the most paltry minions.$B$BShall we have at it then?' WHERE `Id`=13168; -- Parting Gifts +UPDATE `quest_template` SET `OfferRewardText`='Quiet! I''m in a delicate juncture and mustn''t be disturbed!$B$BOne moment...' WHERE `Id`=1947; -- Journey to the Marsh +UPDATE `quest_template` SET `OfferRewardText`='Ah, so you''ve been speaking with MacKinley, have you?$B$BIt''s not what he thinks! I''m not afraid to give him some Steamwheedle Bilge Rum...$B$BI just don''t have any rum to give him!' WHERE `Id`=2872; -- Stoley's Debt +UPDATE `quest_template` SET `OfferRewardText`='Out-frikkin-standing! As of right now $T Civvy : Civvy; $N, you are my favorite person on the sorry remains of this sorry planet!$B$BI''m sure that the eggheads are going to wet themselves when I hand that blood over to them for study. Who knows, maybe we''ll find a new weapon in the fight against those damned fel orcs?' WHERE `Id`=9589; -- The Blood is Life +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=8619; -- Morndeep the Elder +UPDATE `quest_template` SET `OfferRewardText`='Wonderful! We thank you for your generous donation, $N!' WHERE `Id`=7807; -- A Donation of Wool +UPDATE `quest_template` SET `OfferRewardText`='Wonderful! We thank you for your generous donation, $N!' WHERE `Id`=7808; -- A Donation of Silk +UPDATE `quest_template` SET `OfferRewardText`='Vanira''s frogs be tellin'' de truth, den? Dis tiger be a druid and an ally? We couldn''t be hopin'' for a better outcome. Dis be a good omen for de coming battle.' WHERE `Id`=25470; -- Lady Of Da Tigers +UPDATE `quest_template` SET `OfferRewardText`='$n, you''d be a mighty warrior and a fierce commrade to da Darkspear trolls. De Echo Isles are OURS now and we couldn''ta done it wit''out ya.$B$BTake dis cloak. Wear it wit pride. You''d be a member of da tribe now!$B$BIn no time, da trolls will have a home again and we have you to thank for dat.' WHERE `Id`=25445; -- Zalazane's Fall +UPDATE `quest_template` SET `OfferRewardText`='15.9 pounds! That may be a new record for blood and gut weight on apparel! Congratulations, $c!' WHERE `Id`=7729; -- JOB OPPORTUNITY: Culling the Competition +UPDATE `quest_template` SET `OfferRewardText`='Ye''re a good $g lad:lass;, ye are. I got ye a lil'' present fer yer troubles.' WHERE `Id`=7723; -- Curse These Fat Fingers +UPDATE `quest_template` SET `OfferRewardText`='I never thunk I''d be lookin'' at thish ugly mug again!$B$BHe acshually looksh better without the resht o'' him attached.$B$BHere''s yer reward *hic*, $r.' WHERE `Id`=7701; -- WANTED: Overseer Maltorius +UPDATE `quest_template` SET `OfferRewardText`='Wonderful! Those sleepy Dark Irons will head back to their homes in the Depths to get some rest, greatly slowing down the productivity of the Slag Pit.' WHERE `Id`=7702; -- Kill 'Em With Sleep Deprivation +UPDATE `quest_template` SET `OfferRewardText`='There is one final task that you must complete. +' WHERE `Id`=3453; -- The Torch of Retribution +UPDATE `quest_template` SET `OfferRewardText`='Are you prepared to make your strike? +' WHERE `Id`=3462; -- Squire Maltrake +UPDATE `quest_template` SET `OfferRewardText`='It is glorious! Is it not glorious master? ' WHERE `Id`=3463; -- Set Them Ablaze! +UPDATE `quest_template` SET `OfferRewardText`='Oh, this is great! Nice feel to it too!$B$BWhat? Oh, yeah... geologists. Got ''em good, did ya? I can''t thank ya enough, $N. That''ll give me some time to finish up in here... Thanks again, $N.' WHERE `Id`=4449; -- Caught! +UPDATE `quest_template` SET `OfferRewardText`='Keep the residue pouring in!' WHERE `Id`=13662; -- Gaining Acceptance +UPDATE `quest_template` SET `OfferRewardText`='You have struck a decisive blow against the Undermarket. Their leaders will think twice before sending more cronies into the gorge.$B$BOh, and I also found nothing of use in the trader''s satchel. You may keep whatever you find inside.' WHERE `Id`=3385; -- The Undermarket +UPDATE `quest_template` SET `OfferRewardText`='Perfect! I just hope the Dalaran Destroyers finally win one!' WHERE `Id`=13107; -- Mustard Dogs! +UPDATE `quest_template` SET `OfferRewardText`='<Bouldercrag reaches out to take the ore, but then recoils.>$B$BThat ore... I can''t touch it. It seethes with unnatural energy. No creature of stone can handle it. What do they mean to do with this?' WHERE `Id`=12964; -- The Dark Ore +UPDATE `quest_template` SET `OfferRewardText`='<Bouldercrag nods grimly.>$B$BYou''ve weakened the stormforged considerably, but they''ll keep fighting. Their casualties matter nothing to them, while our defenders continue to fall. Even if it costs them a hundred or a thousand iron corpses, they''ll keep fighting until we''ve been pounded to gravel.' WHERE `Id`=12965; -- The Gifts of Loken +UPDATE `quest_template` SET `OfferRewardText`='Ruined? What d''you mean, the camp''s been ruined?$B$B<Brann clenches his fists in anger.>$B$BThose iron dwarves will pay for this! There''s little we can do now, and we have to focus on finishing the key. But once I get into the halls of Ulduar, the irons and their masters will answer for what they''ve done!' WHERE `Id`=13273; -- Going After the Core +UPDATE `quest_template` SET `OfferRewardText`='<Boktar nods in approval as you tell him how you helped Brann recover the pieces of the keystone and combine them.>$B$BBrann may prove to be just the ally we need to discover what is truly happening in Ulduar. You''ve done well in aiding him. We need all the help we can get against this Loken and his iron dwarf minions.' WHERE `Id`=13285; -- Forging the Keystone +UPDATE `quest_template` SET `OfferRewardText`='The Sons of Hodir accept your tribute, small one. You continue to prove your worth as an ally in more ways than one.' WHERE `Id`=13559; -- Hodir's Tribute +UPDATE `quest_template` SET `OfferRewardText`='Yes... these will do. Let us hope my plan works, $N.$B$BVeranus is a great drake. I''d hate to have to settle for a lesser one.' WHERE `Id`=13050; -- Veranus +UPDATE `quest_template` SET `OfferRewardText`='It''s good to have my old friend back. It appears that my luck is finally starting to change... and it''s all thanks to you, little friend.' WHERE `Id`=13051; -- Territorial Trespass +UPDATE `quest_template` SET `OfferRewardText`='So it is done.$b$bWe have heard the screams of Jormuttar as they echoed from across the valley.$b$bYou have done our people a service this day, little $r.' WHERE `Id`=13011; -- Jormuttar is Soo Fat... +UPDATE `quest_template` SET `OfferRewardText`='We''re here, $N. My brother''s forces will learn the meaning of defeat today.' WHERE `Id`=13057; -- The Terrace of the Makers +UPDATE `quest_template` SET `OfferRewardText`='It''s a good start. But my brother''s forces will not take long to regroup. We must make our victory a decisive one.' WHERE `Id`=13005; -- The Earthen Oath +UPDATE `quest_template` SET `OfferRewardText`='One by one, my brother''s servants have fallen. Loken''s insurrection will soon come to an end.' WHERE `Id`=13035; -- Loken's Lackeys +UPDATE `quest_template` SET `OfferRewardText`='No... it cannot be...$B$BNo one can defeat Thorim in single combat. Not a giant, nor a beast... no one! Especially not that coward of a brother of his.$B$BOn my forefathers'' names, this I swear...$B$BLoken will pay for this!' WHERE `Id`=13047; -- The Reckoning +UPDATE `quest_template` SET `OfferRewardText`='The heavens, in their countless stars, hold answers to earthly mysteries, $N. Might, then, the wise, and the lucky, gaze up and find truth?' WHERE `Id`=8727; -- Farwhisper the Elder +UPDATE `quest_template` SET `OfferRewardText`='Human children born of vrykul? And Ymiron ordered the deaths of all human born offspring?$B$B<Thoralius goes silent for a moment.>$B$BAs much as I wish to deny what is so plainly presented to me, I cannot. There is no extinct \"missing link\" to humans as the Explorers'' League proposed. The vrykul are the missing link. They are the progenitors of humanity.' WHERE `Id`=11344; -- Anguish of Nifflevar +UPDATE `quest_template` SET `OfferRewardText`='This is quite a find, $N. I can''t have you selling this to anyone else, so I''m willing to offer generously.' WHERE `Id`=24431; -- Waterlogged Recipe +UPDATE `quest_template` SET `OfferRewardText`='You have rescued the sacred text!$b$bYour journey was long and acquiring the book was undoubtedly no easy task. But the dwarves of Ironforge stand to benefit from your success.$b$bThank you, $n, on behalf of the Explorers'' League.' WHERE `Id`=1050; -- Mythology of the Titans +UPDATE `quest_template` SET `OfferRewardText`='So Stormpike sent you, did he? Good.$B$BI have a big task for you...' WHERE `Id`=707; -- Ironband Wants You! +UPDATE `quest_template` SET `OfferRewardText`='Fantastic, I thought you looked to be the heroic type! We''ve got our work cut out for us $N, I''m not going to lie to you. If we stay focused on the task at hand, we should be able to come out on top.$B$BNow, let me bring you up to speed on what''s been going on...' WHERE `Id`=3523; -- Scourge of the Downs +UPDATE `quest_template` SET `OfferRewardText`='You have my thanks.$B$BThis has been a brutal operation, but we haven''t had any great options otherwise - they''re being equally as unforgiving to our aerial assault. We need to rout these vrykul if we''re going to stand any chance of pressing on in Icecrown.$B$BWe''re likely to need more help later. Please lend yourself to the battle again should the chance present itself.' WHERE `Id`=13284; -- Assault by Ground +UPDATE `quest_template` SET `OfferRewardText`='Let''s see here... what do we have...$B$B<Keritose buries his head in the papers for a bit, seemingly gleaning little that he did not already know. Suddenly he finds what he is looking for...>$B$BMalykriss! The Vile Hold. It seems Arthas did not take the loss of his death knights so well... I''m not exactly sure what he''s doing with all of that saronite, but I have a feeling he might be overcompensating for something.$B$BThat boy is not used to losing.' WHERE `Id`=13174; -- Amidst the Confusion +UPDATE `quest_template` SET `OfferRewardText`='I''ve chained the wretch to the post over there and I''ll look into getting my hands on more of them.$B$BNow let''s make some use of that eye.' WHERE `Id`=13143; -- New Recruit +UPDATE `quest_template` SET `OfferRewardText`='Excellent work. It seems more death knights remained loyal to Arthas than I initially thought.$B$BHe certainly is sparing nothing in his attempt to replace Acherus. A pure saronite citadel would be hard to destroy indeed. There''s no need to destroy it though... we can halt production and put down these death knight leaders here and now, before they become a real threat.$B$BMost importantly, we need to disrupt them enough to get those death knights away from from the leaders so that we can make our strike.' WHERE `Id`=13145; -- The Vile Hold +UPDATE `quest_template` SET `OfferRewardText`='Yay, yay! $N is best proto-drake stealer.$B$BYou come back tomorrow and we make more fire!!!' WHERE `Id`=13071; -- Vile Like Fire! +UPDATE `quest_template` SET `OfferRewardText`='Well done, $N. Let them see the desecrated corpses of their fallen comrades and think twice about striking at us!$B$BIf you come back tomorrow, I will make certain to have more banners prepared for you.' WHERE `Id`=12995; -- Leave Our Mark +UPDATE `quest_template` SET `OfferRewardText`='You are a true champion for the cause, $N!$B$BWon''t you please come speak to me again tomorrow? I''m certain that there will be more of those nasty proto-drakes to shoot down.' WHERE `Id`=13069; -- Shoot 'Em Up +UPDATE `quest_template` SET `OfferRewardText`='<Thassarian nods.>$B$BGood. It''s not much protection, but it''s better than nothing. That gate is still the perfect choke point if the Scourge commanders know what they''re doing. We must gain control of as much of the surrounding area as possible.' WHERE `Id`=13332; -- Raise the Barricades +UPDATE `quest_template` SET `OfferRewardText`='Words cannot describe what I''m feeling at the moment, $N. My revenge is complete and there is naught else for me to do.$B$BIf only I could be there when the Lich King is finally taken down.$B$BDon''t fool yourself though, Jotunheim is far from ''dealt'' with. I will remain in possession of this witch until such time as the vrykul are no longer a threat.$B$BLook around, there are many items of value in this cave. Take your pick.' WHERE `Id`=13142; -- Banshee's Revenge +UPDATE `quest_template` SET `OfferRewardText`='You have bested our finest warriors. Your name is renowned, $N.$B$BPerhaps you think that this concerns me: it does not. If they can fall to you then they are not worthy and should be nothing but lowly vargul!$B$BBut perhaps I can give you and your friends different sport. Valhalas is also a place for combat of all types with many different kinds of foes.$B$BSpeak to me again when you and your friends are ready to proceed. We shall see if you are truly worthy.' WHERE `Id`=13213; -- Battle at Valhalas +UPDATE `quest_template` SET `OfferRewardText`='It''s good to have someone competent running missions, $N. If only we had an army of $cs like you, we could show the Horde what we''re made of. These captured reports will help us to maintain the upper hand in this fight. We may be down, but we''re far from out.' WHERE `Id`=13314; -- Get the Message +UPDATE `quest_template` SET `OfferRewardText`='New blood.$B$B<The vrykul death knight spits on the ground at your feet.>$B$BYou all think that you have what it takes to fight here.$B$BYou are nothing before the might of the vrykul and the Scourge!$B$BStill, you did manage to defeat six incompetent corpses, so you must have some skill in you. Not likely enough for the next challenge though.' WHERE `Id`=13214; -- Battle at Valhalas: Fallen Heroes +UPDATE `quest_template` SET `OfferRewardText`='You want me to be impressed by the fact that you and your friends were able to bring down a lone Nerubian priest?$B$BGet out of my sight before I summon my ghouls upon you!' WHERE `Id`=13215; -- Battle at Valhalas: Khit'rix the Dark Master +UPDATE `quest_template` SET `OfferRewardText`='The defeat of one of the hyldnir is mildly impressive, $r, but you did have the help of your friends.$B$BYou''re lucky that her drake didn''t get involved.' WHERE `Id`=13216; -- Battle at Valhalas: The Return of Sigrid Iceborn +UPDATE `quest_template` SET `OfferRewardText`='I''m starting to respect your prowess in the ring, $N. Now I really don''t like you.$B$BI would much rather have preferred to see you and your friends stuck to the bottom of that flesh giant''s foot!' WHERE `Id`=13217; -- Battle at Valhalas: Carnage! +UPDATE `quest_template` SET `OfferRewardText`='I don''t know what trickery it was that you used to bring down the thane -- I couldn''t see it from this angle -- but I can assure you that you will not survive your next match.$B$BYes, I know who it is. Run, little $r. Flee to the far corners of the world.$B$BOr stay and die. It matters little to me.' WHERE `Id`=13218; -- Battle at Valhalas: Thane Deathblow +UPDATE `quest_template` SET `OfferRewardText`='Your defeat of Prince Sandoval sickens me. An unwashed peasant such as yourself should have willingly given over $g his : her; life simply for the chance to meet him and kneel at his feet.$B$BYou''ve earned your damned reward. Be quick about your choosing.' WHERE `Id`=13219; -- Battle at Valhalas: Final Challenge +UPDATE `quest_template` SET `OfferRewardText`='This will allow us to patch up more of the fallen. Thank you, $N, on behalf of all who defend the refuge.' WHERE `Id`=12930; -- Rare Earth +UPDATE `quest_template` SET `OfferRewardText`='You''ve done well, $N!' WHERE `Id`=192; -- Panther Mastery +UPDATE `quest_template` SET `OfferRewardText`='So the great Bhag''thera is dead! Cheers to you, $N. You are a mighty $c indeed!' WHERE `Id`=193; -- Panther Mastery +UPDATE `quest_template` SET `OfferRewardText`='Ho ho!! We have ourselves a true raptor slayer! Nicely done, $g old chap : fair lady;!' WHERE `Id`=196; -- Raptor Mastery +UPDATE `quest_template` SET `OfferRewardText`='$G Master : Mistress; $N, the raptor slayer!$b$bHas a nice ring to it, eh?' WHERE `Id`=197; -- Raptor Mastery +UPDATE `quest_template` SET `OfferRewardText`='Bloody well done! Right-o! Congratulations, $N, for succeeding where others have failed.$b$bI am honored to count you as a comrade of our great hunting party here. No one will ever doubt your expertise in hunting and tracking!$b$bCheers to you, I say! Cheers!' WHERE `Id`=208; -- Big Game Hunter +UPDATE `quest_template` SET `OfferRewardText`='You''re a good $g man : woman;, $N. We''re fortunate that you happened to stop by.$B$BStick around a while. I''m sure that we have much that a capable $c such as yourself can do.' WHERE `Id`=12740; -- Parachutes for the Argent Crusade +UPDATE `quest_template` SET `OfferRewardText`='<The dwarf sergeant warily eyes the orders in your hand.>$B$BAre those new orders for me, $g mister : miss;?' WHERE `Id`=12505; -- New Orders for Sergeant Stackhammer +UPDATE `quest_template` SET `OfferRewardText`='Perfect! I just hope the Dalaran Destroyers finally win one!' WHERE `Id`=13116; -- Mustard Dogs! +UPDATE `quest_template` SET `OfferRewardText`='Good. $n, I know of you. You''ll be perfect for these tasks.$B$BWe''ve been afforded a rare chance to delve into Icecrown Citadel, but we must move quickly if we''re to avoid Arthas'' notice.' WHERE `Id`=24506; -- Inside the Frozen Citadel +UPDATE `quest_template` SET `OfferRewardText`='Well done, $N. Mounted combat is often hard to pick up for those accustomed to fighting on foot. I have no doubt that you''ll continue to improve with practice, which is more than I can say for some warriors.' WHERE `Id`=13677; -- Learning The Reins +UPDATE `quest_template` SET `OfferRewardText`='You have shown yourself a capable combatant, $N and you will serve as an example to the rest of the aspirants who clamor to compete on behalf of the Horde.' WHERE `Id`=13676; -- Training In The Field +UPDATE `quest_template` SET `OfferRewardText`='So you''re saying this knight''s story is a sham? Most suspicious. Dishonorable at the least, and murderous at the worst. Still, we can''t confront him until we know for certain whether he was involved in these murders.$B$BDo nothing to arouse his suspicions, $N. Discretion will serve us well as we continue to investigate.' WHERE `Id`=13634; -- The Black Knight of Silverpine? +UPDATE `quest_template` SET `OfferRewardText`='Welcome to Orgrim''s Hammer.$B$BFrom here we are laying our groundwork for the assault on Arthas. There''s a lot of preparation to be done, but before we can get into the real meat of it, we want to make sure that the Argent Crusade is adequately reinforced - we''re going to need their help later.$B$BIf you have not already, speak to Brother Keltan on the main deck.' WHERE `Id`=13419; -- Preparations for War +UPDATE `quest_template` SET `OfferRewardText`='Perhaps now we can really get something done. Don''t be fooled though, the Lich King can still ''see'' through his Scourge minions.$B$BThat''s why you''re here.' WHERE `Id`=12892; -- It's All Fun and Games +UPDATE `quest_template` SET `OfferRewardText`='Quickly, hand them to me and stay out of sight!$B$BThe rod, the hook, and the rope are all very self-evident in their usage when combined. I just need to infuse the result with the essences and we''ll be ready to proceed.$B$BIt''s all very mundane in its composition, but extraordinary in its application!' WHERE `Id`=12891; -- I Have an Idea, But First... +UPDATE `quest_template` SET `OfferRewardText`='We will put those three to good use once we finally take the vault.$B$BSpeaking of which....' WHERE `Id`=12893; -- Free Your Mind +UPDATE `quest_template` SET `OfferRewardText`='Careful, now. Keep that plate as far away from me as you can. Even being in its presence is enough to inflict pain.$B$BBut you''re right, $N, these are gigantic armor plates for a war golem of normal size. What would the stormforged be doing with them? There''s only one way to find out.' WHERE `Id`=12979; -- Armor of Darkness +UPDATE `quest_template` SET `OfferRewardText`='There may be hope for victory, $N. We have never been able to sustain an attack on the stormforged, but with your efforts, Valduran may yet fall!' WHERE `Id`=12978; -- Facing the Storm +UPDATE `quest_template` SET `OfferRewardText`='Always more questions than answers, eh, $g lad:lass;? +' WHERE `Id`=13207; -- Halls of Stone +UPDATE `quest_template` SET `OfferRewardText`='So... here I sat, basking in the awesomeness that is me, and in the distance, I hear a pop! Then another! Then a dozen more! And a smile crept onto my face at the thought of all those magnataur and snobolds eagerly rushing to their own deaths.$B$BWas it glorious?' WHERE `Id`=12820; -- A Delicate Touch +UPDATE `quest_template` SET `OfferRewardText`='Excellent!$B$B<A fierce grin creeps onto Ricket''s face.>$B$BLet the destruction begin!' WHERE `Id`=12821; -- Opening the Backdoor +UPDATE `quest_template` SET `OfferRewardText`='I know that we Forsaken appear monstrous to your eyes, but I assure you we mean your people no harm. We are here because of a common enemy: Dar''Khan the traitor! He has returned and now commands the Scourge that are invading this land from his steadfast, Deatholme, to the south.$B$BOur leader, Lady Sylvanas Windrunner, originally hails from these lands, and in fact used to be an elf. She has a history with Dar''Khan and wants him dead as much as your people do.$B$BWe will defeat him together, $c!' WHERE `Id`=9327; -- The Forsaken +UPDATE `quest_template` SET `OfferRewardText`='Oh good, there you are! And just in time... there is much to be done!' WHERE `Id`=9758; -- Return to Arcanist Vandril +UPDATE `quest_template` SET `OfferRewardText`='Very well, these will have to do. No, don''t describe them crawling around, I don''t want to know! I''ll work my magic upon these legs and they''ll turn out quite tasty. A little spice here, a pinch of herb there, and then of course some arcane ingredients, and voila, a meal fit for a queen... or in this case, a dame.$B$BYour service has been adequate, $c. Here, take this recipe and some samples.' WHERE `Id`=9171; -- Culinary Crunch +UPDATE `quest_template` SET `OfferRewardText`='My family... What have I done... What could I have done?$b$bWhy must I be punished so?' WHERE `Id`=10428; -- The Missing Fisherman +UPDATE `quest_template` SET `OfferRewardText`='[Furbolg] The prophecy spoke of one that would rise and deliver us from the oppressive grasp of Bristlelimb -- that the spirits themselves would herald the arrival of this hero.$B$BAnd now, you have come.$B$BI humble myself before you, great one.' WHERE `Id`=9544; -- The Prophecy of Akida +UPDATE `quest_template` SET `OfferRewardText`='You''re a resourceful one! With our navigation gear, we can figure out just how far we''ve veered off course.$b$bBut wait, what''s this? There''s something rolled up in the map. Let me see...$b$bThese are orders from Mogul Razdunk of the Venture Company. According to these plans, they''re here to strip-mine the island of the crystal wreckage, then hijack our ships once they''re finished.$b$bBy Bronzebeard''s bushy brow! This is why they forced us to land? How could they know of our plans?$b$bI smell a traitor...' WHERE `Id`=9506; -- A Small Start +UPDATE `quest_template` SET `OfferRewardText`='Bless yer heart, stranger. This''ll go a long ways in liftin'' the morale o'' the crew. +' WHERE `Id`=9512; -- Cookie's Jumbo Gumbo +UPDATE `quest_template` SET `OfferRewardText`='My pappy would be proud! His boy strikes it big at the first set of night elf ruins he comes across... With your help, of course. Yes, don''t worry, I won''t leave you out of the discovery. Your name is $N, right? They''ll learn all about you in Ironforge. +' WHERE `Id`=9523; -- Precious and Fragile Things Need Special Handling +UPDATE `quest_template` SET `OfferRewardText`='<Gurf spits on the clump of fur and tries to affix it to the hairless patch on his backside.>$B$BThis will have to do for now! Hopefully one of the shaman will be able to repair the damage.' WHERE `Id`=9564; -- Gurf's Dignity +UPDATE `quest_template` SET `OfferRewardText`='You place the gem inside the essence font.$B$B\"Thank you mortal, you have - no... this, this cannot be! No! The corruption of this accursed god even taints the sanctity of a Green Dragonflight essence font! No please, I feel my essence ripping from me! THE PAIN! I feel the grip of an eternal nightmare taking hold on me...\"$B$B\"Mortal, I implore you! Find one of the Green Dragonflight to stop this... help me... I am chained in darkness... forever in agony... please do not torture...\"' WHERE `Id`=3373; -- The Essence of Eranikus +UPDATE `quest_template` SET `OfferRewardText`='Well done, $N. I am pleased. You have done a great thing here today.$B$BU''cha was one of the greatest apes I had ever seen. The fact that you have bested his strength speaks well of your own strength... and courage.$B$BIt is only fitting that I give you this as a sign of respect. You have earned it.' WHERE `Id`=4301; -- The Mighty U'cha +UPDATE `quest_template` SET `OfferRewardText`='The Earth Mother be praised! You''ve done it! Fair play to you, $N. You have proven to be a great hunter in your own right. Your spirit is strong. Your bravery unmatched. And your strength has been fortified. I bow down to your skills.$B$BOnly the greatest of my ancestors could have accomplished something so incredible. Congratulations.' WHERE `Id`=4292; -- The Bait for Lar'korwi +UPDATE `quest_template` SET `OfferRewardText`='I''ll need one vial to make sure that this is truly the elixir... Yes... This is the stuff. ' WHERE `Id`=3909; -- The Videre Elixir +UPDATE `quest_template` SET `OfferRewardText`='Thanks so much, $N! Now I can get back to work here.$B$BDid you find anything of interest at the Winterfall camp?' WHERE `Id`=5082; -- Threat of the Winterfall +UPDATE `quest_template` SET `OfferRewardText`='This thing... it is in the shape of a Winterfall Ritual Totem, but it has been twisted by forces I cannot begin to comprehend. Whatever taint that has set the Winterfall against us is surely present in this object.$B$BDivine wisdom has brought both this and you to us, $N. We will study this object intently; perhaps one day, the Winterfall will rage against us no longer.$B$BThank you, friend - please accept these offerings in exchange for your benevolence.' WHERE `Id`=8471; -- Winterfall Ritual Totem +UPDATE `quest_template` SET `OfferRewardText`='Thank you again, $C, for rescuing me from Baltharus''s clutches!$B$BThere is still much work to be done, however....' WHERE `Id`=26013; -- Assault on the Sanctum +UPDATE `quest_template` SET `OfferRewardText`='It''s locked, isn''t it? It looks pretty ordinary.$B$B<Lieutenant Dumont Shakes the chest, producing a rattling wooden sound.>$B$BNo matter, I suppose. If this gets us the edge we need against the Horde, then I could care less if the cure for the Plague was in there. ' WHERE `Id`=12292; -- Local Support +UPDATE `quest_template` SET `OfferRewardText`='With Malygos defeated, the Nexus War should come to a swift conclusion. You have the gratitude of the Kirin Tor, $N.' WHERE `Id`=24584; -- Malygos Must Die! +UPDATE `quest_template` SET `OfferRewardText`='Shiver me timbers and timber me shivers! Ye found me beautiful eye! Let''s see if she still fits.$b$b$n ho! Blimey, I can see!!' WHERE `Id`=576; -- Keep An Eye Out +UPDATE `quest_template` SET `OfferRewardText`='Good show, $n! And just before I need to ship out too! Can''t thank you enough, old friend.' WHERE `Id`=587; -- Up to Snuff +UPDATE `quest_template` SET `OfferRewardText`='Perfect, $n. Now that we know their plan, it''s just a matter of time.$b$bAnd to think the fools have dropped anchor just off the cape....' WHERE `Id`=604; -- The Bloodsail Buccaneers +UPDATE `quest_template` SET `OfferRewardText`='Witch Doctor Unbagwa like Gorilla Fangs! For you I talk to spirits. Make Mokk the Savage come.$b$bYou protect Witch Doctor Unbagwa from other Gorilla-beast though or no Mokk for you!' WHERE `Id`=349; -- Stranglethorn Fever +UPDATE `quest_template` SET `OfferRewardText`='Ack! Where''d you get these? No, don''t tell me. I don''t want to know!$B$BWho sent you? Sea Wolf?' WHERE `Id`=606; -- Scaring Shaky +UPDATE `quest_template` SET `OfferRewardText`='Ah, very good! Here is your pay.$B$BAnd here is a little something extra... for your discretion.' WHERE `Id`=621; -- Zanzil's Secret +UPDATE `quest_template` SET `OfferRewardText`='Ah, what a great day for the Blackwater Raiders! Three cheers to you, $n!' WHERE `Id`=608; -- The Bloodsail Buccaneers +UPDATE `quest_template` SET `OfferRewardText`='Heh heh, well done! And when you showed Shaky those giblets, how hard did he shake?$B$BHah! He''s so easy to read, when I play cards with him I can''t help but win!$B$BThanks for your help, $N. Now it''s your turn to get paid...' WHERE `Id`=607; -- Return to MacKinley +UPDATE `quest_template` SET `OfferRewardText`='...feel strength returning....$b$bWhere might be? Booty Bay? Oh my! I had the strangest dream...$b$b...the weakness has not completely left me....' WHERE `Id`=348; -- Stranglethorn Fever +UPDATE `quest_template` SET `OfferRewardText`='What?! I got a lot better things to do then talk to the likes of you, $c. Make it worth my while or get outta my face.$B$BHuh? Bloads sent ya, huh? Well, whaddaya got for me?$B$B<Privateer Groy looks over the bundle carefully.>$B$BNot bad, not bad at all. Another bundle will make my client quite happy.$B$BI suppose yer next question''s gonna be about money, huh, $c? Of course it is!$B$BHere, take this coin and some advice: get off my docks.' WHERE `Id`=623; -- Akiris by the Bundle +UPDATE `quest_template` SET `OfferRewardText`='James Hyal, James Hyal... Why does that name sound so familiar?$b$bOf course! The Shady Rest Inn incident. If you have any information about what happened there, I would urge you to speak with Captain Vimes about it. He''s handling the investigation.' WHERE `Id`=1302; -- James Hyal +UPDATE `quest_template` SET `OfferRewardText`='What''s this? Ah! It smells like Dark Iron Ale! Drink has blurred my sight, but I can tell that you, $gsir:my lady;, are a real friend!' WHERE `Id`=4295; -- Rocknot's Ale +UPDATE `quest_template` SET `OfferRewardText`='You have the heart! Amazing! It is even more beautiful than I imagined!$B$BPlease, $N, take this as payment!' WHERE `Id`=4123; -- The Heart of the Mountain +UPDATE `quest_template` SET `OfferRewardText`='Ah, you found the tablet! And your transcription is superb! Are you sure you''re a $c and not a scribe?$B$BHere you are, $N. Here is the payment I promised.' WHERE `Id`=4296; -- Tablet of the Seven +UPDATE `quest_template` SET `OfferRewardText`='Oh my goodness, you made it! I was uncertain.$B$BYou flickered in and out of the time stream there for a moment during the fight! I thought for sure that we''d lost you!$B$BBut here you are safe and sound, with your past self rescued, on the other side of the time loop you were in.$B$BYou''re quite the temporal $g hero : heroine;, $N!' WHERE `Id`=13343; -- Mystery of the Infinite, Redux +UPDATE `quest_template` SET `OfferRewardText`='<Gerk is dying.>$B$BTh... They say these Vargul are the... the ones that weren''t found worthy by the Lich King. Can... Can you im... imagine it? Just th... think how powerful the... the... worthy must be...$B$BI''ll say a prayer for you in the hereafter, hero... May you never have to face them in number.' WHERE `Id`=12904; -- Light Won't Grant Me Vengeance +UPDATE `quest_template` SET `OfferRewardText`='A... A storm giant? I don''t know about this, $N. That sounds risky. On the other hand, I don''t think we have too many other options.$B$BIf I do this you have to promise me that you will get your giant friend to help us deal with Navarius and his cronies.' WHERE `Id`=12912; -- A Great Storm Approaches +UPDATE `quest_template` SET `OfferRewardText`='Excellent work, $n. The tremors have already begun to subside.$b$bWith any luck, your efforts have granted us sufficient time to find a way to thwart Malygos'' efforts.' WHERE `Id`=11905; -- Postponing the Inevitable +UPDATE `quest_template` SET `OfferRewardText`='Ah, that''s the spice! Now here''s some swampy good stew.' WHERE `Id`=1218; -- Marsh Frog Legs +UPDATE `quest_template` SET `OfferRewardText`='A report from an orc spy! How did you find this? No matter -- let''s see what it says...' WHERE `Id`=1220; -- Captain Vimes +UPDATE `quest_template` SET `OfferRewardText`='The freed captives have already begun returning from Blackhoof Village. The information the captain is receiving from the prisoners will give us an advantage in our next battle against the Grimtotems.$B$BYou have my thanks and that of the men. ' WHERE `Id`=11145; -- Prisoners of the Grimtotems +UPDATE `quest_template` SET `OfferRewardText`='Hm, I''m no expert with the construction of arms and armor. Their use, yes, but not their making.$b$bThis shield seems as ordinary as any, excepting the damage from the fire that engulfed the inn.' WHERE `Id`=1253; -- The Black Shield +UPDATE `quest_template` SET `OfferRewardText`='Hoofprints, eh? It is true that there is an extraordinary amount of centaur activity in the lands near the Dustwallow Marsh. In brief excursions into the Barrens, we found their camps and holdings dotting the area.$b$bI''ll send out Falgran Hastil, one of our trackers, to see if he can find where the tracks lead.' WHERE `Id`=1284; -- Suspicious Hoofprints +UPDATE `quest_template` SET `OfferRewardText`='It''s never good news when a guard''s badge is brought to me.$b$bSometimes it''s a man or woman who''s fallen in battle, and I''m left to bring the news to the grieving family. Other times we never find out what happened to them. And other times it''s even worse than that.' WHERE `Id`=1252; -- Lieutenant Paval Reethe +UPDATE `quest_template` SET `OfferRewardText`='Hello, $n. You''d like information about a specific member of the Theramore guard? Reethe, was it?$b$bJust give me a moment to find the right book.' WHERE `Id`=1259; -- Lieutenant Paval Reethe +UPDATE `quest_template` SET `OfferRewardText`='Missing? That would be Tesoran''s kind way of saying traitor.$b$bNo doubt he''s one of those fools so blindly loyal to Admiral Daelin that he turned traitor. Isn''t that a delicious irony? The deserters accuse us of betraying the Alliance.' WHERE `Id`=1285; -- Daelin's Men +UPDATE `quest_template` SET `OfferRewardText`='Mr. Ignatz was just here with the bogbean leaves, and he told me you helped him out of some real trouble.$B$BThank you, $N. I will ask my uncle to treat you to a feast the next time you visit the Blue Recluse in Stormwind.' WHERE `Id`=1222; -- Stinky's Escape +UPDATE `quest_template` SET `OfferRewardText`='You and Renn have done excellent work in bringing this information to light and reporting it immediately. Now, we must confirm your findings. The implications are too great if we are wrong.' WHERE `Id`=11141; -- Jaina Must Know +UPDATE `quest_template` SET `OfferRewardText`='<Lady Jaina listens intently as you report the results of your aerial survey.>$B$BA rune circle, dragonkin? The Defias have allied themselves with HER? The traitor?$B$B<Lady Jaina composes herself and prepares to explain.>' WHERE `Id`=11142; -- Survey Alcaz Island +UPDATE `quest_template` SET `OfferRewardText`='Excellent news, $c! If our tactical deployments continue to be this successful, the Horde will be in full retreat before long.' WHERE `Id`=24220; -- Call to Arms: Arathi Basin +UPDATE `quest_template` SET `OfferRewardText`='You''ve done well! That''s less Templars for me to worry about.$B$BHere you go, $N. Hope there''s something useful in there for you.' WHERE `Id`=8362; -- Abyssal Crests +UPDATE `quest_template` SET `OfferRewardText`='What Huum says is true. I believe I know how to summon a lord of the Abyssal Council! Listen on, and I will explain...' WHERE `Id`=8343; -- Goldleaf's Discovery +UPDATE `quest_template` SET `OfferRewardText`='This wine is quite amazing! I must know where it''s from.' WHERE `Id`=13115; -- Cheese for Glowergold +UPDATE `quest_template` SET `OfferRewardText`='I never cease to be amazed by the horrors that can be created through the use of technology.' WHERE `Id`=24585; -- Flame Leviathan Must Die! +UPDATE `quest_template` SET `OfferRewardText`='<Saurfang grins.>$B$BIt looks familiar... The Might of Kalimdor trampled a thousand bugs like this one in the desert of Silithus.$B$BThis is a different place - a different environment - but the result will be the same.$B$B<Saurfang looks you over.>$B$BYou will bring pride and honor to the Horde in Northrend, $N.$B$B<Saurfang nods.>' WHERE `Id`=11632; -- What the Cold Wind Brings... +UPDATE `quest_template` SET `OfferRewardText`='<Gort takes the tome from you and begins reading.>$B$BWHAT! This can''t be right. I''ve known some of these orcs for years!$B$BLeave me, $N. I have much work to do and many traitors to execute.$B$BTake one of these items for your trouble. You''ve done a great service for the Horde this day.' WHERE `Id`=12136; -- The Translated Tome +UPDATE `quest_template` SET `OfferRewardText`='Icefist, eh? I''ve heard his name before. Dat''s some good work, mon. Hopefully we Darkspear can turn our attention back to dat dragon menace now. ' WHERE `Id`=12145; -- Canyon Chase +UPDATE `quest_template` SET `OfferRewardText`='There is risk in dispelling the evil from a scourgestone, for it attracts the attention of undead for countless miles. But you are strong in the Light, $n, and I do not fear for you...' WHERE `Id`=8414; -- Dispelling Evil +UPDATE `quest_template` SET `OfferRewardText`='You have done as I asked without question, $n.$b$bTrust is achieved, it seems. Perhaps I can reveal our plan in more detail to you now.' WHERE `Id`=8416; -- Inert Scourgestones +UPDATE `quest_template` SET `OfferRewardText`='It''s good to see fresh troops here, $N, but with a little luck you''ll get into some action and won''t be fresh for long!$B$BSpeak with me again. I have tasks I must discuss with you....' WHERE `Id`=7121; -- The Quartermaster +UPDATE `quest_template` SET `OfferRewardText`='<The deathguard rubs his hands together in anticipation.>$B$BExcellent. Their loss is my... our gain!$B$BYou didn''t have trouble with any of these along the way? Some of them look rather unstable. I may be undead, but I value my existence!' WHERE `Id`=12230; -- Stealing from the Siegesmiths +UPDATE `quest_template` SET `OfferRewardText`='Excellent work, $g sir : ma''am;!$B$BI''ll see to it that the commander is apprised of your mission results.' WHERE `Id`=12562; -- The Drakkari Do Not Need Water Elementals! +UPDATE `quest_template` SET `OfferRewardText`='<Stefan reads the missive, then crumples it up and tosses it into the fire.>$B$BOld news. The Argent Crusade is - once again - late to the party. We''ve been tracking Drakuru since Grizzly Hills. He is slated for eradication. +' WHERE `Id`=12884; -- The Ebon Watch +UPDATE `quest_template` SET `OfferRewardText`='Saved them all, did you? Outstanding!$b$bMaybe you''d consider sticking around the post here? We could sure use someone like you....' WHERE `Id`=12512; -- Leave No One Behind +UPDATE `quest_template` SET `OfferRewardText`='Fine specimens, $n.$b$bOn behalf of my soldiers, I thank you for your efforts today.$b$bCaptain Rupert is likely the next stop on your patrol. He''s stationed at the wall just east of here.' WHERE `Id`=12564; -- Troll Patrol: Something for the Pain +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13017; -- Jarten the Elder +UPDATE `quest_template` SET `OfferRewardText`='Just what I wanted to hear! A victory in Alterac Valley - even a temporary one - is crucial to our overall strategy against the Horde.' WHERE `Id`=11336; -- Call to Arms: Alterac Valley +UPDATE `quest_template` SET `OfferRewardText`='The heavens, in their countless stars, hold answers to earthly mysteries, $N. Might, then, the wise, and the lucky, gaze up and find truth?' WHERE `Id`=8715; -- Bladeleaf the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=8680; -- Windtotem the Elder +UPDATE `quest_template` SET `OfferRewardText`='Thank you for heeding Rhonin''s call, brave adventurer.$B$BLet me share with you what we know regarding recent events, and any assistance you might offer would be greatly appreciated.' WHERE `Id`=26012; -- Trouble at Wyrmrest +UPDATE `quest_template` SET `OfferRewardText`='To atone for the sins I committed as one of the Lich King''s Death Knights, I''ve dedicated myself to creating rings of great power for our brothers and sisters to use in the struggle.$B$BYou''ve proven yourself as a valuable ally in the fight against the Scourge, $N. As your dedication continues I can improve on the ring''s original design.$B$BChoose your path carefully. A change of heart will come at a price.' WHERE `Id`=24815; -- Choose Your Path +UPDATE `quest_template` SET `OfferRewardText`='You have seen the Chamber of Khaz''mul? Amazing! Baelog was sure it existed, but I must admit that I had my doubts.$B$BThank you, $N. With luck your finding will incite our leaders to renew their efforts to retake Uldaman. And if it is ever again under Ironforge control, then the secrets of the Chamber of Khaz''mul will be ours!' WHERE `Id`=2240; -- The Hidden Chamber +UPDATE `quest_template` SET `OfferRewardText`='Well done, $N. Your actions in the field are instrumental in our battle for Hellfire Peninsula.' WHERE `Id`=13408; -- Hellfire Fortifications +UPDATE `quest_template` SET `OfferRewardText`='I have to hand it to you, $N, you''re a fighter born! Those Horde yokels may never know how close they came to the end. It takes real character to step in harm''s way on behalf of your enemies. That''s the kind of honor and commitment that holds the Alliance together! $B$B<Field Marshal Brock salutes you crisply.> +' WHERE `Id`=10396; -- Enemy of my Enemy... +UPDATE `quest_template` SET `OfferRewardText`='It is fortuitous that you intercepted this missive when you did, $N. Though it will take me some time to decipher, I can already sense the hatred and urgency woven into this scroll. I fear the Legion''s true motives in this land will soon be made evident...$B$BGive me a moment to decipher this script. $B$B<Warp-Scryer Kryv begins to read the demonic missive> +' WHERE `Id`=10395; -- The Dark Missive +UPDATE `quest_template` SET `OfferRewardText`='Are you certain of your choice, $N? The Aldor will welcome you as an ally, but the Scryers will not easily forgive your decision.' WHERE `Id`=10551; -- Allegiance to the Aldor +UPDATE `quest_template` SET `OfferRewardText`='Welcome back from your exercises, $N. I''m confident that you will make us proud when the competition starts.' WHERE `Id`=13749; -- A Valiant's Field Training +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=8654; -- Primestone the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=8681; -- Thunderhorn the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=8671; -- Ragetotem the Elder +UPDATE `quest_template` SET `OfferRewardText`='$N, you and your allies have spared the tournament from a devastating attack. Though our skytalon riders are brave, they have their hands full keeping the peace on the tournament grounds and would be hard-pressed to defend the skies against the cult''s attack. You have the thanks of the Argent Crusade and all who have gathered here to compete.' WHERE `Id`=13682; -- Threat From Above +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13015; -- Fargal the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13028; -- Graymane the Elder +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13020; -- Stonebeard the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13032; -- Muraco the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13027; -- Tauros the Elder +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13013; -- Beldak the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13025; -- Lunaro the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13030; -- Whurain the Elder +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13019; -- Thoim the Elder +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13014; -- Morthie the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13031; -- Skywarden the Elder +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13012; -- Sardis the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13033; -- Arp the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13029; -- Pamuya the Elder +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13016; -- Northal the Elder +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=13018; -- Sandrene the Elder +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=13024; -- Wanikaya the Elder +UPDATE `quest_template` SET `OfferRewardText`='Here is your Dalaran Jewelcrafter''s Token as promised. Come back tomorrow and I am sure I will have another item I need from you!' WHERE `Id`=12961; -- Shipment: Intricate Bone Figurine +UPDATE `quest_template` SET `OfferRewardText`='Your spirit burns with life, young $c. I accept the homage you pay, and offer in return this token...' WHERE `Id`=8684; -- Dreamseer the Elder +UPDATE `quest_template` SET `OfferRewardText`='You did it! $N, you are the champion of Zul''Drak!$B$BWe will never be able to repay the debt that we owe to you, but the Zandalari have given into my trust a number of objects they believe you might have an interest in.$B$BPlease, I want you to have a token of our appreciation, but hurry. I sense another issue of urgency!' WHERE `Id`=12730; -- Convocation at Zol'Heb +UPDATE `quest_template` SET `OfferRewardText`='Ay, mon. I been expectin'' you.$B$B<To''bor points west.>$B$BTake a peek. Across dat tundra be death, mon... death.' WHERE `Id`=11634; -- Wind Master To'bor +UPDATE `quest_template` SET `OfferRewardText`='NO MERCY FOR THE DEAD!$B$BNone of ''em had the guts to stay behind to defend our glorious tanks after Hellscream deemed the coast ''condemned.'' It''s mostly quiet here, seein'' as how the Scourge are formin'' up ranks to assault Warsong Hold. Sometimes I get a stray zombie or ghoul, but they don''t last very long.$B$B<Gorge strokes his axe.>$B$B''Course, there''s the mist...$B$B<Gorge shudders.> +' WHERE `Id`=11636; -- Magic Carpet Ride +UPDATE `quest_template` SET `OfferRewardText`='You''re the new tank driver, buddy? Fine by me! We just need to get these things up and running again. Yea, you try to go out into the Plains of Nasam without a tank and you''re as good as dead.' WHERE `Id`=11642; -- Tank Ain't Gonna Fix Itself +UPDATE `quest_template` SET `OfferRewardText`='Great work, buddy! Now where''d I put that pneumatic tank transjigamarig. +' WHERE `Id`=11644; -- Super Strong Metal Plates! +UPDATE `quest_template` SET `OfferRewardText`='<Sadness overcomes Waltor.>$B$BRuin... That is all they leave in their wake. They must be taught a lesson.' WHERE `Id`=11655; -- Into the Mist +UPDATE `quest_template` SET `OfferRewardText`='Great work, buddy! Now where''d I put those spare parts...' WHERE `Id`=11643; -- Mobu's Pneumatic Tank Transjigamarig +UPDATE `quest_template` SET `OfferRewardText`='It seems that the loss of their lieutenant has only stirred the nest. They are more angry and aggressive than before!$B$B<Waltor sighs.>$B$BYou''ve done what you can here, friend. At the very least you deserve some form of compensation for thinning their numbers. +' WHERE `Id`=11661; -- Orabus the Helmsman +UPDATE `quest_template` SET `OfferRewardText`='This is it? Hellscream sent a single $r $g boy:girl;?$B$BIf I still had a jaw it would be on the floor right now.' WHERE `Id`=11618; -- Reinforcements Incoming... +UPDATE `quest_template` SET `OfferRewardText`='Most of them made it back. The ones smart enough to know that we''re inside the gigantic metal and stone building, anyway...$B$BRegardless, a job well done. I hear you sprung more than a couple peons loose.$B$BOh yes, you''re the talk of the... um... fortress.' WHERE `Id`=11611; -- Taken by the Scourge +UPDATE `quest_template` SET `OfferRewardText`='Kel''Thuzad? So it''s true - Naxxramas returns...$B$BPerhaps I underestimated you, $N. You''ve done the Horde a great service. The Warchief would be proud!$B$B<Garrosh pauses to think.>$B$BIf Kel''Thuzad is controlling these Scourge, there''s no telling what else the Lich King has in store for us... I''ll need time to think through this new information, $N. You are dismissed.' WHERE `Id`=11652; -- The Plains of Nasam +UPDATE `quest_template` SET `OfferRewardText`='You are foolish to come here, little $r.$B$BWhat is it that you seek?' WHERE `Id`=11624; -- The Sky Will Know +UPDATE `quest_template` SET `OfferRewardText`='I am pleased, though no doubt they will still continue to quarrel a bit longer.$B$BHowever, there is something else that you will need to accomplish before you can return to your spirit talker.' WHERE `Id`=11627; -- Boiling Point +UPDATE `quest_template` SET `OfferRewardText`='I regret the loss of those tempests, but my word is my bond... even to a mortal such as yourself.$B$BNow, let us see if we can fashion something of use to you.' WHERE `Id`=11649; -- Motes of the Enraged +UPDATE `quest_template` SET `OfferRewardText`='Imperean gave you a primal essence of herself? I can hear its howling winds!$B$BI know a ritual we can make use of it in. We must hurry before her primal rips itself apart!' WHERE `Id`=11629; -- Return to the Spirit Talker +UPDATE `quest_template` SET `OfferRewardText`='They''ve shackled his spirit. $N, we have to put an end to his torture!$B$BYou must descend into the bowels of Magmoth and find a way to free him!' WHERE `Id`=11631; -- Vision of Air +UPDATE `quest_template` SET `OfferRewardText`='These are for me? Is this some sort of $r trick? No?$B$BWell then, thank you! Come back any time that you have more clams, and we''ll do business!' WHERE `Id`=11559; -- Winterfin Commerce +UPDATE `quest_template` SET `OfferRewardText`='It does not surprise me that the orc chieftain does not have time to hear of our troubles. The ambassador''s efforts will likely be like so much mist blowing in the wind.$B$BBut you are here now. We shall see if he chose well in sending you.' WHERE `Id`=11888; -- Ride to Taunka'le Village +UPDATE `quest_template` SET `OfferRewardText`='It is good to know the people of this land still pay homage to the olden races. I bid you well, $N, and offer you this token...' WHERE `Id`=8652; -- Graveborn the Elder +UPDATE `quest_template` SET `OfferRewardText`='May you find what you''re looking for, $g brother:sister;.' WHERE `Id`=24819; -- A Change of Heart +UPDATE `quest_template` SET `OfferRewardText`='At last, we have live specimens to study! You have helped to save countless lives this day, $N.$B$BPlease, take this as a token of thanks for this great deed.' WHERE `Id`=24873; -- Residue Rendezvous +UPDATE `quest_template` SET `OfferRewardText`='You continue to prove yourself, $N. Accept this, not as a gift, but as a tool for the fight against the Scourge.' WHERE `Id`=24823; -- Path of Destruction +UPDATE `quest_template` SET `OfferRewardText`='May you find what you''re looking for, $g brother:sister;.' WHERE `Id`=24840; -- A Change of Heart +UPDATE `quest_template` SET `OfferRewardText`='The giant is dead? Praise the Light!$B$BThe way onward and upward is clear. Take some of these spoils of the battle as a token of our gratitude, and we will drink together in celebration once the Frozen Throne has been ground to dust!' WHERE `Id`=24871; -- Securing the Ramparts +UPDATE `quest_template` SET `OfferRewardText`='I trust that you did not have to face too many of his iron construct assistants?' WHERE `Id`=24587; -- Ignis the Furnace Master Must Die! +UPDATE `quest_template` SET `OfferRewardText`='Now that is what I call dedication! Those traitors might have a new master now, but they''ll never forget their sisters'' parting gift.' WHERE `Id`=12953; -- Valkyrion Must Burn +UPDATE `quest_template` SET `OfferRewardText`='The val''kyr are nothing but the Lich King''s lapdogs. They will be put down like the scum they are. They''ve made their choice, now they have to live with the consequences.' WHERE `Id`=12942; -- Off With Their Black Wings +UPDATE `quest_template` SET `OfferRewardText`='Yulda had it coming. No one gets away with insulting the Hyldsmeet. Not even one of our own.' WHERE `Id`=12968; -- Yulda's Folly +UPDATE `quest_template` SET `OfferRewardText`='You have our thanks, sister. We cannot allow our valiant traditions to be corrupted.' WHERE `Id`=12925; -- Aberrations +UPDATE `quest_template` SET `OfferRewardText`='Your efforts appear to have been successful, sister.$b$bYou have brought glory to the Brunnhildar!' WHERE `Id`=12856; -- Cold Hearted +UPDATE `quest_template` SET `OfferRewardText`='So, sister, you think that completing a few simple chores makes you a heroine?$b$bYou shall learn....' WHERE `Id`=13063; -- Deemed Worthy +UPDATE `quest_template` SET `OfferRewardText`='These will do nicely. I''ll have the harness ready for you in no time.' WHERE `Id`=12900; -- Making a Harness +UPDATE `quest_template` SET `OfferRewardText`='I''m impressed. I never thought I would see an icemaw matriarch again. Especially not one this size.' WHERE `Id`=12983; -- The Last of Her Kind +UPDATE `quest_template` SET `OfferRewardText`='The jormungar are vile creatures. You did well in destroying them.' WHERE `Id`=12989; -- The Slithering Darkness +UPDATE `quest_template` SET `OfferRewardText`='Not bad. I was hoping Kirgaraak would snap your neck so I could keep your bear.$B$BJust joking, sister. Well... half-joking. That''s a really nice bear you''ve got.' WHERE `Id`=12996; -- The Warm-Up +UPDATE `quest_template` SET `OfferRewardText`='You really did it! You made it out with your health. Wish we could say the same for your bear.$B$BIt''s going to take a while for her to recover. Fortunately you won''t need her for a while.' WHERE `Id`=12997; -- Into the Pit +UPDATE `quest_template` SET `OfferRewardText`='You''ve really made it this far. Never would I have thought you''d progress so quickly among the hyldnir.' WHERE `Id`=13061; -- Prepare for Glory +UPDATE `quest_template` SET `OfferRewardText`='Are you ready to ride, sister? There is no coming back.' WHERE `Id`=13062; -- Lok'lira's Parting Gift +UPDATE `quest_template` SET `OfferRewardText`='Your bravery seems boundless, $N.$B$BPlease hand me the heart and the essence, and I will fashion them into that which will compel the prophet to appear before you.' WHERE `Id`=12729; -- The Gods Have Spoken +UPDATE `quest_template` SET `OfferRewardText`='Above the stale, unwashed stench, you catch a whiff of a familiar smell! It appears as if this once-mighty adventurer has a real love for kungaloosh.$b$bPeeking through the bars, you can barely make out the recipe written on his arm....' WHERE `Id`=13571; -- Fletcher's Lost and Found +UPDATE `quest_template` SET `OfferRewardText`='Desecrate the Horde''s Ghostlands bonfire!' WHERE `Id`=11774; -- Desecrate this Fire! +UPDATE `quest_template` SET `OfferRewardText`='Oh, bless ya, $N, bless ya!$B$BJust set ''em down right where yer standin''. I''ll have one o'' the boys come load ''em up soon enough and we can stop worryin'' ''bout runnin'' out o'' balls ta shoot at Skorn.' WHERE `Id`=11190; -- One Size Does Not Fit All +UPDATE `quest_template` SET `OfferRewardText`='This will make a fine meal for the men.$B$B<The chef leans in closer to whisper in your ear.>$B$BHere, $g boy : deary;, take some for yourself. You look like you could use some more meat on your bones!' WHERE `Id`=11155; -- Shoveltusk Soup Again? +UPDATE `quest_template` SET `OfferRewardText`='Incredible! What skill!$B$BThought you''d be easy prey, $N. Got me good, you did.$B$BHere''s the coin I promised... not as much as I said it''d be, but that''s on a count o'' me lying to ya in the first place.' WHERE `Id`=590; -- A Rogue's Deal +UPDATE `quest_template` SET `OfferRewardText`='Honor the Tirisfal Glades flame.' WHERE `Id`=11862; -- Honor the Flame +UPDATE `quest_template` SET `OfferRewardText`='Captain Perrine''s death will undoubtedly please The Dark Lady. You have performed your duty well, $c.' WHERE `Id`=370; -- At War With The Scarlet Crusade +UPDATE `quest_template` SET `OfferRewardText`='Varimathras would be proud. You serve your leaders well, $c.' WHERE `Id`=374; -- Proof of Demise +UPDATE `quest_template` SET `OfferRewardText`='It is troubling to hear of the Scourge slipping past the Bulwark. The Lich King and his minions are ceaseless in their assaults.$B$BBut we will not give in. He will not take us again!' WHERE `Id`=360; -- Return to the Magistrate +UPDATE `quest_template` SET `OfferRewardText`='Captain Vachon''s death will slow down the Scarlet Crusade''s advancement in Tirisfal quite a bit. But other threats loom.' WHERE `Id`=371; -- At War With The Scarlet Crusade +UPDATE `quest_template` SET `OfferRewardText`='The ore gave you a strange feeling? Maybe we won''t use that stuff after all.$B$B<Steelring looks at the stuff and takes a step back, changing the subject.>$B$BThose gems look really nice! I wonder what I can get for them? Of course, there are always repairs, and new stuff to be made.$B$BYou know, I''ve really found working with you to be profitable. Take this... it''s the least that I can do!' WHERE `Id`=11218; -- Danger! Explosives! +UPDATE `quest_template` SET `OfferRewardText`='Well timed, $c!$B$BThe Pit of Saron lies ahead, and if our scouts are correct, past that will be the Halls of Reflection. It is there that Arthas lets his guard down, and it is there that we hope to find a clue to his weakness... and a route to vengeance long overdue.' WHERE `Id`=24511; -- Echoes of Tortured Souls +UPDATE `quest_template` SET `OfferRewardText`='Incapable fools. I begin to wonder if any of these louts from the tournament will be of any use at all. Perhaps you''ll prove me wrong.' WHERE `Id`=24682; -- The Pit of Saron +UPDATE `quest_template` SET `OfferRewardText`='You''ve done well this day. With many of the slaves freed and now with access to the forges, it will not be long before I have a strong force to aid in delivering us from Scourgelord Tyrannus and this foul pit.' WHERE `Id`=24507; -- The Path to the Citadel +UPDATE `quest_template` SET `OfferRewardText`='The Halls of Reflection lie ahead. If what that vile gnome said is to be trusted, Frostmourne should be there, and with it, answers to confronting Arthas.' WHERE `Id`=24712; -- Deliverance from the Pit +UPDATE `quest_template` SET `OfferRewardText`='The Halls of Reflection. Finally.$B$BLet me know when you are ready, $c. I will not be so naive as to think that Arthas left his precious sword entirely unguarded.' WHERE `Id`=24713; -- Frostmourne +UPDATE `quest_template` SET `OfferRewardText`='Yet again, vengeance slips through my grasp. It''s hard to believe how much stronger he''s gotten.$B$BIt was foolish of you to come for me, but it''s good to know that there are still some champions of the Horde that aren''t useless cowards. The information Uther gave us may well be key to finally killing Arthas, though it is becoming more and more clear that the Horde will not be able to accomplish this on their own.$B$BGo, $c. I expect your prowess may be needed again very soon.' WHERE `Id`=24802; -- Wrath of the Lich King +UPDATE `quest_template` SET `OfferRewardText`='Excellent! This will help fuel the flames of war for days to come. ' WHERE `Id`=236; -- Fueling the Demolishers +UPDATE `quest_template` SET `OfferRewardText`='You continue to prove yourself, $N. Accept this, not as a gift, but as a tool for the fight against the Scourge.' WHERE `Id`=24828; -- Path of Destruction +UPDATE `quest_template` SET `OfferRewardText`='Stew looks good. Thanks for your help.' WHERE `Id`=13114; -- Sewer Stew +UPDATE `quest_template` SET `OfferRewardText`='I have never seen such terror in the eyes of a vrykul. They think themselves masters of their world.$B$BYou and I are going to prove them wrong. Very wrong.' WHERE `Id`=13091; -- The Art of Being a Water Terror +UPDATE `quest_template` SET `OfferRewardText`='It''s about damned time! No doubt that Baron Sliver took his sweet time in sending you to me.$B$BI should have that empty space above his shoulders removed!' WHERE `Id`=12806; -- To the Rise with all Due Haste! +UPDATE `quest_template` SET `OfferRewardText`='In their folly, the Argent Crusade has chosen to turn a blind eye upon the presence of the Scarlet Onslaught. We will not.$B$BWe do not care if they might assist in the battle against the Lich King. We do not believe them worthy of existence. We will be their end, once and for all!' WHERE `Id`=12807; -- The Story Thus Far... +UPDATE `quest_template` SET `OfferRewardText`='I thought so! I couldn''t quite make out the destruction from here, but I can imagine how it must have looked. Splendid!$B$BWell done, $n. Thrallmar command will be happy to hear of your success!' WHERE `Id`=10087; -- Burn It Up... For the Horde! +UPDATE `quest_template` SET `OfferRewardText`='Well done, $C, That''s one less forge camp we''ll need to worry about. It''ll take the Legion a while to get that facility back up and running. You''ve just bought us the one thing we''d run out of - time. +' WHERE `Id`=10390; -- Forge Camp: Mageddon +UPDATE `quest_template` SET `OfferRewardText`='Now Veranus can finally rest in peace.' WHERE `Id`=24586; -- Razorscale Must Die! +UPDATE `quest_template` SET `OfferRewardText`='That will keep our recruits fed! Here''s how you cook it.' WHERE `Id`=13088; -- Northern Cooking +UPDATE `quest_template` SET `OfferRewardText`='Honor the Stranglethorn Vale flame.' WHERE `Id`=11832; -- Honor the Flame +UPDATE `quest_template` SET `OfferRewardText`='As a hero of the Stormpike, you may choose one item from these recently plun... er, recovered treasures.' WHERE `Id`=8271; -- Hero of the Stormpike +UPDATE `quest_template` SET `OfferRewardText`='You are brave to have carried this. If even one drop were to touch your skin, you''d have died an agonizing death.$b$bAllow me to pay you for it... I can always use venom of exceptional potency.' WHERE `Id`=13845; -- Sealed Vial of Poison +UPDATE `quest_template` SET `OfferRewardText`='Well done, $N. I''ll take these to the Argent Crusade''s keepers right away. They''ll have no choice but to acknowledge that we''re doing far more than the Sunreavers to keep the coliseum running smoothly.' WHERE `Id`=14076; -- Breakfast Of Champions +UPDATE `quest_template` SET `OfferRewardText`='He''s a fine specimen and will serve us well.$B$BNow, we have to make sure to use him properly to trap Vardmadra!' WHERE `Id`=13133; -- Find the Ancient Hero +UPDATE `quest_template` SET `OfferRewardText`='<Narasi accepts the prayer book from you.>$B$BThank you. The book was a gift from Confessor Paletress herself. She would be honored to know that you have used it to bring tranquility to the slain.' WHERE `Id`=14077; -- The Light's Mercy +UPDATE `quest_template` SET `OfferRewardText`='At last, we can finally fish in peace! ''Course, by the time we catch anything, the expedition''ll arrive and claim it all for themselves.$B$BYou have our thanks, $N. Don''t be a stranger ''round here.' WHERE `Id`=11410; -- The One That Got Away +UPDATE `quest_template` SET `OfferRewardText`='<Lurielle listens as you introduce yourself.>$B$BIt is good to finally meet you, $N. We have long hoped that you and the other newcomers might send representatives. We don''t often venture beyond the borders of our glades, especially amid the changes the land is going through.' WHERE `Id`=11302; -- The Enigmatic Frost Nymphs +UPDATE `quest_template` SET `OfferRewardText`='<Lurielle accepts the cores from you quietly.>$B$BThank you, $N.$B$B<Lurielle glances at the icy cores sadly.>$B$BI promise, my friends, I will do all I can to restore you.' WHERE `Id`=11313; -- Spirits of the Ice +UPDATE `quest_template` SET `OfferRewardText`='Thank you for your help, $N. The Vibrant Glade was once a beautiful place, and when we return to it, we shall make it so again.' WHERE `Id`=11315; -- Wild Vines +UPDATE `quest_template` SET `OfferRewardText`='So there is hope for my sisters?$B$B<Lurielle looks away from you, then down at the ground.>$B$BI feel guilty for not thinking of the pendant sooner. We might have saved even more of the sisters.' WHERE `Id`=11314; -- The Fallen Sisters +UPDATE `quest_template` SET `OfferRewardText`='Thank goodness! This should be enough to finish the order in time. Of course, I won''t sleep until the troops arrive, but that''s far better than risking Captain Adams'' wrath.$B$BI''ve heard the stories they tell about him!' WHERE `Id`=11269; -- Down to the Wire +UPDATE `quest_template` SET `OfferRewardText`='<Trapper Jethan inspects the creatures you''ve brought him.>$B$BNicely done. Some of these will fetch a better price than others, but I should have plenty to trade with the locals.' WHERE `Id`=11292; -- Preying Upon the Weak +UPDATE `quest_template` SET `OfferRewardText`='Beaut! Yer a good one you are.$B$BTilt one back wi'' me! Let us celebrae'' this glorious find!' WHERE `Id`=12870; -- Ancient Relics +UPDATE `quest_template` SET `OfferRewardText`='Medical supplies? Thank you! Not exactly sure what to do with them to be honest, but I''m sure they''ll be useful.$B$BIt''s good to meet you... there''s such a colorful variety among your peoples. We''re not used to having visitors up this way very often - it''s good to have some fresh company.' WHERE `Id`=12863; -- Offering Thanks +UPDATE `quest_template` SET `OfferRewardText`='<Archaeologist Andorin looks at you expectantly.>$B$BYou were supposed to come back with Brann, not a piece of paper. What''s going on here?' WHERE `Id`=12854; -- On Brann's Trail +UPDATE `quest_template` SET `OfferRewardText`='When a scout doesn''t come back for this long... that''s about the expected result. The harpies then?$B$BKing Stormheart has us train hard year round... he''s turned us into amazing fighters. At times like this, I understand why it''s necessary. He''s the wisest and strongest leader I''ve yet seen among our people... don''t let his peachy skin fool ya.' WHERE `Id`=12864; -- Missing Scouts +UPDATE `quest_template` SET `OfferRewardText`='Good stuff, $G lad:lass;. You''re making fast friends.$B$BIf you stop back by soon, I''m sure we can find one that will let you ride... they should know that you''re trustworthy now.' WHERE `Id`=12867; -- Baby Stealers +UPDATE `quest_template` SET `OfferRewardText`='It''s done then. Thank you.$B$BI''ve spoken with Fjorlin - he said that his men will take charge of keeping the harpies down a bit. As long as we don''t let up again, they won''t find the courage to think they can attack our people.$B$BI know this wasn''t the most tasteful work - take this as a token of my appreciation.' WHERE `Id`=12868; -- Sirana Iceshriek +UPDATE `quest_template` SET `OfferRewardText`='That''s one less thorn in our side. With Noth destroyed, Scourge research into refining the means of creating the undead will grind to a halt.' WHERE `Id`=24581; -- Noth the Plaguebringer Must Die! +UPDATE `quest_template` SET `OfferRewardText`='I underestimated this Scourgelord, and it''s my men that paid for it. When I think that my guilt over Arthas'' betrayal cannot go any deeper, he proves me wrong yet again.$B$BWe have to press on. We cannot let their sacrifice be meaningless.' WHERE `Id`=24683; -- The Pit of Saron +UPDATE `quest_template` SET `OfferRewardText`='You''ve done well this day. With many of the slaves freed and now with access to the forges, it will not be long before I have a strong force to aid in delivering us from Scourgelord Tyrannus and this foul pit.' WHERE `Id`=24498; -- The Path to the Citadel +UPDATE `quest_template` SET `OfferRewardText`='Such a senseless waste! Arthas goes too far! I can only hope what we find in the Halls of Reflection makes this somehow worth it.$B$BIf what that vile gnome said is to be trusted, Frostmourne should be there, and with it, answers to confronting Arthas.' WHERE `Id`=24710; -- Deliverance from the Pit +UPDATE `quest_template` SET `OfferRewardText`='The Halls of Reflection. Finally.$B$BLet me know when you are ready. Arthas may not be here, but it would be naive to think that he would leave Frostmourne unguarded entirely.' WHERE `Id`=24711; -- Frostmourne +UPDATE `quest_template` SET `OfferRewardText`='<Urik points to a gryphon.>$B$BHave you ever ridden one of those? It''s simple, friend. Just hop on and tell it where to go. +' WHERE `Id`=12235; -- Naxxramas and the Fall of Wintergarde +UPDATE `quest_template` SET `OfferRewardText`='<Jaina is still catching her breath.>$B$BI can barely believe we''re still alive. It was foolish of me to follow him. I''ve made that mistake too many times. And you... it was reckless of you to come after me instead of escaping with the information! But... well... thank you. You truly are a hero.$B$BWith Uther''s guidance, we may stand a chance at defeating Arthas. All the lives lost today were not in vain.' WHERE `Id`=24500; -- Wrath of the Lich King +UPDATE `quest_template` SET `OfferRewardText`='<Bruor listens as you describe what you learned in the workshop.>$B$BSo Valduran''s master has given him this sinister metal to construct a giant weapon? That must be what he intends to use for the final strike against us! We need to stop him before he''s able to complete it and unleash this weapon.' WHERE `Id`=12980; -- The Armor's Secrets +UPDATE `quest_template` SET `OfferRewardText`='<Bouldercrag begins to look over the documents, his eyes wide.>$B$BI had no idea the irons were capable of this! Our men will have no chance against this behemoth if it''s completed. Fortunately, it looks like they''re still lacking a key part.' WHERE `Id`=12993; -- A Colossal Threat + +-- RequestItemsText +UPDATE `quest_template` SET `RequestItemsText`='How might I be of service to you, young one? Are you here to rest in the inn? Do you require a hearthstone?' WHERE `Id`=2159; -- Dolanaar Delivery +UPDATE `quest_template` SET `RequestItemsText`='Yes, young one? What can Kauth do for you?$B$BThe journey here from the Mesa can be a tremendous burden for some, but a welcome sight for others. Which is it for you, I wonder?' WHERE `Id`=1656; -- A Task Unfinished +UPDATE `quest_template` SET `RequestItemsText`='It takes a lot of work to be the strongest woman alive! My weight set is getting too light and if I''m to stay fit then I''ll need more weights!$B$BDo you think you could bring me some weight stones? If you do, then I''ll give you a Darkmoon Faire ticket.' WHERE `Id`=7889; -- Coarse Weightstone +UPDATE `quest_template` SET `RequestItemsText`='The first lesson in drawing a crowd is: lure them with gadgets and trinkets! Can you help me?$B$BI need small furry paws to use for prizes. You can find those on the cats of the Barrens or Darkshore....$B$BBring me some paws and I''ll trade you a Darkmoon Faire ticket for them.' WHERE `Id`=7899; -- Small Furry Paws +UPDATE `quest_template` SET `RequestItemsText`='Yebb is developing a new attraction for the Zoo Bizarre, one that will drive people crazy with wonder, and delight! But it will take a lot of work, and a lot of materials...$B$BThat includes copper modulators. We need lots of modulators for the mechanical parts of the attraction. Bring me copper modulators and I''ll trade for them with a Darkmoon Faire ticket.' WHERE `Id`=7894; -- Copper Modulator +UPDATE `quest_template` SET `RequestItemsText`='We at the Darkmoon Faire do much walking. We walk from one faire site to another... in fact, you''ll never see us sitting down on the job! So it is no surprise that we wear out quite a lot of boots! We need boots that are both durable and stylish, and embossed leather boots fit that bill rather well.$B$BYou! You''re a leatherworker; make me embossed leather boots and I''ll give you a Darkmoon Faire ticket for the work.' WHERE `Id`=7881; -- Carnival Boots +UPDATE `quest_template` SET `RequestItemsText`='King Varian has placed great importance on learning, and thus has provided funds for making copies of various tomes and writings available to the public. It''s very simple. You bring me a library scrip, and I can give you a copy of one of the available books.' WHERE `Id`=579; -- Stormwind Library +UPDATE `quest_template` SET `RequestItemsText`='My runes, $N? Do you have them?' WHERE `Id`=12841; -- The Crone's Bargain +UPDATE `quest_template` SET `RequestItemsText`='You will be richly rewarded for your service to me.$B$B<The darkspeaker projects soothing feelings into your mind.>$B$BYou will not regret unfettering me.' WHERE `Id`=13308; -- Mind Tricks +UPDATE `quest_template` SET `RequestItemsText`='Do you have 8 Trogg Stone Teeth to show me? If not, there is still work to be done, $N.' WHERE `Id`=267; -- The Trogg Threat +UPDATE `quest_template` SET `RequestItemsText`='You appear to have uncovered the wreckage of... a robotic chicken? The voice from within the egg crackles to life again:$B$B\"Yes, excellent work! This is indeed my homing robot, though my sensors indicate that it needs a jump start before it can fly back to Booty Bay for repairs. Go ahead and place the beacon inside the rover. The beacon will take care of the rest!\"' WHERE `Id`=351; -- Find OOX-17/TN! +UPDATE `quest_template` SET `RequestItemsText`='Got the five Wastewander water pouches we need? If you do, then the Gadgetzan Water Company Care Package, Model 103-XB, will be yours!' WHERE `Id`=1707; -- Water Pouch Bounty +UPDATE `quest_template` SET `RequestItemsText`='Yes $c, I am an official of the Gadgetzan Water Company. What can I assist you with?' WHERE `Id`=2781; -- WANTED: Caliph Scorpidsting +UPDATE `quest_template` SET `RequestItemsText`='You look a little dazed. Have you been reading our legal documents?' WHERE `Id`=2875; -- WANTED: Andre Firebeard +UPDATE `quest_template` SET `RequestItemsText`='The cries seem somehow... fainter than they were before. The Light grant it''s more than wishful thinking.' WHERE `Id`=10047; -- The Path of Glory +UPDATE `quest_template` SET `RequestItemsText`='The Legion could start shelling the Horde at any time, $N! You need to destroy those blasted cannons! +' WHERE `Id`=10396; -- Enemy of my Enemy... +UPDATE `quest_template` SET `RequestItemsText`='Do you have the broodling essence, $N? I can''t wait to study it.$B$BAnd besides that... my patron is not the type of person you want to disappoint.' WHERE `Id`=4726; -- Broodling Essence +UPDATE `quest_template` SET `RequestItemsText`='Hey, $N. Been to the Grizzled Den yet? Those Wendigos can be fierce.' WHERE `Id`=313; -- The Grizzled Den +UPDATE `quest_template` SET `RequestItemsText`='Preparations are going well. How goes your hunting?' WHERE `Id`=317; -- Stocking Jetsteam +UPDATE `quest_template` SET `RequestItemsText`='Hmph! There is all this booze down here, but I have strict orders not to touch it. If only I could get a taste of some of our Thunder Ale...that would sharpen my wits, no lying!' WHERE `Id`=308; -- Distracting Jarven +UPDATE `quest_template` SET `RequestItemsText`='Do you have that shimmerweed? I almost have a batch of stout ready to brew, and I want to try throwing the weed in with this mixture.' WHERE `Id`=315; -- The Perfect Stout +UPDATE `quest_template` SET `RequestItemsText`='Hello, $C! And what business takes you all the way out here?$B$BSomething exciting, I hope. I haven''t been in a good fight in days, and this barrel of ale is almost dry...' WHERE `Id`=413; -- Shimmer Stout +UPDATE `quest_template` SET `RequestItemsText`='I see you are back, $c. Have you collected 10 Red Wool Bandanas from those Defias Scum in The Stockade yet?' WHERE `Id`=388; -- The Color of Blood +UPDATE `quest_template` SET `RequestItemsText`='Loch Modan is under siege, $N! We need every able-bodied member of the Alliance to aid our cause. Have you killed 10 Stonesplinter Troggs and 10 Stonesplinter Scouts yet?' WHERE `Id`=224; -- In Defense of the King's Lands +UPDATE `quest_template` SET `RequestItemsText`='I know my plan was brilliant. Don''t even worry about it.$B$BDoes it feel good to be in the presence of greatness? A little tingly maybe?' WHERE `Id`=12828; -- Ample Inspiration +UPDATE `quest_template` SET `RequestItemsText`='If Janks were here, I could have just sent him on this errand. Oh... on second thought... I''m not sure I told him where the safe path is anyway.$B$BGood thing I have you resourceful adventure types around, eh?' WHERE `Id`=12819; -- Just Around the Corner +UPDATE `quest_template` SET `RequestItemsText`='Hi there. Do you have something for me?' WHERE `Id`=13836; -- Disarmed! +UPDATE `quest_template` SET `RequestItemsText`='Stand easy, $N. What have you to report? +' WHERE `Id`=13139; -- Into The Frozen Heart Of Northrend +UPDATE `quest_template` SET `RequestItemsText`='Well met, $c. I knew that you would return, despite my warnings, but I''m pleased that you heeded my desire to not risk anyone else.$B$BWhy have you come back to me?' WHERE `Id`=13075; -- The Boon of Remulos +UPDATE `quest_template` SET `RequestItemsText`='You want to talk about the bounty for Haghazed? Well, is he dead? There isn''t much else to talk about!' WHERE `Id`=9730; -- Leader of the Darkcrest +UPDATE `quest_template` SET `RequestItemsText`='We have to have something we can use to insulate our engines against this cold... think, Jeer, think!$B$BOh hey! Did you get some of that wreckage for me?' WHERE `Id`=12818; -- Clean Up +UPDATE `quest_template` SET `RequestItemsText`='Any luck with our equipment, $N?' WHERE `Id`=12844; -- Equipment Recovery +UPDATE `quest_template` SET `RequestItemsText`='Hello, $c. What have you there? Is it for me?' WHERE `Id`=9409; -- Urgent Delivery! +UPDATE `quest_template` SET `RequestItemsText`='Hello, $c. Do you have those flowers yet?' WHERE `Id`=9799; -- Botanical Legwork +UPDATE `quest_template` SET `RequestItemsText`='I''ll need all of the samples in good condition if we''re to have a chance of cleansing the lake.$B$BWe don''t have much time, $c!' WHERE `Id`=9293; -- What Must Be Done... +UPDATE `quest_template` SET `RequestItemsText`='The more we can do to clear up Nestlewood, the faster Zhanaa can get back to work.' WHERE `Id`=9303; -- Inoculation +UPDATE `quest_template` SET `RequestItemsText`='Together, the Broken and the draenei will regain a deeper understanding of the mysteries that the elements hold.$B$BHave you returned with that which is necessary for the creation of your earth totem?' WHERE `Id`=9451; -- Call of Earth +UPDATE `quest_template` SET `RequestItemsText`='The stag hides are frail which tend to make for tender, succulent flesh.' WHERE `Id`=9454; -- The Great Moongraze Hunt +UPDATE `quest_template` SET `RequestItemsText`='Do not waste time, $g boy:girl;.' WHERE `Id`=9473; -- An Alternative Alternative +UPDATE `quest_template` SET `RequestItemsText`='Have you done what I asked of you, $N?' WHERE `Id`=11913; -- Take No Chances +UPDATE `quest_template` SET `RequestItemsText`='Reporting from Honor Hold, $n? That''s good -- our campaign against the demons and the fel orcs is running thin on able bodies!' WHERE `Id`=10483; -- Ill Omens +UPDATE `quest_template` SET `RequestItemsText`='The ring, $N! Please... tell me you''ve found it!' WHERE `Id`=12624; -- It Could Be Anywhere! +UPDATE `quest_template` SET `RequestItemsText`='You find anything yet, $N?' WHERE `Id`=12699; -- An Embarassing Incident +UPDATE `quest_template` SET `RequestItemsText`='Any luck with the bloodtooth? Don''t forget what I told you about making blood pools.' WHERE `Id`=13833; -- Blood Is Thicker +UPDATE `quest_template` SET `RequestItemsText`='What is it that you''ve found, $N?' WHERE `Id`=24442; -- Battle Plans Of The Kvaldir +UPDATE `quest_template` SET `RequestItemsText`='Watch where you''re stepping! Watch watch watch!! This is delicate stuff you see here, and if we''re to win then it must all work perfectly!' WHERE `Id`=1179; -- The Brassbolts Brothers +UPDATE `quest_template` SET `RequestItemsText`='Tell me, $N, has the deed been done? Has the Legionlord been vanquished? +' WHERE `Id`=10400; -- Overlord +UPDATE `quest_template` SET `RequestItemsText`='We need to get this information to the Alliance! It may well be the key to Arthas'' defeat.' WHERE `Id`=24500; -- Wrath of the Lich King +UPDATE `quest_template` SET `RequestItemsText`='We are currently accepting donations for wool cloth. A donation of sixty pieces of wool cloth will net you full recognition by the Gnomeregan Exiles for your generous actions. Our stores are such on wool that we would only need sixty pieces from you total; we should be able to acquire enough from others in the realm to support our drive.$B$BIf you have the sixty pieces of wool cloth on you and are ready to donate them, I''m able to take them from you now.' WHERE `Id`=7807; -- A Donation of Wool +UPDATE `quest_template` SET `RequestItemsText`='As with most other fabrics, our stocks of silk are at an all-time low. Our stores are such that we''d only need sixty pieces of silk from you total; we should be able to reach our goal with the support of others.$B$BA benevolent gift such as silk, might I add, would certainly increase your local standing in the community! If you have the sixty pieces of silk cloth on you and are ready to donate them, I''m able to take them from you now.' WHERE `Id`=7808; -- A Donation of Silk +UPDATE `quest_template` SET `RequestItemsText`='<Hansel is busily rubbing his bunions.>$B$BDon''t just stand there, grab some oil and a luffa and get to scrubbin'' these bunions.$B$BYe don''t have a luffa? Well then! Perhaps it''s time I sent you out to find a luffa?$B$BHey, where are ye goin''?' WHERE `Id`=7727; -- Incendosaurs? Whateverosaur is More Like It +UPDATE `quest_template` SET `RequestItemsText`='Eight, $N. I need eight! ' WHERE `Id`=3443; -- Forging the Shaft +UPDATE `quest_template` SET `RequestItemsText`='Don''t let the crazy goggles fool you, $N. I''m the smart one here.' WHERE `Id`=7702; -- Kill 'Em With Sleep Deprivation +UPDATE `quest_template` SET `RequestItemsText`='Let''s not waste more of my precious time with jibber jabber, $r. It''s time to focus on replenishing our dwindling fiery flux supply.$B$BWhat I''m gonna need from you is the following:$B$B*Incendosaur scales.$B$B*Heavy Leather.$B$B*Coal.$B$BI''ll take all that you can offer!$B$BAnd you''ll do it fast if you wanna get in good with the Brotherhood. +' WHERE `Id`=8242; -- Restoring Fiery Flux Supplies via Heavy Leather +UPDATE `quest_template` SET `RequestItemsText`='You''ve worked your way up through the Brotherhood''s corporate hierarchy, $r. We have begun to look favorably upon you. Quite an accomplishment!$B$BIf you''re interested in more work and earning more respect amongst us, listen up.$B$BWe can refine the fiery flux by adding a simple Dark Iron residue to the mix. The Dark Iron residue can be found in Blackrock Depths.$B$BBring me all the Dark Iron residue you find!' WHERE `Id`=7737; -- Gaining Even More Acceptance +UPDATE `quest_template` SET `RequestItemsText`='You''ve worked your way up through the Brotherhood''s corporate hierarchy, $r. We have begun to look favorably upon you. Quite an accomplishment!$B$BIf you''re interested in more work and earning more respect amongst us, listen up.$B$BWe can refine the fiery flux by adding a simple Dark Iron residue to the mix. The Dark Iron residue can be found in Blackrock Depths.$B$BBring me all the Dark Iron residue you find!' WHERE `Id`=13662; -- Gaining Acceptance +UPDATE `quest_template` SET `RequestItemsText`='The Thorium Brotherhood sympathizes with your plight, $r. This is why Lokthos has been empowered to bargain.$B$BOffer 1 Lava Core and you shall be granted favor amongst the Brotherhood.' WHERE `Id`=6644; -- Favor Amongst the Brotherhood, Lava Core +UPDATE `quest_template` SET `RequestItemsText`='No ordinary tributes were good enough for the great Hodir when he walked among the frost giants.$B$BHe might not be with us anymore, but we''ve kept the tradition of offering tribute to his strength and wisdom. It would do much for your renown to partake in this tradition, small $c.' WHERE `Id`=13559; -- Hodir's Tribute +UPDATE `quest_template` SET `RequestItemsText`='Did you obtain the eggs, $N?' WHERE `Id`=13050; -- Veranus +UPDATE `quest_template` SET `RequestItemsText`='The power of this chapel gives me the strength to resist the corruption in my heart. If I leave it, I will become a death knight. But there is a medallion, the medallion of faith, that will give me the strength I need to leave.$B$BPlease, $N, retrieve the medallion. It is guarded by Malor the Zealous, a crazed member of the Scarlet Crusade who resides deep in the Scarlet Bastion in western Stratholme.' WHERE `Id`=5122; -- The Medallion of Faith +UPDATE `quest_template` SET `RequestItemsText`='Wine is only as fine as the person drinking it, I always say.' WHERE `Id`=24431; -- Waterlogged Recipe +UPDATE `quest_template` SET `RequestItemsText`='The Monastery was a seminary for Paladins-in-training. Once a stronghold of the Light, it fell into the hands of the crazed zealots of the Scarlet Crusade.$b$bThe Crusade believed their goal a noble one: to purify the land of the undead plague. But insanity tainted their plight and now they stand enemies to all.$b$bBring Mythology of the Titans to me so I can study it and house it here in Ironforge.$b$bThe corrupt halls of the Monastery are no place for such a historical treasure.' WHERE `Id`=1050; -- Mythology of the Titans +UPDATE `quest_template` SET `RequestItemsText`='I''m not one for politics; I care not if your affiliations are for either Horde or Alliance. I am more interested in squelching direct and dire threats to all the races... and we have quite a large one in here.$B$BIf you''re willing to be a true hero for all people, then hand me the oathstone I have given you as a sign of commitment. I''m... not from around these parts; an oathstone is important to people of my kind as a bond of agreement.' WHERE `Id`=3523; -- Scourge of the Downs +UPDATE `quest_template` SET `RequestItemsText`='Ach, $N! It''s good to see you, little one.' WHERE `Id`=13047; -- The Reckoning +UPDATE `quest_template` SET `RequestItemsText`='Bhag''thera can prove to be an elusive beast. How fares the hunt?' WHERE `Id`=193; -- Panther Mastery +UPDATE `quest_template` SET `RequestItemsText`='How goes the hunt for Tethis? Tracked her all the way back to camp, did you?' WHERE `Id`=197; -- Raptor Mastery +UPDATE `quest_template` SET `RequestItemsText`='I see you''re back, $g old bloke : lass;. King Bangalash has caused me to come crawling back to camp many times. Hang in there.' WHERE `Id`=208; -- Big Game Hunter +UPDATE `quest_template` SET `RequestItemsText`='Arrr... Yarr... Shiver me timbers... Er, sorry $g lad:lass;, I gotta practice me pirate lest I forget it...' WHERE `Id`=9512; -- Cookie's Jumbo Gumbo +UPDATE `quest_template` SET `RequestItemsText`='As you near the essence font that Eranikus told you of, his voice once again touches your mind.$B$B\"Yes mortal, this essence font will redeem what untainted element of my psyche remains imbued in this gem. Place the gem inside the font, and let the magic of the Green Dragonflight cleanse the corruption and taint from my being. Only then will I find true release, and only then will the Dragonflight be able to reassert their stewardship over the Atal''ai.\"' WHERE `Id`=3373; -- The Essence of Eranikus +UPDATE `quest_template` SET `RequestItemsText`='Here''s the plan, $n: Go out and collect some bloodpetal sprouts -- you know, the plants that haven''t fully sprouted yet, and bring them here. Then I''ll see what the Atal''ai haze can do.$B$BYou may think I''m vengeful... Actually, you''d be right about that! $B$BTruth is, I know the way out of here, but until Larion will admit that I''m right, I''m staying right here!$B$BSo off with you, find those bloodpetal sprouts and let''s have some fun!' WHERE `Id`=4144; -- Bloodpetal Sprouts +UPDATE `quest_template` SET `RequestItemsText`='Do not let fear overpower you, $N. Fear is the great betrayer... you must remain strong!$B$BTake the meat, place it in the small valley, and then use the gland on it. Only then will death come for you.' WHERE `Id`=4292; -- The Bait for Lar'korwi +UPDATE `quest_template` SET `RequestItemsText`='$C - you approach us in a peaceful manner, but I sense that you are here on matters that are grave and severe... for both furbolg and $r alike. What have you come to tell us?' WHERE `Id`=8471; -- Winterfall Ritual Totem +UPDATE `quest_template` SET `RequestItemsText`='Ahoy, me bucko! Might not be able to see but I can smell ye from halfway across port.$b$bCould really use me eye back. Captain''s going to keelhaul me when he finds out me peeper is in the hands of them dirty Bloodsail Buccaneers.$b$bWhat good is a lookout who can''t see? The crow''s nest used to be me home...without me deadlights I''d be lucky to scrub the bilge.' WHERE `Id`=576; -- Keep An Eye Out +UPDATE `quest_template` SET `RequestItemsText`='Ahoy, $n. What word do you bring of the Bloodsail encampment to the south?' WHERE `Id`=604; -- The Bloodsail Buccaneers +UPDATE `quest_template` SET `RequestItemsText`='Witch Doctor Unbagwa know what Mokk the Savage like. Yes, yes!$b$bMe speak with spirits and make he come, I do.$b$bBut other Gorilla-beast like spirit talkin'' too. You protect Witch Doctor Unbagwa and I make he come to you.$b$bWitch Doctor Unbagwa want something first. You bring a Gorilla Fang and me start spirit talking!' WHERE `Id`=349; -- Stranglethorn Fever +UPDATE `quest_template` SET `RequestItemsText`='Hey! I don''t like the look you''re giving me, $gmister:lady;.' WHERE `Id`=606; -- Scaring Shaky +UPDATE `quest_template` SET `RequestItemsText`='Here here, $N. Did you get Shaky''s payment?' WHERE `Id`=607; -- Return to MacKinley +UPDATE `quest_template` SET `RequestItemsText`='Do you have the writings of the Seven, $N? Have you learned the secrets from their tablet?' WHERE `Id`=4296; -- Tablet of the Seven +UPDATE `quest_template` SET `RequestItemsText`='I really don''t know if this plan will work, $N. Just bring me the scrap metal and I''ll do what I can.' WHERE `Id`=12901; -- Making Something Out Of Nothing +UPDATE `quest_template` SET `RequestItemsText`='Well met, $c. What brings you out here?' WHERE `Id`=11138; -- Renn McGill +UPDATE `quest_template` SET `RequestItemsText`='You''ve proved you can handle yourself in a fight, $N. Let''s keep the pressure up on the Twilight''s Hammer. Go fight some more Abyssal Templars, I''ll reward you with some of the stuff Huum and I have found in battle.' WHERE `Id`=8362; -- Abyssal Crests +UPDATE `quest_template` SET `RequestItemsText`='Have you seen a servant with my wine and cheese platter. I am quite peckish!' WHERE `Id`=13115; -- Cheese for Glowergold +UPDATE `quest_template` SET `RequestItemsText`='Their spirits are low, soldier. After our last failed air strike against the Horde, they refuse to fly! It is up to you to bolster their morale.$B$BReturn to the battlefield and strike at the heart of the Frostwolf''s command. Take down their commanders and guardians. Return to me with as many of their medals as you can stuff in your pack! I promise you, when my gryphons see the bounty and smell the blood of our enemies, they will fly again! Go now!' WHERE `Id`=6943; -- Call of Air - Ichman's Fleet +UPDATE `quest_template` SET `RequestItemsText`='You are the delivery $g boy:girl;?' WHERE `Id`=12182; -- To Venomspite! +UPDATE `quest_template` SET `RequestItemsText`='What''s all this?$B$BBy any chance have you seen my no-good apprentice, Pestlepot?$B$BI sent him on an errand quite some time ago and he has yet to return!' WHERE `Id`=12527; -- Gluttonous Lurkers +UPDATE `quest_template` SET `RequestItemsText`='Have you collected the water-poppies, $n?' WHERE `Id`=12564; -- Troll Patrol: Something for the Pain +UPDATE `quest_template` SET `RequestItemsText`='You seek to change the path you walk, $N?' WHERE `Id`=24819; -- A Change of Heart +UPDATE `quest_template` SET `RequestItemsText`='You close down that war-portal yet, $N? While you''re here shuffling your feet, there are more demons entering Outland! +' WHERE `Id`=10397; -- Invasion Point: Annihilator +UPDATE `quest_template` SET `RequestItemsText`='What is it, $C? I sense you''ve found something that speaks of a coming doom. +' WHERE `Id`=10395; -- The Dark Missive +UPDATE `quest_template` SET `RequestItemsText`='I sense a growing darkness within your heart, $C. Have you faced your fear? Or does it still await you at the Pools of Aggonar? +' WHERE `Id`=10399; -- The Heart of Darkness +UPDATE `quest_template` SET `RequestItemsText`='$N, you have returned. What did you learn?$B$BWhat is that sound?' WHERE `Id`=11629; -- Return to the Spirit Talker +UPDATE `quest_template` SET `RequestItemsText`='What''s this? Who are you?$B$BYou''re one of those $r things! How can you speak our tongue?' WHERE `Id`=11559; -- Winterfin Commerce +UPDATE `quest_template` SET `RequestItemsText`='You seek to continue down the path of destruction?' WHERE `Id`=24823; -- Path of Destruction +UPDATE `quest_template` SET `RequestItemsText`='You seek to change the path you walk, $N?' WHERE `Id`=24840; -- A Change of Heart +UPDATE `quest_template` SET `RequestItemsText`='As you draw near, the forge''s flame seems to burn even more ravenously...' WHERE `Id`=24545; -- The Sacred and the Corrupt +UPDATE `quest_template` SET `RequestItemsText`='Did you find the hides yet? You''ll find yeti in the hills below.' WHERE `Id`=12900; -- Making a Harness +UPDATE `quest_template` SET `RequestItemsText`='Do you have that which is required, $N?' WHERE `Id`=12729; -- The Gods Have Spoken +UPDATE `quest_template` SET `RequestItemsText`='We''re runnin'' dangerously low on rounds ''round here, $c. Our enemies need poundin'', especially Skorn!$B$BYa got more balls fer us?' WHERE `Id`=11190; -- One Size Does Not Fit All +UPDATE `quest_template` SET `RequestItemsText`='Have you collected 10 Scarlet Insignia Rings yet, $c?' WHERE `Id`=374; -- Proof of Demise +UPDATE `quest_template` SET `RequestItemsText`='You seek to continue down the path of destruction?' WHERE `Id`=24828; -- Path of Destruction +UPDATE `quest_template` SET `RequestItemsText`='You seek to change the path you walk, $N?' WHERE `Id`=24836; -- A Change of Heart +UPDATE `quest_template` SET `RequestItemsText`='Have you scouted all of the Blood Furnace yet? What do you have to tell me?' WHERE `Id`=9608; -- Heart of Rage +UPDATE `quest_template` SET `RequestItemsText`='The tears of the Fire Lord are a rare find indeed.$B$BOffer 1 Blood of the Mountain and you shall be granted favor amongst the Brotherhood. +' WHERE `Id`=6646; -- Favor Amongst the Brotherhood, Blood of the Mountain diff --git a/sql/updates/world/2012_06_03_04_world_misc.sql b/sql/updates/world/2012_06_03_04_world_misc.sql new file mode 100644 index 00000000000..22621d92cbd --- /dev/null +++ b/sql/updates/world/2012_06_03_04_world_misc.sql @@ -0,0 +1,25 @@ +-- Update Felboar +SET @ENTRY := 21878; +UPDATE `creature` SET `spawndist`=5,`MovementType`=1,`curhealth`=1,`spawntimesecs`=300 WHERE `id`=@ENTRY; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +UPDATE `creature_template_addon` SET `bytes2`=1,`auras`='33908' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,100,100,30000,55000,11,35570,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Felboar - Combat - Cast charge'); + +-- Update Dormant Infernal +SET @ENTRY := 21080; +UPDATE `creature_template_addon` SET `bytes2`=1,`auras`='36055' WHERE `entry`=@ENTRY; + +-- Update Kagrosh +SET @ENTRY := 21725; +UPDATE `creature_template_addon` SET `bytes2`=1,`auras`='29266' WHERE `entry`=@ENTRY; +UPDATE `creature` SET `position_x`=-3421.365,`position_y`=2289.388,`position_z`=33.63479,`orientation`=3.874631 WHERE `guid`=86869; +DELETE FROM `creature` WHERE `guid`=86870; + +-- Update Invis Deathforge Caster +SET @ENTRY := 21210; +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@ENTRY,1,'36393'); +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128 WHERE `entry`=@ENTRY; diff --git a/sql/updates/world/2012_06_03_05_world_creature.sql b/sql/updates/world/2012_06_03_05_world_creature.sql new file mode 100644 index 00000000000..c5bccdbf33c --- /dev/null +++ b/sql/updates/world/2012_06_03_05_world_creature.sql @@ -0,0 +1,7 @@ +-- Fix up Shadowmoon Harbinger +SET @ENTRY := 21795; +UPDATE `creature` SET `spawndist`=5,`MovementType`=1,`curhealth`=1,`curmana`=0 WHERE `id`=@ENTRY; +UPDATE `creature_template` SET `AIName`='' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@ENTRY,1,'37467 37509'); diff --git a/sql/updates/world/2012_06_03_06_world_sai.sql b/sql/updates/world/2012_06_03_06_world_sai.sql new file mode 100644 index 00000000000..32d1995a092 --- /dev/null +++ b/sql/updates/world/2012_06_03_06_world_sai.sql @@ -0,0 +1,39 @@ +-- Bron Goldhammer SAI +SET @ENTRY := 19395; +SET @SPELL := 33822; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +UPDATE `creature_template` SET `AIName`= '' WHERE `entry`=19394; +DELETE FROM `creature_ai_scripts` WHERE `creature_id` IN (@ENTRY,19394); +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=9 AND `entryorguid`=@ENTRY*100; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,1,0,100,0,30000,30000,100000,100000,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Bron Goldhammer - OOC - Run Script'), +(@ENTRY*100,9,0,0,0,0,100,0,1000,1000,0,0,1,0,0,0,0,0,0,11,19394,15,0,0,0,0,0, 'Bron Goldhammer - Script - Barimoke Wildbeard Say 0'), +(@ENTRY*100,9,1,0,0,0,100,0,6000,6000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Bron Goldhammer - Script - Bron Goldhammer Say 0'), +(@ENTRY*100,9,2,0,0,0,100,0,3000,3000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Bron Goldhammer - Script - Bron Goldhammer Say 1'), +(@ENTRY*100,9,3,0,0,0,100,0,3000,3000,0,0,1,1,0,0,0,0,0,11,19394,15,0,0,0,0,0, 'Bron Goldhammer - Script - Barimoke Wildbeard Say 1'), +(@ENTRY*100,9,4,0,0,0,100,0,3000,3000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Bron Goldhammer - Script - Bron Goldhammer Say 2'), +(@ENTRY*100,9,5,0,0,0,100,0,2000,2000,0,0,1,2,0,0,0,0,0,11,19394,15,0,0,0,0,0, 'Bron Goldhammer - Script - Barimoke Wildbeard Say 2'), +(@ENTRY*100,9,6,0,0,0,100,0,2500,2500,0,0,11,@SPELL,3,0,0,0,0,11,19394,15,0,0,0,0,0, 'Bron Goldhammer - Script - cast spell'), +(@ENTRY*100,9,7,0,0,0,100,0,1000,1000,0,0,90,7,0,0,0,0,0,11,19394,15,0,0,0,0,0, 'Bron Goldhammer - Script - Barimoke Wildbeard set bytes 1'), +(@ENTRY*100,9,8,0,0,0,100,0,3000,3000,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Bron Goldhammer - Script - Bron Goldhammer Say 3'), +(@ENTRY*100,9,9,0,0,0,100,0,2000,2000,0,0,91,7,0,0,0,0,0,11,19394,15,0,0,0,0,0, 'Bron Goldhammer - Script - Barimoke Wildbeard remove bytes 1'), +(@ENTRY*100,9,10,0,0,0,100,0,500,500,0,0,1,3,0,0,0,0,0,11,19394,15,0,0,0,0,0, 'Bron Goldhammer - Script - Barimoke Wildbeard Say 3'); +-- Bron Goldhammer text +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_texts` WHERE `entry` IN (-325,-326,-327,-328); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, '%s blinks, a perplexed expression crossing his face.',16,0,100,0,0,0, 'Bron Goldhammer'), +(@ENTRY,1,0, 'What, with me fists?',12,0,100,6,0,0, 'Bron Goldhammer'), +(@ENTRY,2,0, 'I''m... not sure that''s a good idea, ''Moke. Ye might get hurt...',12,0,100,1,0,0, 'Bron Goldhammer'), +(@ENTRY,3,0, 'Er... ''Moke?',12,0,100,6,0,0, 'Bron Goldhammer'); +-- Barimoke Wildbeard text +SET @ENTRY := 19394; +UPDATE `creature_template_addon` SET `bytes1`=0 WHERE `entry`=@ENTRY; +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_texts` WHERE `entry` IN (-329,-330,-331,-332); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'Bron! ''Ey Bron! ''Ey Bron! Hit me!',12,0,100,1,0,0, 'Barimoke Wildbeard'), +(@ENTRY,1,0, 'Nae, that''s fer wimps. Hit me with yer hammer!',12,0,100,274,0,0, 'Barimoke Wildbeard'), +(@ENTRY,2,0, 'DO IT, YE PANSEY!',12,0,100,5,0,0, 'Barimoke Wildbeard'), +(@ENTRY,3,0, '...THAT WAS GREAT!',12,0,100,5,0,0, 'Barimoke Wildbeard'); diff --git a/sql/updates/world/2012_06_04_00_world_sai.sql b/sql/updates/world/2012_06_04_00_world_sai.sql new file mode 100644 index 00000000000..9497f73041c --- /dev/null +++ b/sql/updates/world/2012_06_04_00_world_sai.sql @@ -0,0 +1,134 @@ +-- Kolkar Pack Runner SAI +SET @ENTRY := 3274; +SET @SPELL := 9128; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `creature_ai_summons` WHERE `id`=8; +DELETE FROM `creature_ai_texts` WHERE `entry` IN (-769); +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,4,0,100,0,0,0,0,0,11,@SPELL,32,0,0,0,0,1,0,0,0,0,0,0,0, 'Kolkar Pack Runner - On Aggro - Cast Battle Shout'), +(@ENTRY,0,1,2,6,0,3,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Kolkar Pack Runner - On Death 3% - Say 0'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,12,3395,4,60000,0,0,0,8,0,0,0,-1209.65,-2738.38,102.646,4.99352, 'Kolkar Pack Runner - On Death 3% - Summon Verog the Dervish'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'I am slain! Summon Verog!',14,0,100,0,0,0, 'Kolkar Pack Runner'); + +-- Kolkar Marauder SAI +SET @ENTRY := 3275; +SET @SPELL := 11976; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,80,0,12000,12000,7000,7000,11,@SPELL,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Kolkar Marauder - Combat - Cast Strike'), +(@ENTRY,0,1,2,6,0,3,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Kolkar Marauder - On Death 3% - Say 0'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,12,3395,4,60000,0,0,0,8,0,0,0,-1209.65,-2738.38,102.646,4.99352, 'Kolkar Marauder - On Death 3% - Summon Verog the Dervish'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'I am slain! Summon Verog!',14,0,100,0,0,0, 'Kolkar Marauder'); + +-- Kolkar Bloodcharger SAI +SET @ENTRY := 3397; +SET @SPELL1 := 6742; +SET @SPELL2 := 172; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,35000,35000,10000,10000,11,@SPELL1,32,0,0,0,0,1,0,0,0,0,0,0,0, 'Kolkar Bloodcharger - Combat - Cast Bollodlust'), +(@ENTRY,0,1,0,0,0,100,0,20000,20000,5000,5000,11,@SPELL2,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Kolkar Bloodcharger - Combat - Cast Corruption'), +(@ENTRY,0,2,3,6,0,3,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Kolkar Bloodcharger - On Death 3% - Say 0'), +(@ENTRY,0,3,0,61,0,100,0,0,0,0,0,12,3395,4,60000,0,0,0,8,0,0,0,-1209.65,-2738.38,102.646,4.99352, 'Kolkar Bloodcharger - On Death 3% - Summon Verog the Dervish'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'I am slain! Summon Verog!',14,0,100,0,0,0, 'Kolkar Bloodcharger'); + +-- Clara Charles SAI +SET @ENTRY := 5917; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `creature_ai_summons` WHERE `id` BETWEEN 7 AND 19; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,10,0,100,1,1,15,0,0,12,583,4,60000,0,0,0,8,0,0,0,-9232.11,342.473,74.4399,4.31658, 'Clara Charles - On LOS - Summon Defias Ambusher'); + +-- Defias Dockmaster SAI +SET @ENTRY := 6846; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `creature_ai_texts` WHERE `entry` IN (-232); +DELETE FROM `creature_ai_summons` WHERE `id` IN (4,5,6); +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,1,4,0,100,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Defias Dockmaster - On Aggro - Say 0'), +(@ENTRY,0,1,2,61,0,100,0,0,0,0,0,12,6866,4,60000,0,0,0,8,0,0,0,-9967.55,-135.956,24.5909,0.170326, 'Defias Dockmaster - On Aggro - Summon Defias Bodyguard'), +(@ENTRY,0,2,3,61,0,100,0,0,0,0,0,12,6866,4,60000,0,0,0,8,0,0,0,-9958.49,-140.526,24.2409,4.0015, 'Defias Dockmaster - On Aggro - Summon Defias Bodyguard'), +(@ENTRY,0,3,0,61,0,100,0,0,0,0,0,12,6866,4,60000,0,0,0,8,0,0,0,-9964.59,-140.567,24.5105,0.741307, 'Defias Dockmaster - On Aggro - Summon Defias Bodyguard'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'The Brotherhood will not be hampered by insects.',12,0,100,0,0,0, 'Defias Dockmaster'); + +-- Mekgineer Thermaplugg SAI +SET @ENTRY := 7800; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `creature_ai_texts` WHERE `entry` IN (-188,-189,-190,-191); +DELETE FROM `creature_ai_summons` WHERE `id` IN (2,3); +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,4,0,100,3,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mekgineer Thermaplugg - On Aggro - Say 0'), +(@ENTRY,0,1,0,5,0,100,2,0,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mekgineer Thermaplugg - On Kill - Say 3'), +(@ENTRY,0,2,0,0,0,100,2,40000,40000,40000,60000,11,11130,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Mekgineer Thermaplugg - Combat - Cast Knock Away'), +(@ENTRY,0,3,0,0,0,100,2,15000,15000,15000,35000,11,10101,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Mekgineer Thermaplugg - Combat - Cast Knock Away'), +(@ENTRY,0,4,5,0,0,100,2,30000,30000,30000,30000,12,7915,4,60000,0,0,0,8,0,0,0,-521.934,693.13,-327.005,2.95, 'Mekgineer Thermaplugg - Combat - Summon Walking Bomb'), +(@ENTRY,0,5,6,61,0,100,0,0,0,0,0,12,7915,4,60000,0,0,0,8,0,0,0,-535.318,649.987,-326.494,2.72, 'Mekgineer Thermaplugg - Combat - Summon Walking Bomb'), +(@ENTRY,0,6,0,61,0,100,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mekgineer Thermaplugg - Combat - Say 2'), +(@ENTRY,0,7,0,0,0,100,2,20000,20000,40000,65000,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mekgineer Thermaplugg - Combat - Say 1'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'USURPERS!!! GNOMEREGAN IS MINE!!!',14,0,100,0,0,5807, 'Mekgineer Thermaplugg'), +(@ENTRY,1,0, 'My machines are the future! They''ll destroy you all!',14,0,100,0,0,5808, 'Mekgineer Thermaplugg'), +(@ENTRY,2,0, 'Explosions! MORE explosions! I''ve got to have more explosions!',14,0,100,0,0,5809, 'Mekgineer Thermaplugg'), +(@ENTRY,3,0, '...and stay dead! He got served!',14,0,100,0,0,5810, 'Mekgineer Thermaplugg'); + +-- Shy-Rotam SAI +SET @ENTRY := 10737; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `creature_ai_summons` WHERE `id` IN (1); +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,5000,5000,5000,10000,11,14100,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Shy-Rotam - Combat - Cast Terrifying Roar'), +(@ENTRY,0,1,0,0,0,100,0,7000,9000,22000,27000,11,13443,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Shy-Rotam - Combat - Cast Rend'), +(@ENTRY,0,2,0,0,0,100,0,2000,3000,15000,20000,11,3604,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Shy-Rotam - Combat - Cast Tendon Rip'), +(@ENTRY,0,3,0,0,0,100,1,0,50,0,0,12,10741,1,180000,0,0,0,8,0,0,0,8074.84,-3840,690.061,4.6, 'Shy-Rotam - @50%HP - Summon Sian-Rotam'); + +-- Jammal'an the Prophet SAI +SET @ENTRY := 5710; +SET @QUEST_SOULGRINDER := 11000; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `creature_ai_texts` WHERE `entry` IN (-821,-822,-823,-824); +DELETE FROM `creature_ai_summons` WHERE `id` IN (20,21); +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,1,10,0,100,0,0,85,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Jammal'an the Prophet - On OOC Los - Say Line 0 (P0)"), +(@ENTRY,0,1,2,61,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Jammal'an the Prophet - On OOC Los - Set Phase 1"), +(@ENTRY,0,2,0,0,1,100,0,0,0,31400,76200,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,"Jammal'an the Prophet - In Combat - Say Line 2"), +(@ENTRY,0,3,0,0,1,100,0,8100,35600,20100,52900,11,12468,0,0,0,0,0,2,0,0,0,0,0,0,0,"Jammal'an the Prophet - In Combat - Cast Flamestrike"), +(@ENTRY,0,4,0,0,1,100,0,6200,16500,26100,36600,11,8376,0,0,0,0,0,1,0,0,0,0,0,0,0,"Jammal'an the Prophet - In Combat - Cast Earthgrab Totem"), +(@ENTRY,0,5,6,1,1,100,0,16300,19900,31400,53500,11,12479,0,0,0,0,0,2,0,0,0,0,0,0,0,"Jammal'an the Prophet - In Combat - Cast Hex of Jammal'an"), +(@ENTRY,0,6,0,61,1,100,0,0,0,0,0,1,2,0,0,0,0,0,2,0,0,0,0,0,0,0,"Jammal'an the Prophet - On Hex of Jammal'an Cast - Say Line 1"), +(@ENTRY,0,7,8,2,1,100,1,0,30,0,0,11,12492,0,0,0,0,0,1,0,0,0,0,0,0,0,"Jammal'an the Prophet - At 30% HP - Cast Healing Wave"), +(@ENTRY,0,8,0,61,1,100,0,0,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Jammal'an the Prophet - At 30% HP - Say Line 3"), +(@ENTRY,0,9,0,5,1,100,0,0,0,0,0,4,5863,0,0,0,0,0,1,0,0,0,0,0,0,0,"Jammal'an the Prophet - Killed Unit - Play Sound 5863"), +(@ENTRY,0,10,11,6,1,100,0,0,0,0,0,12,5721,1,300000,0,0,0,8,0,0,0,-472.02,105.823,-94.6299,0.0301925,"Jammal'an the Prophet - On Death - Summon Dreamscyte"), +(@ENTRY,0,11,0,61,1,100,0,0,0,0,0,12,5720,1,300000,0,0,0,8,0,0,0,-467.099,85.2944,-94.7318,3.95326,"Jammal'an the Prophet - On Death - Summon Weaver"); +-- Jammal'an the Prophet text +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0,"The shield be down! Rise up Atal'ai! Rise up!",14,0,100,0,0,0,"Jammal'an the Prophet"), -- 821 +(@ENTRY,1,0,"Join us!",14,0,100,0,0,0,"Jammal'an the Prophet"), -- 823 +(@ENTRY,2,0,"The Soulflayer comes!",14,0,100,0,0,0,"Jammal'an the Prophet"), -- 822 +(@ENTRY,3,0,"Hakkar shall live again!",14,0,100,0,0,0,"Jammal'an the Prophet"); -- 824 diff --git a/sql/updates/world/2012_06_04_01_world_gossip.sql b/sql/updates/world/2012_06_04_01_world_gossip.sql new file mode 100644 index 00000000000..f6246967452 --- /dev/null +++ b/sql/updates/world/2012_06_04_01_world_gossip.sql @@ -0,0 +1,23 @@ +-- Add some missing gossip for winterspring +UPDATE `creature_template` SET `gossip_menu_id`=3049 WHERE `entry`=10918; +DELETE FROM `gossip_menu` WHERE `entry`=3049; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (3049,3758); +UPDATE `creature_template` SET `gossip_menu_id`=7046 WHERE `entry`=16015; +DELETE FROM `gossip_menu` WHERE `entry`=7046; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (7046,8292); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=7046 AND `id` IN (0); +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`) VALUES +(7046,0,1, 'Hey Vi''el, show me your wares!',3,128,0,0,0,0, ''); +UPDATE `creature_template` SET `gossip_menu_id`=9821 WHERE `entry`=11119; +UPDATE `creature_template` SET `gossip_menu_id`=6092 WHERE `entry`=14742; +DELETE FROM `gossip_menu` WHERE `entry`=6092; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (6092,7249); +UPDATE `creature_template` SET `gossip_menu_id`=6091 WHERE `entry`=11193; +DELETE FROM `gossip_menu` WHERE `entry`=6091; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (6091,7247); +UPDATE `creature_template` SET `gossip_menu_id`=6089 WHERE `entry`=11192; +DELETE FROM `gossip_menu` WHERE `entry`=6089; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (6089,7243); +UPDATE `creature_template` SET `gossip_menu_id`=6090 WHERE `entry`=11191; +DELETE FROM `gossip_menu` WHERE `entry`=6090; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (6090,7245); diff --git a/sql/updates/world/2012_06_04_02_world_gossip.sql b/sql/updates/world/2012_06_04_02_world_gossip.sql new file mode 100644 index 00000000000..0122e9b736e --- /dev/null +++ b/sql/updates/world/2012_06_04_02_world_gossip.sql @@ -0,0 +1,143 @@ +UPDATE `creature_template` SET `gossip_menu_id`=10466 WHERE `entry`=33558; +UPDATE `creature_template` SET `gossip_menu_id`=10471 WHERE `entry`=33561; +UPDATE `creature_template` SET `gossip_menu_id`=10465 WHERE `entry`=33562; + +SET @OLDGOSSIP := 21000; +SET @NEWGOSSIP := 9935; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21007; +SET @NEWGOSSIP := 9941; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21024; +SET @NEWGOSSIP := 9937; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21038; +SET @NEWGOSSIP := 9938; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21049; +SET @NEWGOSSIP := 9931; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21067; +SET @NEWGOSSIP := 9945; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21048; +SET @NEWGOSSIP := 9946; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21039; +SET @NEWGOSSIP := 9948; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21065; +SET @NEWGOSSIP := 9953; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21035; +SET @NEWGOSSIP := 9954; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21010; +SET @NEWGOSSIP := 9959; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21069; +SET @NEWGOSSIP := 9961; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21028; +SET @NEWGOSSIP := 9963; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21001; +SET @NEWGOSSIP := 9964; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21027; +SET @NEWGOSSIP := 9966; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21064; +SET @NEWGOSSIP := 9968; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21041; +SET @NEWGOSSIP := 9971; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21074; +SET @NEWGOSSIP := 9972; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21015; +SET @NEWGOSSIP := 9975; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; + +SET @OLDGOSSIP := 21019; +SET @NEWGOSSIP := 9980; +UPDATE `creature_template` SET `gossip_menu_id`=@NEWGOSSIP WHERE `gossip_menu_id`=@OLDGOSSIP; +UPDATE `gossip_menu` SET `entry`=@NEWGOSSIP WHERE `entry`=@OLDGOSSIP; +UPDATE `gossip_menu_option` SET `menu_id`=@NEWGOSSIP WHERE `menu_id`=@OLDGOSSIP; +UPDATE `conditions` SET `SourceGroup`=@NEWGOSSIP WHERE `SourceGroup`=@OLDGOSSIP AND `SourceTypeOrReferenceId`=15; diff --git a/sql/updates/world/2012_06_04_03_world_conditions.sql b/sql/updates/world/2012_06_04_03_world_conditions.sql new file mode 100644 index 00000000000..0eadeb8542e --- /dev/null +++ b/sql/updates/world/2012_06_04_03_world_conditions.sql @@ -0,0 +1,6 @@ +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 19 AND `SourceEntry` IN (13408,13409,13410,13411); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19, 0, 13408, 0, 0, 15, 0, 1503, 0, 0, 0, 0, '', 'Hellfire Fortifications - Alliance -All classes other than dk'), +(19, 0, 13409, 0, 0, 15, 0, 1503, 0, 0, 0, 0, '', 'Hellfire Fortifications - Horde -All classes other than dk'), +(19, 0, 13410, 0, 0, 15, 0, 32, 0, 0, 0, 0, '', 'Hellfire Fortifications - Alliance -Only dk'), +(19, 0, 13411, 0, 0, 15, 0, 32, 0, 0, 0, 0, '', 'Hellfire Fortifications - Horde -Only dk'); diff --git a/sql/updates/world/2012_06_04_04_world_sai.sql b/sql/updates/world/2012_06_04_04_world_sai.sql new file mode 100644 index 00000000000..f38cd1fe63f --- /dev/null +++ b/sql/updates/world/2012_06_04_04_world_sai.sql @@ -0,0 +1,15 @@ +-- Hogger EAI to SAI Conversion +SET @ENTRY := 448; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,1,4,0,100,0,0,0,0,0,11,6268,1,0,0,0,0,2,0,0,0,0,0,0,0, 'Hogger - On aggro - Cast Rushing Charge'), +(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Hogger - On Aggro - Random Say'), +(@ENTRY,0,2,0,0,0,100,0,1300,3700,20000,25000,11,6730,1,0,0,0,0,2,0,0,0,0,0,0,0, 'Hogger - Combat - Cast Headbutt'), +(@ENTRY,0,3,0,0,0,100,0,4800,6000,30000,30000,11,6016,1,0,0,0,0,2,0,0,0,0,0,0,0, 'Hogger - Combat - Cast Armor Pierce'); +-- Hogger creature text +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`) VALUES +(@ENTRY,0,0, 'More bones to gnaw on...',12,0,100,0,0,0, 'Hogger Agro Say 1'), +(@ENTRY,0,1, 'Grrrr... fresh meat!',12,0,100,0,0,0, 'Hogger Agro Say 2'); diff --git a/sql/updates/world/2012_06_04_05_world_sai.sql b/sql/updates/world/2012_06_04_05_world_sai.sql new file mode 100644 index 00000000000..51d998c15ab --- /dev/null +++ b/sql/updates/world/2012_06_04_05_world_sai.sql @@ -0,0 +1,3 @@ +-- Fix SAI for Lothos Riftwaker +UPDATE `smart_scripts` SET `event_param1`=5750 WHERE `entryorguid`=14387 AND `id`=0; +UPDATE `smart_scripts` SET `event_param1`=0 WHERE `entryorguid`=14387 AND `id`=1; diff --git a/sql/updates/world/2012_06_04_06_world_sai.sql b/sql/updates/world/2012_06_04_06_world_sai.sql new file mode 100644 index 00000000000..455246d82b7 --- /dev/null +++ b/sql/updates/world/2012_06_04_06_world_sai.sql @@ -0,0 +1,18 @@ +-- Mok'rash SAI +SET @ENTRY := 1493; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY; +INSERT INTO smart_scripts (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,1,0,100,0,5000,10000,300000,600000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0, 'Mok''Rash - OOC - Random Yell'), +(@ENTRY,0,1,0,0,0,85,0,8000,8000,15000,15000,11,40505,0,0,0,0,0,2,0,0,0,0,0,0,0, 'Mok''Rash - Combat - Cast Cleave'); +-- Mok'rash Text +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO creature_text (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY, 0, 0, 'SMOTTS, I HAVE YOUR LITTLE BELT....COME GET IT!', 14, 0, 100, 0, 0, 0, 'Mok''rash Yell'), +(@ENTRY, 0, 1, 'SMOTTS! HEY, SMOTTS! COME OUT AND PLAY!', 14, 0, 100, 0, 0, 0, 'Mok''rash Yell'), +(@ENTRY, 0, 2, 'DON''T LET THIS STATUE BE MY ONLY COMPANY, COME OUT AND PLAY!', 14, 0, 100, 0, 0, 0, 'Mok''rash Yell'), +(@ENTRY, 0, 3, 'COME OUT TO JANEIRO''S POINT. I''M WAITING FOR YOU, SMOTTS...', 14, 0, 100, 0, 0, 0, 'Mok''rash Yell'), +(@ENTRY, 0, 4, 'I PROMISE I WON''T KILL YOUR CREW THIS TIME. HAH! BUT MY BROTHER MIGHT EAT THEM!', 14, 0, 100, 0, 0, 0, 'Mok''rash Yell'), +(@ENTRY, 0, 5, 'HAVE YOU RUN OUT OF SHIPS TO SEND? WHERE IS YOUR COURAGE?', 14, 0, 100, 0, 0, 0, 'Mok''rash Yell'), +(@ENTRY, 0, 6, 'I HAVE YOUR LITTLE BELT TIED AROUND MY FINGER, SMOTTS. DON''T YOU WANT IT BACK?', 14, 0, 100, 0, 0, 0, 'Mok''rash Yell'); diff --git a/sql/updates/world/2012_06_04_07_world_misc.sql b/sql/updates/world/2012_06_04_07_world_misc.sql new file mode 100644 index 00000000000..947ba3b31ee --- /dev/null +++ b/sql/updates/world/2012_06_04_07_world_misc.sql @@ -0,0 +1,7 @@ +-- Add Missing spell to Jotunheim Rapid-Fire Harpoon close 6435 +UPDATE `creature_template` SET `spell1`=56585 WHERE `entry`=30337; +-- Wailing Winds missing aura +UPDATE `creature_template_addon` SET `auras`='56769' WHERE `entry`=30450; +-- Disturbed Taunka Ancestor missing aura +DELETE FROM `creature_template_addon` WHERE `entry`=30458; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (30458,1,43167); diff --git a/sql/updates/world/2012_06_05_00_world_sai.sql b/sql/updates/world/2012_06_05_00_world_sai.sql new file mode 100644 index 00000000000..c43998b7459 --- /dev/null +++ b/sql/updates/world/2012_06_05_00_world_sai.sql @@ -0,0 +1,13 @@ +-- Witch Doctor Mau'ari SAI +SET @ENTRY := 10307; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `quest_start_scripts` WHERE `id`=975; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=9 AND `entryorguid`=@ENTRY*100; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,19,0,100,0,975,0,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - On Quest Accept - Run Script'), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,81,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - Script - Remove npc flags'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,17,69,0,0,0,0,0,1,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - Script - Set emote state use standing'), +(@ENTRY*100,9,2,0,0,0,100,0,9000,9000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - Script - Set emote state use standing'), +(@ENTRY*100,9,3,0,0,0,100,0,1000,1000,0,0,81,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - Script - add npc flags'), +(@ENTRY*100,9,4,0,0,0,100,0,0,0,0,0,15,975,0,0,0,0,0,7,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - Script - Complete quest 975'); diff --git a/sql/updates/world/2012_06_05_01_world_gossip.sql b/sql/updates/world/2012_06_05_01_world_gossip.sql new file mode 100644 index 00000000000..11697eeffd4 --- /dev/null +++ b/sql/updates/world/2012_06_05_01_world_gossip.sql @@ -0,0 +1,24 @@ +-- Witch Doctor Mau'ari SAI +SET @ENTRY := 10307; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0 AND `id` IN (1,2); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,1,2,62,0,100,0,2703,2,0,0,85,16351,0,0,0,0,0,7,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - On Gossip Option 2 Select - Cast Spell'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Witch Doctor Mau''ari - On Gossip Option 2 Select - Close gossip'); +-- Add some missing gossip for Witch Doctor Mau'ari +UPDATE `creature_template` SET `gossip_menu_id`=2703,`ScriptName`='' WHERE `entry`=10307; +DELETE FROM `gossip_menu` WHERE `entry` IN (2703,21320,21321); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (2703,3375),(2703,3377),(21320,3382),(21321,3383); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=2703 AND `id` IN (0,1,2); +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`) VALUES +(2703,0,0, 'How do I use the Cache of Mau''ari?',1,1,21320,0,0,0, ''), +(2703,1,0, 'What is E''ko?',1,1,21321,0,0,0, ''), +(2703,2,0, 'I''d like you to make me a new Cache of Mau''ari please',1,1,0,0,0,0, ''); +-- Add conditions for gossip text +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=2703; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,2703,3377,0,8,975,0,0,0,0,'','Only show gossip text 3377 if player has completed quest 975'); +-- Add conditions for gossip options +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=2703; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,2703,2,0,8,975,0,0,0,0,'','Only show gossip option if player has completed quest 975'), +(15,2703,2,0,2,12384,1,1,1,0,'','Only show gossip option if player Does not have item 12384'); diff --git a/sql/updates/world/2012_06_05_01_world_gossip_sai.sql b/sql/updates/world/2012_06_05_01_world_gossip_sai.sql new file mode 100644 index 00000000000..84893613c75 --- /dev/null +++ b/sql/updates/world/2012_06_05_01_world_gossip_sai.sql @@ -0,0 +1,23 @@ +-- Lorax SAI +SET @ENTRY := 10918; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,62,0,100,0,3051,0,0,0,5,11,0,0,0,0,0,1,0,0,0,0,0,0,0,'Lorax - On Gossip Option Select - Laugh emote'), +(@ENTRY,0,1,2,62,0,100,0,3054,0,0,0,15,5126,0,0,0,0,0,7,0,0,0,0,0,0,0,'Lorax - On Gossip Option Select - Give Quest Credit'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Lorax - On Gossip Option Select - Close gossip'); +-- Lorax Gossip +DELETE FROM `gossip_menu` WHERE `entry` IN (3050,3051,3052,3053,3054); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (3050,3759),(3051,3760),(3052,3761),(3053,3762),(3054,3763); +DELETE FROM `gossip_menu_option` WHERE `menu_id` BETWEEN 3049 AND 3054; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`) VALUES +(3049,0,0, 'You will have to excuse me, Lorax, I do not speak ''crazy''.',1,1,3050,0,0,0, ''), +(3050,0,0, 'My apologies, I did not realize that you could understand what I was saying. What is it you are doing out here?',1,1,3051,0,0,0, ''), +(3051,0,0, 'Do you? Perhaps you should tell me what it is that is bothering you',1,1,3052,0,0,0, ''), +(3052,0,0, 'What deal?',1,1,3053,0,0,0, ''), +(3053,0,0, 'So how did he break the deal?',1,1,3054,0,0,0, ''), +(3054,0,0, 'Perhaps I can be of some assistance. I will make a deal with you, Satyr. I shall recover this unforged breastplate and slay the beast. In exchange for this task, you will teach me how to create the breastplate',1,1,0,0,0,0, ''); +-- Add conditions for gossip options +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=3049; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,3049,0,0,9,5126,0,0,0,0,'','Only show gossip option if player has quest 5126'); diff --git a/sql/updates/world/2012_06_05_03_world_script.sql b/sql/updates/world/2012_06_05_03_world_script.sql new file mode 100644 index 00000000000..d10247979d9 --- /dev/null +++ b/sql/updates/world/2012_06_05_03_world_script.sql @@ -0,0 +1,2 @@ +-- Frostblade Shrine Script for Quest The Cleansing +UPDATE `gameobject_template` SET `ScriptName`= 'go_frostblade_shrine' WHERE `entry`=186649; diff --git a/sql/updates/world/2012_06_06_00_world_script.sql b/sql/updates/world/2012_06_06_00_world_script.sql new file mode 100644 index 00000000000..727d28e8ea9 --- /dev/null +++ b/sql/updates/world/2012_06_06_00_world_script.sql @@ -0,0 +1,27 @@ +-- Remove Mistake +DELETE FROM `gossip_menu` WHERE `entry` IN (3050,3051,3052,3053,3054); +DELETE FROM `gossip_menu_option` WHERE `menu_id` BETWEEN 3050 AND 3054; +-- Lorax SAI +SET @ENTRY := 10918; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,62,0,100,0,21323,0,0,0,5,11,0,0,0,0,0,1,0,0,0,0,0,0,0,'Lorax - On Gossip Option Select - Laugh emote'), +(@ENTRY,0,1,2,62,0,100,0,21326,0,0,0,15,5126,0,0,0,0,0,7,0,0,0,0,0,0,0,'Lorax - On Gossip Option Select - Give Quest Credit'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Lorax - On Gossip Option Select - Close gossip'); +-- Lorax Gossip +DELETE FROM `gossip_menu` WHERE `entry` IN (21322,21323,21324,21325,21326); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (21322,3759),(21323,3760),(21324,3761),(21325,3762),(21326,3763); +DELETE FROM `gossip_menu_option` WHERE `menu_id`=3049; +DELETE FROM `gossip_menu_option` WHERE `menu_id` BETWEEN 21322 AND 21326; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`) VALUES +(3049,0,0, 'You will have to excuse me, Lorax, I do not speak ''crazy''.',1,1,21322,0,0,0, ''), +(21322,0,0, 'My apologies, I did not realize that you could understand what I was saying. What is it you are doing out here?',1,1,21323,0,0,0, ''), +(21323,0,0, 'Do you? Perhaps you should tell me what it is that is bothering you',1,1,21324,0,0,0, ''), +(21324,0,0, 'What deal?',1,1,21325,0,0,0, ''), +(21325,0,0, 'So how did he break the deal?',1,1,21326,0,0,0, ''), +(21326,0,0, 'Perhaps I can be of some assistance. I will make a deal with you, Satyr. I shall recover this unforged breastplate and slay the beast. In exchange for this task, you will teach me how to create the breastplate',1,1,0,0,0,0, ''); +-- Add conditions for gossip options +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=3049; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,3049,0,0,9,5126,0,0,0,0,'','Only show gossip option if player has quest 5126'); diff --git a/sql/updates/world/2012_06_06_01_world_sai.sql b/sql/updates/world/2012_06_06_01_world_sai.sql new file mode 100644 index 00000000000..97e175652d2 --- /dev/null +++ b/sql/updates/world/2012_06_06_01_world_sai.sql @@ -0,0 +1,42 @@ +-- Fix for Quest 11317 & 11322 "The Cleansing" +-- Your Inner Turmoil SAI +SET @ENTRY := 27959; +UPDATE `creature_template` SET `faction_A`=14,`faction_H`=14,`unit_flags`=`unit_flags`|256,`AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY*100 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,1,54,0,100,0,0,0,0,0,11,41408,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On Summon - Cast Shadowform on self'), +(@ENTRY,0,1,2,61,0,100,0,0,0,0,0,85,50218,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On Summon - Player Cast The Cleansing: Your Inner Turmoil''s Mirror Image Aura on npc'), +(@ENTRY,0,2,3,61,0,100,0,0,0,0,0,85,41054,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On Summon - Player Cast Copy Weapon on npc'), +(@ENTRY,0,3,4,61,0,100,0,0,0,0,0,85,41055,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On Summon - Player Cast Copy Weapon on npc'), +(@ENTRY,0,4,5,61,0,100,0,0,0,0,0,85,45205,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On Summon - Player Cast Copy Offhand Weapon on npc'), +(@ENTRY,0,5,6,61,0,100,0,0,0,0,0,85,45206,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On Summon - Player Cast Copy Offhand Weapon on npc'), +(@ENTRY,0,6,0,61,0,100,0,0,0,0,0,80,@ENTRY*100,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On Summon - Run Script'), +(@ENTRY,0,7,0,2,0,100,1,0,50,0,0,1,2,2,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - @50%hp - Say 2'), +(@ENTRY,0,8,9,6,0,100,1,0,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On death - Say 3'), +(@ENTRY,0,9,0,61,0,100,1,0,0,0,0,3,0,11686,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - On death - set model'), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Your Inner Turmoil - Script - Turn to invoker'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Your Inner Turmoil - Script - Say 0'), +(@ENTRY*100,9,2,0,0,0,100,0,6000,6000,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Your Inner Turmoil - Script - Turn to invoker'), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,7,0,0,0,0,0,0,0,'Your Inner Turmoil - Script - Say 1'), +(@ENTRY*100,9,4,0,0,0,100,0,7000,7000,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Your Inner Turmoil - Script - remove unit flags'), +(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,49,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Your Inner Turmoil - Script - Attack invoker'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0,'You think that you can get rid of me through meditation?',15,0,100,0,0,0,'Your Inner Turmoil text 0'), +(@ENTRY,1,0,'Fool! I will destroy you and finally become that which has been building inside of you all of these years!',15,0,100,0,0,0,'Your Inner Turmoil text 1'), +(@ENTRY,2,0,'You cannot defeat me. I''m an inseparable part of you!',15,0,100,0,0,0,'Your Inner Turmoil text 50%'), +(@ENTRY,3,0,'NOOOOOOOoooooooooo!',15,0,100,0,0,0,'Your Inner Turmoil text death'); +-- Spell Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (50218,41054,41055,45205,45206); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,50218,0,31,3,27959,0,0,'','Spell 50218 can target Your Inner Turmoil'), +(13,1,41054,0,31,3,27959,0,0,'','Spell 41054 can target Your Inner Turmoil'), +(13,1,41055,0,31,3,27959,0,0,'','Spell 41055 can target Your Inner Turmoil'), +(13,1,45205,0,31,3,27959,0,0,'','Spell 45205 can target Your Inner Turmoil'), +(13,1,45206,0,31,3,27959,0,0,'','Spell 45206 can target Your Inner Turmoil'); +-- Spell Linking +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=-43351; +INSERT INTO spell_linked_spell VALUES +(-43351,50167,0, ''), +(-43351,61720,0, ''); diff --git a/sql/updates/world/2012_06_06_02_world_sai.sql b/sql/updates/world/2012_06_06_02_world_sai.sql new file mode 100644 index 00000000000..297409ed776 --- /dev/null +++ b/sql/updates/world/2012_06_06_02_world_sai.sql @@ -0,0 +1,91 @@ +-- Fix Quest 11307 "Field Test" + +-- Remove hack +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=43385; + +-- Fix Plagued Proto-Dragon +UPDATE `creature_addon` SET `bytes1`=50331648 WHERE guid=107626; + +-- Plagued Dragonflayer Tribesman SAI +SET @ENTRY := 23564; +SET @SPELL1 := 15496; -- Cleave +SET @SPELL2 := 32736; -- Mortal Strike +SET @SPELL3 := 43506; -- Plague Blight +SET @SPELL4 := 43381; -- Plague Spray +SET @SPELL5 := 43384; -- Plague Credit +SET @SPELL6 := 43327; -- Vomit +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +UPDATE `creature_addon` SET `auras`= '21862' WHERE guid IN (SELECT guid FROM creature WHERE id=@ENTRY); +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@ENTRY,1,'21862'); +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,2,0,100,1,0,95,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - HP@95% - Set Phase 1'), +(@ENTRY,0,1,0,0,0,100,0,1000,1000,4000,5000,11,@SPELL1,0,0,0,0,0,2,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - Combat - Cast Cleave'), +(@ENTRY,0,2,0,0,0,100,0,2000,4000,5000,8000,11,@SPELL2,0,0,0,0,0,2,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - Combat - Cast Mortal Strike'), +(@ENTRY,0,3,0,2,0,100,1,0,75,0,0,11,@SPELL3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - HP@75% - Cast Plague Blight'), +(@ENTRY,0,4,0,23,1,100,0,@SPELL4,1,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - On Aura - Set phase 0 (phase 1)'), +(@ENTRY,0,5,0,0,1,100,0,1000,1000,1000,1000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - Combat - Set phase 2 (phase 1)'), +(@ENTRY,0,6,0,23,2,100,0,@SPELL4,1,0,0,22,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - On Spell Hit - Set Phase 3 (phase 2)'), +(@ENTRY,0,7,0,0,4,100,0,0,0,10000,10000,49,0,0,0,0,0,0,5,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - Combat - Attack Random target (phase 3)'), +(@ENTRY,0,8,0,6,4,100,0,0,0,0,0,85,@SPELL5,0,0,0,0,0,16,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - On Death - Give Killcredit (phase 3)'), +(@ENTRY,0,9,0,1,0,35,0,0,30000,25000,45000,11,@SPELL6,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - OOC - Cast 43327 on self'), +(@ENTRY,0,10,11,23,0,100,1,@SPELL4,1,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - On Spell Hit - Say 0'), +(@ENTRY,0,11,0,61,0,100,0,0,0,0,0,2,1925,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Tribesman - On Spell Hit - Set Faction'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0,'%s loses all self control and begins to attack friend and foe alike!',16,0,100,0,0,0,'Plagued Dragonflayer Tribesman'); + +-- Plagued Dragonflayer Rune-Caster SAI +SET @ENTRY := 24199; +SET @SPELL1 := 47782; -- Corruption +SET @SPELL2 := 15616; -- Flame Shock +SET @SPELL3 := 43381; -- Plague Spray +SET @SPELL4 := 43384; -- Plague Credit +SET @SPELL5 := 43327; -- Vomit +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +UPDATE `creature_addon` SET `auras`= '21862' WHERE guid IN (SELECT guid FROM creature WHERE id=@ENTRY); +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@ENTRY,1,'21862'); +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,2,0,100,1,0,95,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - HP@95% - Set Phase 1'), +(@ENTRY,0,1,0,4,0,100,0,0,0,0,0,11,@SPELL1,0,0,0,0,0,2,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - On aggro - Cast Corruption'), +(@ENTRY,0,2,0,0,0,100,0,2000,4000,15000,17000,11,@SPELL2,0,0,0,0,0,5,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - Combat - Cast Flame Shock'), +(@ENTRY,0,3,0,23,1,100,0,@SPELL3,1,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - On Aura - Set phase 0 (phase 1)'), +(@ENTRY,0,4,0,0,1,100,0,1000,1000,1000,1000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - Combat - Set phase 2 (phase 1)'), +(@ENTRY,0,5,0,23,2,100,0,@SPELL3,1,0,0,22,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - On Spell Hit - Set Phase 3 (phase 2)'), +(@ENTRY,0,6,0,0,4,100,0,0,0,10000,10000,49,0,0,0,0,0,0,5,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - Combat - Attack Random target (phase 3)'), +(@ENTRY,0,7,0,6,4,100,0,0,0,0,0,85,@SPELL4,0,0,0,0,0,16,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - On Death - Give Killcredit (phase 3)'), +(@ENTRY,0,8,0,1,0,35,0,0,30000,25000,45000,11,@SPELL5,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - OOC - Cast 43327 on self'), +(@ENTRY,0,9,10,23,0,100,1,@SPELL3,1,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - On Spell Hit - Say 0'), +(@ENTRY,0,10,0,61,0,100,0,0,0,0,0,2,1925,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Rune-Caster - On Spell Hit - Set Faction'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0,'%s loses all self control and begins to attack friend and foe alike!',16,0,100,0,0,0,'Plagued Dragonflayer Rune-Caster'); + +-- Plagued Dragonflayer Handler SAI +SET @ENTRY := 24199; +SET @SPELL1 := 43506; -- Plague Blight +SET @SPELL2 := 43381; -- Plague Spray +SET @SPELL3 := 43384; -- Plague Credit +SET @SPELL4 := 43327; -- Vomit +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +UPDATE `creature_addon` SET `auras`= '21862' WHERE guid IN (SELECT guid FROM creature WHERE id=@ENTRY); +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@ENTRY,1,'21862'); +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,2,0,100,1,0,95,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - HP@95% - Set Phase 1'), +(@ENTRY,0,1,0,2,0,100,1,0,75,0,0,11,@SPELL1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - HP@75% - Cast Plague Blight'), +(@ENTRY,0,2,0,23,1,100,0,@SPELL2,1,0,0,22,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - On Aura - Set phase 0 (phase 1)'), +(@ENTRY,0,3,0,0,1,100,0,1000,1000,1000,1000,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - Combat - Set phase 2 (phase 1)'), +(@ENTRY,0,4,0,23,2,100,0,@SPELL2,1,0,0,22,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - On Spell Hit - Set Phase 3 (phase 2)'), +(@ENTRY,0,5,0,0,4,100,0,0,0,10000,10000,49,0,0,0,0,0,0,5,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - Combat - Attack Random target (phase 3)'), +(@ENTRY,0,6,0,6,4,100,0,0,0,0,0,85,@SPELL3,0,0,0,0,0,16,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - On Death - Give Killcredit (phase 3)'), +(@ENTRY,0,7,0,1,0,35,0,0,30000,25000,45000,11,@SPELL4,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - OOC - Cast 43327 on self'), +(@ENTRY,0,8,9,23,0,100,1,@SPELL2,1,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - On Spell Hit - Say 0'), +(@ENTRY,0,9,0,61,0,100,0,0,0,0,0,2,1925,0,0,0,0,0,1,0,0,0,0,0,0,0,'Plagued Dragonflayer Handler - On Spell Hit - Set Faction'); +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0,'%s loses all self control and begins to attack friend and foe alike!',16,0,100,0,0,0,'Plagued Dragonflayer Handler'); diff --git a/sql/updates/world/2012_06_06_03_world_conditions.sql b/sql/updates/world/2012_06_06_03_world_conditions.sql new file mode 100644 index 00000000000..c9af2a1bcbc --- /dev/null +++ b/sql/updates/world/2012_06_06_03_world_conditions.sql @@ -0,0 +1,2 @@ +-- Spell conditions shouldn't have been added +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (41054,41055,45205,45206); diff --git a/sql/updates/world/2012_06_06_04_world_sai.sql b/sql/updates/world/2012_06_06_04_world_sai.sql new file mode 100644 index 00000000000..af820f418be --- /dev/null +++ b/sql/updates/world/2012_06_06_04_world_sai.sql @@ -0,0 +1,19 @@ +-- Forsaken Plaguebringer SAI +SET @ENTRY := 23760; +SET @SPELL1 := 44005; -- Shoot Plague +SET @SPELL2 := 3436; -- Wandering Plague +SET @SPELL3 := 11978; -- Kick +SET @SPELL4 := 43333; -- Shoot Plague +UPDATE `creature_template` SET `equipment_id`=509,`AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`) VALUES (@ENTRY,2); +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,4000,11000,7000,11000,11,@SPELL1,0,0,0,0,0,2,0,0,0,0,0,0,0,'Forsaken Plaguebringer - Combat - Cast Shoot Plague'), +(@ENTRY,0,1,0,0,0,100,0,4000,10000,40000,50000,11,@SPELL2,0,0,0,0,0,2,0,0,0,0,0,0,0,'Forsaken Plaguebringer - Combat - Cast Wandering Plague'), +(@ENTRY,0,2,0,0,0,80,0,4000,12000,12000,18000,11,@SPELL3,0,0,0,0,0,2,0,0,0,0,0,0,0,'Forsaken Plaguebringer - Combat - Cast Kick'), +(@ENTRY,0,3,0,10,0,100,0,24042,40,6000,11000,11,@SPELL4,0,0,0,0,0,1,0,0,0,0,0,0,0,'Forsaken Plaguebringer - OOC - Cast Shoot Plague'); -- Not working correctly +-- Spell Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (43333); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,43333,0,31,3,24042,0,0,'','Spell 43333 can target Generic Trigger LAB - OLD'); diff --git a/sql/updates/world/2012_06_07_00_world_gossip.sql b/sql/updates/world/2012_06_07_00_world_gossip.sql new file mode 100644 index 00000000000..aac3ac53e74 --- /dev/null +++ b/sql/updates/world/2012_06_07_00_world_gossip.sql @@ -0,0 +1,39 @@ +-- SAI for Charles Worth +SET @NPC := 28699; +SET @GOSSIP := 10118; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@NPC; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@NPC; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@NPC,0,0,2,62,0,100,0,@GOSSIP,3,0,0,85,59817,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Charles Worth - On Gossip Select - Cast Spell Teach Wispcloak'), +(@NPC,0,1,2,62,0,100,0,@GOSSIP,5,0,0,85,59841,2,0,0,0,0,7,0,0,0,0,0,0,0, 'Charles Worth - On Gossip Select - Cast Spell Teach Deathchill Cloak'), +(@NPC,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0, 'Charles Worth - On Gossip Select - Close Gossip'); +-- Add missing Gossip for Charles Worth +DELETE FROM `gossip_menu` WHERE `entry` IN (10136,10138); +DELETE FROM `gossip_menu` WHERE `entry`=10118 AND `text_id`=14076; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (10136,14072),(10138,14074),(10118,14076); +-- Add Gossip Options +DELETE FROM `gossip_menu_option` WHERE `menu_id`=@GOSSIP AND `id` IN (2,3,4,5); +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`) VALUES +(@GOSSIP,2,0, 'Tell me about the Wispcloak Recipe.',1,1,10136,0,0,0, ''), +(@GOSSIP,3,0, 'I am ready to learn the Wispcloak Recipe.',1,1,0,0,0,0, ''), +(@GOSSIP,4,0, 'Tell me about the Deathchill Cloak Recipe.',1,1,10138,0,0,0, ''), +(@GOSSIP,5,0, 'I am ready to learn the Deathchill Cloak Recipe.',1,1,0,0,0,0, ''); +-- Add conditions for gossip text +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=@GOSSIP; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,@GOSSIP,14076,0,7,197,420,0,0,0,'','Only show gossip text 14076 if player has Tailoring with skill level 420'); +-- Add conditions for gossip options +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=@GOSSIP; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,@GOSSIP,2,0,7,197,420,0,0,0,'','Only show gossip option if player has Tailoring with skill level 420'), +(15,@GOSSIP,2,0,25,56016,0,0,1,0,'','Only show gossip option if player has not learned spell 56016'), +(15,@GOSSIP,3,0,7,197,420,0,0,0,'','Only show gossip option if player has Tailoring with skill level 420 Alliance'), +(15,@GOSSIP,3,0,17,41,0,0,0,0,'','Only show gossip option if player has achievement Loremaster of Northrend Alliance'), +(15,@GOSSIP,3,1,7,197,420,0,0,0,'','Only show gossip option if player has Tailoring with skill level 420 Horde'), +(15,@GOSSIP,3,1,17,1360,0,0,0,0,'','Only show gossip option if player has achievement Loremaster of Northrend Horde'), +(15,@GOSSIP,3,0,25,56016,0,0,1,0,'','Only show gossip option if player has not learned spell 56016'), +(15,@GOSSIP,4,0,7,197,420,0,0,0,'','Only show gossip option if player has Tailoring with skill level 420'), +(15,@GOSSIP,4,0,25,56017,0,0,1,0,'','Only show gossip option if player has not learned spell 56017'), +(15,@GOSSIP,5,0,7,197,420,0,0,0,'','Only show gossip option if player has Tailoring with skill level 420'), +(15,@GOSSIP,5,0,17,1288,0,0,0,0,'','Only show gossip option if player has achievement Northrend Dungeonmaster'), +(15,@GOSSIP,5,0,25,56017,0,0,1,0,'','Only show gossip option if player has not learned spell 56017'); diff --git a/sql/updates/world/2012_06_07_01_world_gossip.sql b/sql/updates/world/2012_06_07_01_world_gossip.sql new file mode 100644 index 00000000000..d77d41fa523 --- /dev/null +++ b/sql/updates/world/2012_06_07_01_world_gossip.sql @@ -0,0 +1,11 @@ +-- Fix Gossip for Leryssa +SET @ENTRY := 9223; +SET @TEXT1 := 12534; +SET @TEXT2 := 13481; +SET @QUEST := 11599; +DELETE FROM `gossip_menu` WHERE `entry`=@ENTRY AND `text_id`=@TEXT1; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (@ENTRY,@TEXT1); +-- Add conditions for gossip text +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=@ENTRY AND `SourceEntry`=@TEXT2; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,@ENTRY,@TEXT2,0,8,@QUEST,0,0,0,0,'','Only show gossip text if player has completed quest 11599'); diff --git a/sql/updates/world/2012_06_07_02_world_item_template.sql b/sql/updates/world/2012_06_07_02_world_item_template.sql new file mode 100644 index 00000000000..fdf3cce7c24 --- /dev/null +++ b/sql/updates/world/2012_06_07_02_world_item_template.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `flags` = `flags` | 2048 WHERE `entry` IN (50274,50226,50231); diff --git a/sql/updates/world/2012_06_07_03_world_item_template.sql b/sql/updates/world/2012_06_07_03_world_item_template.sql new file mode 100644 index 00000000000..a6caa15632e --- /dev/null +++ b/sql/updates/world/2012_06_07_03_world_item_template.sql @@ -0,0 +1 @@ +UPDATE `item_template` SET `flags` = 0 WHERE `entry` IN (50274,50226,50231); diff --git a/sql/updates/world/2012_06_07_04_world_spell_dbc.sql b/sql/updates/world/2012_06_07_04_world_spell_dbc.sql new file mode 100644 index 00000000000..de5753fc7a6 --- /dev/null +++ b/sql/updates/world/2012_06_07_04_world_spell_dbc.sql @@ -0,0 +1,8 @@ +-- add missing spell to db +DELETE FROM `spell_dbc` WHERE `Id`=28782; +INSERT INTO `spell_dbc` (`Id`,`SchoolMask`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`Comment`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`DmgMultiplier1`,`DmgMultiplier2`,`AreaGroupId`)VALUES +(28782,0,0,0,256,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,21,1,0,-1,0,0,6,6,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,12,40,0,0,0,0,0,0,0,0,127,0,0,0,0, 'Stun Self + Immune',0,0,0,0,0,0,0,1,1,0); + +-- Add Stun Self + Immune aura to Snack-O-Matic IV & Vend-O-Tron D-Luxe +DELETE FROM `creature_template_addon` WHERE `entry` IN (24934,24935); +INSERT INTO `creature_template_addon` (`entry`,`auras`) VALUES (24934, '28782'),(24935, '28782'); diff --git a/sql/updates/world/2012_06_07_05_world_misc.sql b/sql/updates/world/2012_06_07_05_world_misc.sql new file mode 100644 index 00000000000..d45384dd3ef --- /dev/null +++ b/sql/updates/world/2012_06_07_05_world_misc.sql @@ -0,0 +1,117 @@ +-- Remove some bad spawns in world +DELETE FROM `creature` WHERE `guid` IN (45208,45099,45075,45136,12925,12402); +DELETE FROM `creature_addon` WHERE `guid` IN (45208,45099,45075,45136,12925,12402); + +-- Some missing Gossip +UPDATE `creature_template` SET `gossip_menu_id`=9054 WHERE `entry`=25021; +UPDATE `creature_template` SET `gossip_menu_id`=9056 WHERE `entry`=25022; +UPDATE `creature_template` SET `gossip_menu_id`=9057 WHERE `entry`=25023; +UPDATE `creature_template` SET `gossip_menu_id`=9054 WHERE `entry`=25024; +UPDATE `creature_template` SET `gossip_menu_id`=9077 WHERE `entry`=25025; +DELETE FROM `gossip_menu` WHERE `entry`=9054 AND `text_id`=12243; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (9054,12243); +DELETE FROM `gossip_menu` WHERE `entry`=9057 AND `text_id`=12245; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (9057,12245); +DELETE FROM `gossip_menu` WHERE `entry`=9077 AND `text_id`=12275; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (9077,12275); + +-- Zeppelin: <The Thundercaller> "Durotar to Tirisfal Glades" +DELETE FROM `creature_transport` WHERE `transport_entry`=164871; +INSERT INTO `creature_transport` (`guid`,`transport_entry`,`npc_entry`,`TransOffsetX`,`TransOffsetY`,`TransOffsetZ`,`TransOffsetO`,`emote`) VALUES +(1,164871,15214,7.005304,-7.647912,-16.11262,2.897247,0), -- Invisible Stalker +(2,164871,24934,-4.516505,-13.11248,-22.59472,1.53589,0), -- Snack-O-Matic IV +(3,164871,24935,-6.37827,-13.18376,-22.59391,4.712389,0), -- Vend-O-Tron D-Luxe +(4,164871,25070,-9.407872,-8.023982,-17.15783,3.176499,0), -- Chief Officer Coppernut <The Thundercaller> +(5,164871,25071,7.248865,-5.480326,-17.68592,4.817109,432), -- Crewman Rusthammer <The Thundercaller> +(6,164871,25072,8.008065,-10.71344,-17.67366,1.169371,432), -- Crewman Quickfix <The Thundercaller> +(7,164871,25074,5.023749,-7.69781,-17.78876,5.986479,432), -- Crewman Sparkfly <The Thundercaller> +(8,164871,25075,-8.875813,-11.40282,-22.5883,6.248279,0), -- Zeppelin Controls +(9,164871,25075,-3.307774,-9.474165,-23.69589,1.553343,0), -- Zeppelin Controls +(10,164871,25075,4.482075,-13.40077,-23.59003,1.623156,0), -- Zeppelin Controls +(11,164871,25075,-3.314179,-6.128806,-23.69835,4.677482,0), -- Zeppelin Controls +(12,164871,25075,4.362147,-2.254167,-23.59002,4.712389,0), -- Zeppelin Controls +(13,164871,25075,-4.161887,-7.687522,-23.69754,0,0), -- Zeppelin Controls +(14,164871,25075,11.74357,-10.44521,-24.21887,6.161012,0), -- Zeppelin Controls +(15,164871,25075,10.82609,-12.18536,-23.48949,3.176499,0), -- Zeppelin Controls +(16,164871,25075,10.70341,-3.505423,-23.49001,3.246312,0), -- Zeppelin Controls +(17,164871,25076,-2.727229,-7.772857,-23.69677,1.553343,432), -- Navigator Fairweather <The Thundercaller> +(18,164871,25077,-19.68856,-8.170582,-14.37648,3.176499,0), -- Sky-Captain Cloudkicker <The Thundercaller> +(19,164871,25079,-5.1094,-11.14663,-17.60601,4.485496,0), -- Deathguard Fowles <The Thundercaller> +(20,164871,25083,-5.212496,-4.927022,-17.5966,1.43117,0), -- Deathguard Lawson <The Thundercaller> +(21,164871,25171,-8.703286,-11.40788,-22.58871,0.03490658,0); -- Invisible Stalker (Scale x0.5) +-- gameobject 21680 -6.905273,-4.876801,-17.51628,5.911792 Rotation: 0,0,0.9850225,0.1724255 + +-- Zeppelin: <The Zephyr> "Durotar to Thunder Bluff" +DELETE FROM `creature_transport` WHERE `transport_entry`=190549; +INSERT INTO `creature_transport` (`guid`,`transport_entry`,`npc_entry`,`TransOffsetX`,`TransOffsetY`,`TransOffsetZ`,`TransOffsetO`,`emote`) VALUES +(1,190549,3084,-4.83257,-4.312334,-17.63218,1.623156,0), -- Bluffwatcher +(2,190549,3084,-5.206744,-11.34318,-17.61012,4.712389,0), -- Bluffwatcher +(3,190549,24934,10.32099,-3.573514,-23.49413,3.176499,0), -- Snack-O-Matic IV +(4,190549,24935,10.2871,-12.02722,-23.49424,3.106686,0), -- Vend-O-Tron D-Luxe +(5,190549,25075,-3.396398,-7.905448,-23.69672,6.248279,0), -- Zeppelin Controls +(6,190549,34715,-9.183155,-7.775729,-17.21699,3.281219,0), -- Sky-Captain "Dusty" Blastnut <The Zephyr> +(7,190549,34717,-13.67017,-12.40177,-15.98756,4.590216,0), -- Crewman Pipewrench <The Zephyr> +(8,190549,34718,13.74505,-5.128461,-24.04518,0.1396263,207), -- Crewman Deadbolt <The Zephyr> +(9,190549,34719,7.623085,-5.025319,-17.67015,4.921828,28), -- Crewman Grit <The Zephyr> +(10,190549,34721,-0.919197,-6.164221,-23.67286,3.577925,0), -- Chief Officer Ograh <The Zephyr> +(11,190549,34723,-17.47968,-5.606984,-14.92807,3.228859,0), -- Watcher Tolwe <The Zephyr> +(12,190549,34730,-2.166869,-7.854215,-23.6919,3.385939,0); -- Navigator Zippik <The Zephyr> + +-- Zeppelin: <The Iron Eagle> "Durotar to Stranglethorn Val" +DELETE FROM `creature_transport` WHERE `transport_entry`=175080; +INSERT INTO `creature_transport` (`guid`,`transport_entry`,`npc_entry`,`TransOffsetX`,`TransOffsetY`,`TransOffsetZ`,`TransOffsetO`,`emote`) VALUES +(1,175080,24924,-1.207598,-9.948863,-23.67485,0.1570796,0), -- Sky-Captain Bomblast <The Iron Eagle> +(2,175080,24926,-10.3057,-12.10524,-16.96907,5.927236,0), -- Chief Officer Brassbolt <The Iron Eagle> <PATHING> +(3,175080,24927,-1.874165,-7.847112,-23.68718,3.385939,0), -- Navigator Sparksizzle <The Iron Eagle> +(4,175080,24929,9.083008,-4.964111,-23.59211,1.594056,0), -- Crewman Crosswire <The Iron Eagle> +(5,175080,24930,-17.0083,-7.874878,-15.18782,3.141593,0), -- Crewman Gazzlegear <The Iron Eagle> +(6,175080,24931,7.884921,-11.15133,-17.76227,4.90483,432), -- Crewman Fastwrench <The Iron Eagle> <PATHING> +(7,175080,24934,9.209188,-3.503923,-23.51212,3.124139,0), -- Snack-O-Matic IV +(8,175080,24935,9.554915,-12.02288,-23.50588,3.124139,0), -- Vend-O-Tron D-Luxe +(9,175080,25075,-2.705565,-7.845885,-23.6967,0.03490658,0), -- Zeppelin Controls +(10,175080,25080,-4.910018,-4.742365,-17.61534,1.605703,0), -- Grunt Umgor +(11,175080,25081,-4.939394,-10.80493,-17.61089,4.712389,0); -- Grunt Ounda + +-- Zeppelin: <The Mighty Wind> "Durotar to Borean Tundra" +DELETE FROM `creature_transport` WHERE `transport_entry`=186238; +INSERT INTO `creature_transport` (`guid`,`transport_entry`,`npc_entry`,`TransOffsetX`,`TransOffsetY`,`TransOffsetZ`,`TransOffsetO`,`emote`) VALUES +(1,186238,25075,9.44542,-7.849475,-16.60061,0.05235988,0), -- Zeppelin Controls +(2,186238,31720,-16.56853,-5.083331,-15.94212,1.989675,0), -- Crewman Shubbscoop <The Mighty Wind> +(3,186238,31723,-10.75516,-12.81286,-16.77452,4.537856,0), -- Crewman Barrowswizzle <The Mighty Wind> +(4,186238,31724,5.77627,-2.004689,-17.72185,1.64061,0), -- Crewman Paltertop <The Mighty Wind> +(5,186238,31725,10.69841,-7.821921,-16.60061,3.281219,0), -- Sky-Captain LaFontaine <The Mighty Wind> +(6,186238,31726,-3.453068,-13.78959,-17.61107,1.43117,0), -- Grunt Gritch +(7,186238,31727,-3.383076,-1.913925,-17.6198,4.729842,0); -- Grunt Grikee + +-- Ship: <Northspear> "Wetlands to Howling Fjord" +DELETE FROM `creature_transport` WHERE `transport_entry`=181688; +INSERT INTO `creature_transport` (`guid`,`transport_entry`,`npc_entry`,`TransOffsetX`,`TransOffsetY`,`TransOffsetZ`,`TransOffsetO`,`emote`) VALUES +(1,181688,31759,-9.170654,-9.222412,9.44523,4.339638,0), -- Sailor Jansen <Northspear> +(2,181688,31760,-24.34204,-1.495605,11.79066,4.531185,0), -- Sailor Berg <Northspear> +(3,181688,31761,17.25,3.982666,9.827404,1.127068,0), -- Sailor Davies <Northspear> +(4,181688,31762,34.08345,-0.002845,19.79711,3.124139,0), -- Navigator Marcus <Northspear> +(5,181688,31763,30.11512,-5.088479,19.32816,3.089233,0), -- Captain John Brookman <Northspear> +(6,181688,31764,26.07068,2.057755,19.32802,3.001966,0); -- First Mate Kacy Dishon <Northspear> + +-- Ship: <The Kraken> "Stormwind to Borean Tundra" +DELETE FROM `creature_transport` WHERE `transport_entry`=190536; +INSERT INTO `creature_transport` (`guid`,`transport_entry`,`npc_entry`,`TransOffsetX`,`TransOffsetY`,`TransOffsetZ`,`TransOffsetO`,`emote`) VALUES +(1,190536,31788,27.59511,-2.344238,19.32811,3.228859,0), -- Captain Constance <The Kraken> +(2,190536,31789,28.09979,5.993899,19.32799,3.647738,0), -- First Mate Fitzgerald <The Kraken> +(3,190536,31790,34.22358,0.067648,19.76266,3.071779,0), -- Navigator Meyer <The Kraken> +(4,190536,31791,0.919363,8.75723,9.436611,1.256637,0), -- Sailor Dawning <The Kraken> +(5,190536,31792,-4.766113,0.09985352,9.36669,4.834562,0), -- Sailor Picardo <The Kraken> +(6,190536,31793,17.146,-3.921387,9.813052,5.497081,0); -- Sailor Phillips <The Kraken> + +-- Ship: <Feathermoon Ferry> "Feralas to Feathermoon Stronghold" +DELETE FROM `creature_transport` WHERE `transport_entry`=177233; +INSERT INTO `creature_transport` (`guid`,`transport_entry`,`npc_entry`,`TransOffsetX`,`TransOffsetY`,`TransOffsetZ`,`TransOffsetO`,`emote`) VALUES +(1,177233,3681,-38.64771,-0.071194,6.08577,0.06981317,0), -- Wisp +(2,177233,3681,29.56227,0.119925,24.45391,0.08726646,0), -- Wisp +(3,177233,25019,12.80499,-7.601957,6.105068,2.9147,0), -- Merchant Felagunne <Feathermoon Ferry> +(4,177233,25020,12.95386,7.333937,6.131125,3.281219,0), -- Galley Chief Alunwea <Feathermoon Ferry> +(5,177233,25021,-21.41735,-2.833596,4.391686,6.248279,0), -- Mariner Moonblade <Feathermoon Ferry> +(6,177233,25022,20.86332,-1.285908,11.80898,2.949606,0), -- Mariner Stillwake <Feathermoon Ferry> +(7,177233,25023,-36.76907,0.169367,5.975922,3.176499,0), -- Mariner Everwatch <Feathermoon Ferry> +(8,177233,25024,-21.65951,3.22012,4.402726,0.1396263,0), -- Mariner Softsong <Feathermoon Ferry> +(9,177233,25025,31.13095,-0.454317,16.73282,2.96706,0); -- Captain Idrilae <Feathermoon Ferry> diff --git a/sql/updates/world/2012_06_08_00_world_spell_bonus_data.sql b/sql/updates/world/2012_06_08_00_world_spell_bonus_data.sql new file mode 100644 index 00000000000..bf899421605 --- /dev/null +++ b/sql/updates/world/2012_06_08_00_world_spell_bonus_data.sql @@ -0,0 +1 @@ +UPDATE `spell_bonus_data` SET `direct_bonus`=0.571 WHERE `entry`=51505; diff --git a/sql/updates/world/2012_06_09_00_world_creature.sql b/sql/updates/world/2012_06_09_00_world_creature.sql new file mode 100644 index 00000000000..b2454b54163 --- /dev/null +++ b/sql/updates/world/2012_06_09_00_world_creature.sql @@ -0,0 +1,21 @@ +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`=36725; -- Nerub'ar Broodkeeper + +DELETE FROM `creature` WHERE `guid` IN (200939,200949,200956,201106,201127,201170); +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`MovementType`) VALUES +(200939,36725,631,15,1,-210.3750,2202.675,75.09233,0.13962630,7200,0,0), -- Nerub'ar Broodkeeper +(200949,36725,631,15,1,-220.3819,2177.068,81.70050,0.85521130,7200,0,0), -- Nerub'ar Broodkeeper +(200956,36725,631,15,1,-216.4861,2245.405,81.70050,5.18362800,7200,0,0), -- Nerub'ar Broodkeeper +(201106,36725,631,15,1,-211.2899,2219.420,75.09233,0.15707960,7200,0,0), -- Nerub'ar Broodkeeper +(201127,36725,631,15,1,-249.8542,2219.672,86.27979,5.95157300,7200,0,0), -- Nerub'ar Broodkeeper +(201170,36725,631,15,1,-250.6129,2203.800,86.27979,0.03490658,7200,0,0); -- Nerub'ar Broodkeeper + +DELETE FROM `creature_addon` WHERE `guid` IN (200912,200934,200939,200949,200956,201106,201127,201170); +INSERT INTO `creature_addon` (`guid`,`mount`,`bytes1`,`bytes2`,`auras`) VALUES +(200912,0,0x3000000,0x1,''), -- Nerub'ar Broodkeeper +(200934,0,0x3000000,0x1,''), -- Nerub'ar Broodkeeper +(200939,0,0x3000000,0x1,''), -- Nerub'ar Broodkeeper +(200949,0,0x3000000,0x1,''), -- Nerub'ar Broodkeeper +(200956,0,0x3000000,0x1,''), -- Nerub'ar Broodkeeper +(201106,0,0x3000000,0x1,''), -- Nerub'ar Broodkeeper +(201127,0,0x3000000,0x1,''), -- Nerub'ar Broodkeeper +(201170,0,0x3000000,0x1,''); -- Nerub'ar Broodkeeper diff --git a/sql/updates/world/2012_06_12_00_world_transport.sql b/sql/updates/world/2012_06_12_00_world_transport.sql new file mode 100644 index 00000000000..d3a35c254d9 --- /dev/null +++ b/sql/updates/world/2012_06_12_00_world_transport.sql @@ -0,0 +1,82 @@ +-- Zeppelin: <The Zephyr> "Durotar to Thunder Bluff" +SET @GUID := 43468; +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID AND @GUID+11; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@GUID,3084,647,1,1,0,0,-4.83257,-4.312334,-17.63218,1.623156,180,0,0,1,0,0), -- Bluffwatcher +(@GUID+1,3084,647,1,1,0,0,-5.206744,-11.34318,-17.61012,4.712389,180,0,0,1,0,0), -- Bluffwatcher +(@GUID+2,24934,647,1,1,0,0,10.32099,-3.573514,-23.49413,3.176499,180,0,0,1,0,0), -- Snack-O-Matic IV +(@GUID+3,24935,647,1,1,0,0,10.2871,-12.02722,-23.49424,3.106686,180,0,0,1,0,0), -- Vend-O-Tron D-Luxe +(@GUID+4,25075,647,1,1,0,0,-3.396398,-7.905448,-23.69672,6.248279,180,0,0,1,0,0), -- Zeppelin Controls +(@GUID+5,34715,647,1,1,0,0,-9.183155,-7.775729,-17.21699,3.281219,180,0,0,1,0,0), -- Sky-Captain "Dusty" Blastnut <The Zephyr> +(@GUID+6,34717,647,1,1,0,0,-13.67017,-12.40177,-15.98756,4.590216,180,0,0,1,0,2), -- Crewman Pipewrench <The Zephyr> +(@GUID+7,34718,647,1,1,0,0,13.74505,-5.128461,-24.04518,0.1396263,180,0,0,1,0,0), -- Crewman Deadbolt <The Zephyr> +(@GUID+8,34719,647,1,1,0,0,7.623085,-5.025319,-17.67015,4.921828,180,0,0,1,0,0), -- Crewman Grit <The Zephyr> +(@GUID+9,34721,647,1,1,0,0,-0.919197,-6.164221,-23.67286,3.577925,180,0,0,1,0,0), -- Chief Officer Ograh <The Zephyr> +(@GUID+10,34723,647,1,1,0,0,-17.47968,-5.606984,-14.92807,3.228859,180,0,0,1,0,0), -- Watcher Tolwe <The Zephyr> +(@GUID+11,34730,647,1,1,0,0,-2.166869,-7.854215,-23.6919,3.385939,180,0,0,1,0,0); -- Navigator Zippik <The Zephyr> +DELETE FROM `creature_template_addon` WHERE `entry` IN (34718,34719); +INSERT INTO `creature_template_addon` (`entry`,`bytes1`,`bytes2`,`emote`) VALUES +(34718,3,1,0),(34719,0,1,133); +-- Pathing for Crewman Pipewrench <The Zephyr> Entry: 34717 +SET @NPC := @GUID+6; +SET @PATH := @NPC * 10; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,1,69, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-13.66992,-12.40186,-16.09792,4.590216,26000,0,0,100,0), +(@PATH,2,-14.49512,-9.873911,-15.99125,0,0,0,0,100,0), +(@PATH,3,-14.49512,-6.373911,-15.99125,0,0,0,0,100,0), +(@PATH,4,-14.31525,-3.41333,-15.88589,0,24000,0,0,100,0); +-- Zeppelin: <The Zephyr> SAI +SET @ENTRY := 190549; +UPDATE `gameobject_template` SET `AIName`= 'SmartGameObjectAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=1; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100,@ENTRY*100+1,@ENTRY*100+2,@ENTRY*100+3) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,1,0,0,71,0,100,0,21868,0,0,0,80,@ENTRY*100 ,0,0,0,0,0,1,0,0,0,0,0,0,0,'Zeppelin: <The Zephyr> - Event Dock Orgrimmar - Run Script'), +(@ENTRY,1,1,0,71,0,100,0,21869,0,0,0,80,@ENTRY*100+1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Zeppelin: <The Zephyr> - Event Leave Orgrimmar - Run Script'), +(@ENTRY,1,2,0,71,0,100,0,21870,0,0,0,80,@ENTRY*100+2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Zeppelin: <The Zephyr> - Event Dock Thunder Bluff - Run Script'), +(@ENTRY,1,3,0,71,0,100,0,21871,0,0,0,80,@ENTRY*100+3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Zeppelin: <The Zephyr> - Event Leave Thunder Bluff - Run Script'), +-- Script 0 +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,19,34715,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Orgrimmar - Sky-Captain Blastnut Say 0'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Orgrimmar - Chief Officer Ograh Say 1'), +(@ENTRY*100,9,2,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,19,34765,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Orgrimmar - Zelli Hotnozzle Say 0'), +(@ENTRY*100,9,3,0,0,0,100,0,3000,3000,0,0,5,5,0,0,0,0,0,19,34715,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Orgrimmar - Sky-Captain Blastnut emote'), +(@ENTRY*100,9,4,0,0,0,100,0,1000,1000,0,0,5,25,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Orgrimmar - Chief Officer Ograh emote'), +-- Script 1 +(@ENTRY*100+1,9,0,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,19,34715,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Leave Orgrimmar - Sky-Captain Blastnut Say 1'), +(@ENTRY*100+1,9,1,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Leave Orgrimmar - Chief Officer Ograh Say 0'), +(@ENTRY*100+1,9,2,0,0,0,100,0,4000,4000,0,0,5,25,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Leave Orgrimmar - Chief Officer Ograh emote'), +-- Script 2 +(@ENTRY*100+2,9,0,0,0,0,100,0,0,0,0,0,1,2,0,0,0,0,0,19,34715,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Thunder Bluff - Sky-Captain Blastnut Say 2'), +(@ENTRY*100+2,9,1,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Thunder Bluff - Chief Officer Ograh Say 1'), +(@ENTRY*100+2,9,2,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,19,34766,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Thunder Bluff - Krendle Bigpockets Say 0'), +(@ENTRY*100+2,9,3,0,0,0,100,0,3000,3000,0,0,5,5,0,0,0,0,0,19,34715,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Thunder Bluff - Sky-Captain Blastnut emote'), +(@ENTRY*100+2,9,4,0,0,0,100,0,1000,1000,0,0,5,25,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Dock Thunder Bluff - Chief Officer Ograh emote'), +-- Script 3 +(@ENTRY*100+3,9,0,0,0,0,100,0,0,0,0,0,1,3,0,0,0,0,0,19,34715,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Leave Thunder Bluff - Sky-Captain Blastnut Say 3'), +(@ENTRY*100+3,9,1,0,0,0,100,0,0,0,0,0,1,2,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Leave Thunder Bluff - Chief Officer Ograh Say 2'), +(@ENTRY*100+3,9,2,0,0,0,100,0,4000,4000,0,0,5,25,0,0,0,0,0,19,34721,100,0,0,0,0,0,'Zeppelin: <The Zephyr> - Script Leave Thunder Bluff - Chief Officer Ograh emote'); +-- Watcher Tolwe <The Zephyr> SAI +SET @ENTRY := 34723; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,1,0,100,0,60000,120000,60000,120000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Watcher Tolwe <The Zephyr> - OOC - Say Random'); +-- Text for Watcher Tolwe, Sky-Captain Blastnut, Chief Officer Ograh, Krendle Bigpockets, & Zelli Hotnozzle +DELETE FROM `creature_text` WHERE `entry` IN (34723,34715,34721,34766,34765); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(34723,0,0,'Dat cloud look like da Warchief.',12,1,100,25,0,0,'Watcher Tolwe - Random'), +(34723,0,1,'Dere be a bug.',12,1,100,25,0,0,'Watcher Tolwe - Random'), +(34723,0,2,'Ware da ship! A harpy! ...wait, dat be another bird.',12,1,100,25,0,0,'Watcher Tolwe - Random'), +(34723,0,3,'Dere be a bird!',12,1,100,25,0,0,'Watcher Tolwe - Random'), +(34715,0,0,'And there''s Orgrimmar, huge and menacing like always. Take a quick break, boys, then it''s back to the Bluff!',12,1,100,1,0,0,'Sky-Captain Blastnut - Dock at Orgrimmar'), -- wait 3 sec do emote 5 +(34715,1,0,'Next stop, Thunder Bluff',12,1,100,5,0,0,'Sky-Captain Blastnut - Leave for Thunder Bluff'), +(34715,2,0,'Watch your step! Don''t want you becoming a smudge down there. Welcome to Thunder Bluff!',12,1,100,1,0,0,'Sky-Captain Blastnut - Dock at Thunder Bluff'), -- wait 3 sec do emote 5 +(34715,3,0,'Okay, boys, let''s get this baby over to Orgrimmar!',12,1,100,25,0,0,'Sky-Captain Blastnut - Leave for Orgrimmar'), +(34721,0,0,'Move it, Zippik! We don''t have all day!',12,1,100,5,0,0,'Chief Officer Ograh - Leave for Thunder Bluff'), +(34721,1,0,'Careful. CAREFUL! Did I feel a shudder? You''re going to knock that tower down, oaf!',12,1,100,5,0,0,'Chief Officer Ograh - Dock at Orgrimmar & Thunder Bluff'), +(34721,2,0,'We''re behind schedule! Turn this tub east! EAST!',12,1,100,5,0,0,'Chief Officer Ograh - Leave for Orgrimmar'), +(34766,0,0,'Step right up! The zeppelin to Orgrimmar has arrived! All aboard to Durotar!',14,0,100,22,0,11804,'Krendle Bigpockets - Dock at Thunder Bluff'), +(34765,0,0,'The zeppelin to Thunder Bluff has arrived! All aboard for a smooth ride across the Barrens!',14,0,100,22,0,11804,'Zelli Hotnozzle - Dock at Orgrimmar'); diff --git a/sql/updates/world/2012_06_13_00_world_creature.sql b/sql/updates/world/2012_06_13_00_world_creature.sql new file mode 100644 index 00000000000..0d2aa74c9c7 --- /dev/null +++ b/sql/updates/world/2012_06_13_00_world_creature.sql @@ -0,0 +1,71 @@ +-- Pathing for Violetta (32720) +SET @NPC := 32720; +SET @GUID := 12402; +DELETE FROM `creature` WHERE `guid`=@GUID; +DELETE FROM `creature` WHERE `id`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`) +VALUES (@GUID,@NPC,571,1,1,0,0,5693.527,680.9248,645.9013,4.681826,300,0,0,1,0,0,0,0,0); +DELETE FROM `creature_template_addon` WHERE `entry`=@NPC; +INSERT INTO `creature_template_addon` (`entry`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(@NPC,0,0,0,1,0,''); +-- SAI +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@NPC; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@NPC AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC*100+0,@NPC*100+1,@NPC*100+2,@NPC*100+3) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@NPC,0,0,1,25,0,100,0,0,0,0,0,71,1670,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On reset - Equip default"), +(@NPC,0,1,0,61,0,100,0,0,0,0,0,88,@NPC*100+0,@NPC*100+1,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On reset - Run random script"), +(@NPC,0,2,0,40,1,100,0,8,0,0,0,80,@NPC*100+2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On wp8 - Run script"), +(@NPC,0,3,0,40,2,100,0,8,0,0,0,80,@NPC*100+3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On wp8 - Run script"), +(@NPC,0,4,0,58,0,100,0,0,0,0,0,41,10000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On wp end - Despawn"), +(@NPC*100+0,9,0,0,0,0,100,0,0,0,0,0,53,0,@NPC*10+0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script 1 - Start waypoint 1"), +(@NPC*100+0,9,1,0,0,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script 1 - Set phase 1"), +(@NPC*100+1,9,0,0,0,0,100,0,0,0,0,0,53,0,@NPC*10+1,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script 2 - Start waypoint 2"), +(@NPC*100+1,9,1,0,0,0,100,0,0,0,0,0,22,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script 2 - Set phase 2"), +(@NPC*100+2,9,0,0,0,0,100,0,0,0,0,0,54,10000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script - Pause WP 10 seconds"), +(@NPC*100+2,9,1,0,0,0,100,0,5000,5000,5000,5000,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script - Emote talk"), +(@NPC*100+2,9,2,0,0,0,100,0,3000,3000,3000,3000,71,0,0,44655,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script - Equip item"), +(@NPC*100+3,9,0,0,0,0,100,0,0,0,0,0,54,10000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script - Pause WP 10 seconds"), +(@NPC*100+3,9,1,0,0,0,100,0,5000,5000,5000,5000,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script - Emote talk"), +(@NPC*100+3,9,2,0,0,0,100,0,3000,3000,3000,3000,71,0,0,40020,0,0,0,1,0,0,0,0,0,0,0,"Violetta - On script - Equip item"); +-- Waypoints +DELETE FROM `waypoints` WHERE `entry` IN (@NPC*10+0,@NPC*10+1); +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(@NPC*10+0,1,5693.35,675.1416,645.6994,'Violetta wp1'), +(@NPC*10+0,2,5690.851,664.07,646.2488,'Violetta wp1'), +(@NPC*10+0,3,5686.851,656.5425,646.5913,'Violetta wp1'), +(@NPC*10+0,4,5679.384,648.7989,646.6834,'Violetta wp1'), +(@NPC*10+0,5,5675.498,647.6321,647.0242,'Violetta wp1'), +(@NPC*10+0,6,5669.809,645.4785,647.9725,'Violetta wp1'), +(@NPC*10+0,7,5664.492,643.8845,647.98,'Violetta wp1'), +(@NPC*10+0,8,5664.87,642.0466,647.98,'Violetta wp1'), +(@NPC*10+0,9,5669.127,645.5728,647.9717,'Violetta wp1'), +(@NPC*10+0,10,5675.875,647.3784,647.0391,'Violetta wp1'), +(@NPC*10+0,11,5681.011,648.9694,646.6834,'Violetta wp1'), +(@NPC*10+0,12,5683.774,658.9824,646.6004,'Violetta wp1'), +(@NPC*10+0,13,5682.824,671.3663,647.0424,'Violetta wp1'), +(@NPC*10+0,14,5677.113,674.4891,649.4763,'Violetta wp1'), +(@NPC*10+0,15,5667.89,677.9095,652.0448,'Violetta wp1'), +(@NPC*10+0,16,5655.117,684.3335,651.9886,'Violetta wp1'), +(@NPC*10+0,17,5649.896,690.4983,651.9928,'Violetta wp1'), +(@NPC*10+0,18,5646.092,697.507,651.9928,'Violetta wp1'), +(@NPC*10+0,19,5646.725,700.2504,651.9928,'Violetta wp1'), +(@NPC*10+1,1,5693.35,675.1416,645.6994,'Violetta wp2'), +(@NPC*10+1,2,5690.851,664.07,646.2488,'Violetta wp2'), +(@NPC*10+1,3,5686.851,656.5425,646.5913,'Violetta wp2'), +(@NPC*10+1,4,5679.384,648.7989,646.6834,'Violetta wp2'), +(@NPC*10+1,5,5675.498,647.6321,647.0242,'Violetta wp2'), +(@NPC*10+1,6,5669.809,645.4785,647.9725,'Violetta wp2'), +(@NPC*10+1,7,5664.369,644.7076,647.9811,'Violetta wp2'), +(@NPC*10+1,8,5661.005,643.9919,647.9821,'Violetta wp2'), +(@NPC*10+1,9,5669.143,645.5861,647.9418,'Violetta wp2'), +(@NPC*10+1,10,5675.875,647.3784,647.0391,'Violetta wp2'), +(@NPC*10+1,11,5681.011,648.9694,646.6834,'Violetta wp2'), +(@NPC*10+1,12,5683.774,658.9824,646.6004,'Violetta wp2'), +(@NPC*10+1,13,5682.824,671.3663,647.0424,'Violetta wp2'), +(@NPC*10+1,14,5677.113,674.4891,649.4763,'Violetta wp2'), +(@NPC*10+1,15,5667.89,677.9095,652.0448,'Violetta wp2'), +(@NPC*10+1,16,5655.117,684.3335,651.9886,'Violetta wp2'), +(@NPC*10+1,17,5649.896,690.4983,651.9928,'Violetta wp2'), +(@NPC*10+1,18,5646.092,697.507,651.9928,'Violetta wp2'), +(@NPC*10+1,19,5646.725,700.2504,651.9928,'Violetta wp2'); diff --git a/sql/updates/world/2012_06_13_01_world_creature.sql b/sql/updates/world/2012_06_13_01_world_creature.sql new file mode 100644 index 00000000000..5ba3e0d34a2 --- /dev/null +++ b/sql/updates/world/2012_06_13_01_world_creature.sql @@ -0,0 +1,11 @@ +DELETE FROM `creature_template_addon` WHERE `entry` = 29975; +INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(29975, 0, 0x10000, 0x1, 54503); -- Lok'lira the Crone - Quest Invisibility 2 + +DELETE FROM `creature` WHERE `id` = 29975 OR `guid` = 2593; +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `MovementType`) VALUES +(2593, 29975, 571, 1, 1, 6922.175, -1534.575, 836.1568, 4.276057, 120, 0, 0); -- Lok'lira the Crone (Area: Brunnhildar Village) + +DELETE FROM `spell_area` WHERE `spell` = 54504; +INSERT INTO `spell_area` (`spell`,`area`,`quest_start`,`quest_start_active`,`quest_end`,`aura_spell`,`racemask`,`gender`,`autocast`) VALUES +(54504,4422,12921,1,0,0,0,2,1); -- cast see quest invisibility 2 after accepting the quest from lok'lira. diff --git a/sql/updates/world/2012_06_13_02_world_gossip.sql b/sql/updates/world/2012_06_13_02_world_gossip.sql new file mode 100644 index 00000000000..2cac9fe2a0a --- /dev/null +++ b/sql/updates/world/2012_06_13_02_world_gossip.sql @@ -0,0 +1,32 @@ +-- Missing gossip for Krendle Bigpockets <Durotar Zeppelin Master> in Thunder Bluff +UPDATE `creature_template` SET `gossip_menu_id`=10566 WHERE `entry`=34766; +DELETE FROM `gossip_menu` WHERE `entry`=10566 AND `text_id`=14622; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES (10566,14622); +-- Missing gossip +DELETE FROM `gossip_menu_option` WHERE `menu_id`=7368 AND `id` IN (3,4); +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`)VALUES +(7368,3,0,'Acteon, where is the best area to hunt for moongraze stags?',1,1,7423,0,0,0,''), +(7368,4,0,'Acteon, where is the best place to hunt moongraze bucks?',1,1,7424,0,0,0,''); +-- conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=7368 AND `SourceEntry` IN (3,4); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,7368,3,0,0,9,9454,0,0,0,0,'','Acteon - Show gossip option if player has quest 9454'), +(15,7368,4,0,0,9,10324,0,0,0,0,'','Acteon - Show gossip option if player has quest 10324'); +-- Gossip Condition for Archmage Celindra <Portal Trainer> +SET @GOSSIP := 9777; +SET @TEXTNO := 13455; +SET @TEXTYES := 13456; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=@GOSSIP; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,@GOSSIP,@TEXTNO,0,15,1407,0,0,0,'','Show gossip text if player is not a mage'), +(14,@GOSSIP,@TEXTYES,0,15,128,0,0,0,'','Show gossip text if player is a mage'); +-- Update NPC 4217 Mathrengyl Bearwalker +DELETE FROM `gossip_menu_option` WHERE `menu_id`=1403 AND `id`=3; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`)VALUES +(1403,3,1,'I''d like to purchase more Tharlendris seeds.',3,128,0,0,0,0,''); +-- conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=1403 AND `SourceEntry`=3; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,1403,3,0,0,8,3781,0,0,0,0,'','Mathrengyl Bearwalker - Show gossip option if player has rewarded quest 3781'); -- available only for druids + -- Quest 3792 should only be available after quest 3791 +UPDATE `quest_template` SET `PrevQuestId`=3791 WHERE `id`=3792; diff --git a/sql/updates/world/2012_06_13_03_world_sai.sql b/sql/updates/world/2012_06_13_03_world_sai.sql new file mode 100644 index 00000000000..ad9642447c0 --- /dev/null +++ b/sql/updates/world/2012_06_13_03_world_sai.sql @@ -0,0 +1,70 @@ +-- Grand Anchorite Almonen SAI +SET @ENTRY := 19216; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,1,0,100,0,10000,10000,300000,300000,80,@ENTRY*100 ,0,0,0,0,0,1,0,0,0,0,0,0,0,'Sky-Captain Cloudkicker - OOC - Run Script'), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.654867,'Grand Anchorite Almonen - Script - Turn to'), +(@ENTRY*100,9,1,0,0,0,100,0,9000,9000,0,0,5,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - emote'), +(@ENTRY*100,9,2,0,0,0,100,0,23000,23000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1854.72,5423.082,-10.45947,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,3,0,0,0,100,0,800,800,0,0,69,0,0,0,0,0,0,8,0,0,0,-1854.598,5411.999,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,4,0,0,0,100,0,5000,5000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.183628,'Grand Anchorite Almonen - Script - Turn to'), +(@ENTRY*100,9,5,0,0,0,100,0,100,100,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 0'), +(@ENTRY*100,9,6,0,0,0,100,0,9000,9000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 1'), +(@ENTRY*100,9,7,0,0,0,100,0,9000,9000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 2'), +(@ENTRY*100,9,8,0,0,0,100,0,25000,25000,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 3'), +(@ENTRY*100,9,9,0,0,0,100,0,10000,10000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1851.699,5413.06,-12.42816,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,10,0,0,0,100,0,100,100,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 4'), +(@ENTRY*100,9,11,0,0,0,100,0,1000,1000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1848.775,5412.81,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,12,0,0,0,100,0,2000,2000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.276057,'Grand Anchorite Almonen - Script - Turn to'), +(@ENTRY*100,9,13,0,0,0,100,0,4000,4000,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 5'), +(@ENTRY*100,9,14,0,0,0,100,0,7000,7000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1851.574,5412.084,-12.42816,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,15,0,0,0,100,0,1900,1900,0,0,69,0,0,0,0,0,0,8,0,0,0,-1856.307,5410.266,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,16,0,0,0,100,0,1900,1900,0,0,69,0,0,0,0,0,0,8,0,0,0,-1859.002,5406.959,-12.42814,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,17,0,0,0,100,0,3000,3000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.707227,'Grand Anchorite Almonen - Script - Turn to'), +(@ENTRY*100,9,18,0,0,0,100,0,100,100,0,0,1,6,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 6'), +(@ENTRY*100,9,19,0,0,0,100,0,10000,10000,0,0,1,7,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 7'), +(@ENTRY*100,9,20,0,0,0,100,0,9000,9000,0,0,1,8,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 8'), +(@ENTRY*100,9,21,0,0,0,100,0,5000,5000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1855.089,5410.676,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,22,0,0,0,100,0,1000,1000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1853.62,5409.833,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,23,0,0,0,100,0,3000,3000,0,0,1,9,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 9'), +(@ENTRY*100,9,24,0,0,0,100,0,11000,11000,0,0,1,10,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 10'), +(@ENTRY*100,9,25,0,0,0,100,0,9000,9000,0,0,1,11,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 11'), +(@ENTRY*100,9,26,0,0,0,100,0,100,100,0,0,69,0,0,0,0,0,0,8,0,0,0,-1852.503,5412.286,-12.42816,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,27,0,0,0,100,0,1000,1000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1849.053,5415.075,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,28,0,0,0,100,0,2000,2000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,5.340707,'Grand Anchorite Almonen - Script - Turn to'), +(@ENTRY*100,9,29,0,0,0,100,0,5000,5000,0,0,1,12,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 12'), +(@ENTRY*100,9,30,0,0,0,100,0,11000,11000,0,0,1,13,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 13'), +(@ENTRY*100,9,31,0,0,0,100,0,4000,4000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1851.643,5414.012,-12.42816,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,32,0,0,0,100,0,1200,1200,0,0,69,0,0,0,0,0,0,8,0,0,0,-1854.913,5412.682,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,33,0,0,0,100,0,800,800,0,0,69,0,0,0,0,0,0,8,0,0,0,-1854.408,5411.227,-12.42815,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,34,0,0,0,100,0,1000,1000,0,0,1,14,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 14'), +(@ENTRY*100,9,35,0,0,0,100,0,10000,10000,0,0,1,15,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 15'), +(@ENTRY*100,9,36,0,0,0,100,0,7000,7000,0,0,1,16,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 16'), +(@ENTRY*100,9,37,0,0,0,100,0,10000,10000,0,0,1,17,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 17'), +(@ENTRY*100,9,38,0,0,0,100,0,11000,11000,0,0,1,18,0,0,0,0,0,1,0,0,0,0,0,0,0,'Grand Anchorite Almonen - Script - say 18'), +(@ENTRY*100,9,39,0,0,0,100,0,10000,10000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1853.137,5424.863,-10.47787,0,'Grand Anchorite Almonen - Script - move to'), +(@ENTRY*100,9,40,0,0,0,100,0,6500,6500,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,2.6529,'Grand Anchorite Almonen - Script - Turn to'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=19216; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(19216,0,0, 'Friends, it is my great pleasure to welcome you to the temple today.',12,0,100,1,0,0, 'Grand Anchorite Almonen'), +(19216,1,0, 'A''dal has been most generous in his revelations to me, a humble servant of the Light.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,2,0, 'In accordance with my divine calling, I must share these revealed truths to all who would hear.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,3,0, 'It has been made known to me that inside each of us, the Light resides...',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,4,0, '...that it is a gift, given freely to all naturally born beings.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,5,0, 'It manifests itself as a feeling, small at first and easily ignored, that confirms truths and subtly prods one to do good.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,6,0, 'Simple kindnesses, charitable deeds, service to those in need. These are all fruits of the Light.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,7,0, 'It rewards those who heed its promptings with blessings, both seen and unseen.',12,0,100,1,0,0, 'Grand Anchorite Almonen'), +(19216,8,0, 'Personal reservoirs of hope and faith are strengthened, and one''s capacity for greater light increases.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,9,0, 'Over the course of time, through obedience to the Light''s guidance, one becomes more sensitive to its voice, and its power.',12,0,100,273,0,0, 'Grand Anchorite Almonen'), +(19216,10,0, 'Great is the healing and blessing power of the Light''s most diligent followers.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,11,0, 'Sadly, there are those who wander through mortality in defiance of the Light.',12,0,100,1,0,0, 'Grand Anchorite Almonen'), +(19216,12,0, 'From these the Light withdraws, until only darkness remains.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,13,0, 'Where there is no light, despair, loathing and rage thrive.',12,0,100,5,0,0, 'Grand Anchorite Almonen'), +(19216,14,0, 'We are born into a perilous age, where the forces of darkness are determined to bring about our destruction.',12,0,100,1,0,0, 'Grand Anchorite Almonen'), +(19216,15,0, 'These are the times to find yourselves in unison with the Light.',12,0,100,5,0,0, 'Grand Anchorite Almonen'), +(19216,16,0, 'Hear my words, and let the Light inside of you confirm the truth of them.',12,0,100,0,0,0, 'Grand Anchorite Almonen'), +(19216,17,0, 'Embrace the light that is in you, my friends! Deny yourself all darkness...',12,0,100,5,0,0, 'Grand Anchorite Almonen'), +(19216,18,0, 'We must endure these trying times faithfully, and one day we will find ourselves victorious.',12,0,100,5,0,0, 'Grand Anchorite Almonen'); diff --git a/sql/updates/world/2012_06_14_00_world_spell_linked_spell.sql b/sql/updates/world/2012_06_14_00_world_spell_linked_spell.sql new file mode 100644 index 00000000000..85cae64c21d --- /dev/null +++ b/sql/updates/world/2012_06_14_00_world_spell_linked_spell.sql @@ -0,0 +1,5 @@ +-- Fix Surge of Adrenaline +DELETE FROM `spell_linked_spell` WHERE `spell_effect`=68667; +INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES +(-66683,68667,0, 'Icehowl - Surge of Adrenaline'), +(-67660,68667,0, 'Icehowl - Surge of Adrenaline'); diff --git a/sql/updates/world/2012_06_14_01_world_spell_linked_spell.sql b/sql/updates/world/2012_06_14_01_world_spell_linked_spell.sql new file mode 100644 index 00000000000..6109c8db068 --- /dev/null +++ b/sql/updates/world/2012_06_14_01_world_spell_linked_spell.sql @@ -0,0 +1,51 @@ +-- delete 'Mangle - Remover' +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33876 AND `spell_effect`=-48564 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33876 AND `spell_effect`=-48563 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33876 AND `spell_effect`=-33987 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33876 AND `spell_effect`=-33986 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33876 AND `spell_effect`=-33878 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33878 AND `spell_effect`=-48566 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33878 AND `spell_effect`=-48565 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33878 AND `spell_effect`=-33983 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33878 AND `spell_effect`=-33982 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33878 AND `spell_effect`=-33876 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33982 AND `spell_effect`=-48564 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33982 AND `spell_effect`=-48563 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33982 AND `spell_effect`=-33987 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33982 AND `spell_effect`=-33986 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33982 AND `spell_effect`=-33878 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33983 AND `spell_effect`=-48564 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33983 AND `spell_effect`=-48563 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33983 AND `spell_effect`=-33987 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33983 AND `spell_effect`=-33986 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33983 AND `spell_effect`=-33878 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33986 AND `spell_effect`=-48566 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33986 AND `spell_effect`=-48565 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33986 AND `spell_effect`=-33983 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33986 AND `spell_effect`=-33982 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33986 AND `spell_effect`=-33876 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33987 AND `spell_effect`=-48566 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33987 AND `spell_effect`=-48565 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33987 AND `spell_effect`=-33983 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33987 AND `spell_effect`=-33982 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=33987 AND `spell_effect`=-33876 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48563 AND `spell_effect`=-48566 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48563 AND `spell_effect`=-48565 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48563 AND `spell_effect`=-33983 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48563 AND `spell_effect`=-33982 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48563 AND `spell_effect`=-33876 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48564 AND `spell_effect`=-48566 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48564 AND `spell_effect`=-48565 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48564 AND `spell_effect`=-33983 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48564 AND `spell_effect`=-33982 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48564 AND `spell_effect`=-33876 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48565 AND `spell_effect`=-48564 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48565 AND `spell_effect`=-48563 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48565 AND `spell_effect`=-33987 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48565 AND `spell_effect`=-33986 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48565 AND `spell_effect`=-33878 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48566 AND `spell_effect`=-48564 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48566 AND `spell_effect`=-48563 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48566 AND `spell_effect`=-33987 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48566 AND `spell_effect`=-33986 AND `type`=1; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=48566 AND `spell_effect`=-33878 AND `type`=1; diff --git a/sql/updates/world/2012_06_14_02_world_spell_bonus_data.sql b/sql/updates/world/2012_06_14_02_world_spell_bonus_data.sql new file mode 100644 index 00000000000..b7f61f407b4 --- /dev/null +++ b/sql/updates/world/2012_06_14_02_world_spell_bonus_data.sql @@ -0,0 +1,102 @@ +-- Death Knight +DELETE FROM `spell_bonus_data` WHERE `entry` IN(58621, 47632, 47633, 50444, 70890, 50526, 48982, 59754, 49184); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(58621, 0, -1, 0.08, -1, 'Death Knight - Glyph of Chains of Ice'), -- Shouldn't scale with SP. +(47632, 0, -1, 0.15, -1, 'Death Knight - Death Coil'), -- Shouldn't scale with SP. +(47633, 0, -1, 0.15, -1, 'Death Knight - Death Coil (Heal)'), -- Shouldn't scale with SP. +(50444, 0, -1, 0.105, -1, 'Death Knight - Corpse Explosion (Triggered)'), -- Shouldn't scale with SP. +(70890, 0, -1, -1, -1, 'Death Knight - Scourge Strike (Shadow)'), -- Shouldn't scale with SP. +(50526, 0, -1, -1, -1, 'Death Knight - Wandering Plague (Triggered)'), -- Shouldn't scale with SP. +(48982, 0, -1, -1, -1, 'Death Knight - Rune Tap'), -- Shouldn't scale with SP. +(59754, 0, -1, -1, -1, 'Death Knight - Glyph of Rune Tap (Triggered)'), -- Shouldn't scale with SP. +(49184, 0, -1, 0.2, -1, 'Death Knight - Howling Blast'); -- Shouldn't scale with SP. + +-- Druid +DELETE FROM `spell_bonus_data` WHERE `entry` IN(48450, 48451); -- Lifebloom Rank 2, Rank 3 +DELETE FROM `spell_bonus_data` WHERE `entry` IN(48567, 48568); -- Lacerate Rank 2, Rank 3 +DELETE FROM `spell_bonus_data` WHERE `entry` IN(33745, 9007); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(33745, 0, 0, 0.01, 0.01, 'Druid - Lacerate ($AP*0.05/number of ticks)'), -- Direct damage should scale with AP, based on DrDamage addon(3.3.5a). +(9007, -1, 0, -1, 0.03, 'Druid - Pounce Bleed (Triggered)'); -- Shouldn't scale with SP. Increase AP coefficient, based on DrDamage addon(3.3.5a) and Wowwiki.com. + +-- Hunter +DELETE FROM `spell_bonus_data` WHERE `entry` IN(56641, 42243, 3674, 19306, 1495, 63468, 136); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(56641, 0, -1, 0.1, -1, 'Hunter - Steady Shot'), -- Shouldn't scale with SP. +(42243, 0, -1, 0.0837, -1, 'Hunter - Volley (Triggered)'), -- Shouldn't scale with SP. +(3674, -1, 0, -1, 0.023, 'Hunter - Black Arrow ($RAP*0.1 / number of ticks)'), -- Shouldn't scale with SP. Increase AP coefficient, based on DrDamage addon(3.3.5a). +(19306, 0, -1, 0.2, -1, 'Hunter - Counterattack'), -- Shouldn't scale with SP. +(1495, 0, -1, 0.2, -1, 'Hunter - Mongoose Bite'), -- Shouldn't scale with SP. +(63468, -1, 0, -1, -1, 'Hunter - Piercing Shots'), -- Shouldn't scale with SP. +(136, -1, 0, -1, -1, 'Hunter - Mend Pet'); -- Shouldn't scale with SP. + +-- Mage +DELETE FROM `spell_bonus_data` WHERE `entry`=7269; -- Arcane Missiles Triggered Spell Rank 2 +DELETE FROM `spell_bonus_data` WHERE `entry` IN(133, 44614, 44457, 44461); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(133, 1, 0, -1, -1, 'Mage - Fireball'), -- DoT componenet shouldn't scale. +(44614, 0.8571, 0, -1, -1, 'Mage - Frostfire Bolt'), -- DoT componenet shouldn't scale. +(44457, -1, 0.2, -1, -1, 'Mage - Living Bomb ($SP*0.8 / number of ticks)'), -- Direct damage bonus correction. +(44461, 0.4286, -1, -1, -1, 'Mage - Living Bomb (Triggered)'); -- Direct damage bonus correction. + +-- Paladin +DELETE FROM `spell_bonus_data` WHERE `entry` IN(633, 54158, 20467, 20187, 31803, 53742, 31804, 53733); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(633, 0, -1, -1, -1, 'Paladin - Lay on Hands'), -- Shouldn't scale with SP. +(54158, 0.27, -1, 0.175, -1, 'Paladin - Judgement (Seal of Light, Seal of Wisdom, Seal of Justice)'), -- Increase coefficient, based on Wowwiki.com. +(20467, 0.14, -1, 0.115, -1, 'Paladin - Judgement of Command'), -- Decrease coefficient, based on Wowwiki.com. +(20187, 0.355, -1, 0.225, -1, 'Paladin - Judgement of Righteousness'), -- Increase coefficient, based on Wowwiki.com. +(31803, -1, 0.0132, -1, 0.0252, 'Paladin - Holy Vengeance'), -- Decrease coefficient, based on DrDamage addon(3.3.5a) and Wowwiki.com. +(53742, -1, 0.0132, -1, 0.0252, 'Paladin - Blood Corruption'), -- Decrease coefficient, based on DrDamage addon(3.3.5a) and Wowwiki.com. +(31804, 0.24, -1, 0.15, -1, 'Paladin - Judgement of Vengeance'), -- Increase coefficient, based on Wowwiki.com. +(53733, 0.24, -1, 0.15, -1, 'Paladin - Judgement of Corruption'); -- Increase coefficient, based on Wowwiki.com. + +-- Priest +DELETE FROM `spell_bonus_data` WHERE `entry` IN(52983, 52954, 58985); -- Penance Heal Rank 2, Rank 3, Rank 4 +DELETE FROM `spell_bonus_data` WHERE `entry` IN(52998, 52999, 53000); -- Penance Hurt Rank 2, Rank 3, Rank 4 +DELETE FROM `spell_bonus_data` WHERE `entry` IN(7001); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(7001, -1, 0.626, -1, -1, 'Priest - Lightwell Renew ($SP*1.878 / number of ticks)'); -- Increase coefficient, based on DrDamage addon(3.3.5a). + +-- Rogue +DELETE FROM `spell_bonus_data` WHERE `entry` IN(819, 11353, 11354, 25349, 26968, 27187, 57969, 57970); -- Deadly Poison Rank 2, Rank 3, etc. +DELETE FROM `spell_bonus_data` WHERE `entry` IN(8685, 8689, 11335, 11336, 11337, 26890, 57964, 57965); -- Instant Poison Rank 2, Rank 3, etc. +DELETE FROM `spell_bonus_data` WHERE `entry` IN(13222, 13223, 13224, 27189, 57974, 57975); -- Wound Poison Rank 2, Rank 3, etc. +DELETE FROM `spell_bonus_data` WHERE `entry` IN(32645, 2098, 703, 1776, 1943, 8680, 26688, 13218); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(32645, 0, -1, -1, -1, 'Rogue - Envenom'), -- Shouldn't scale with SP. +(2098, 0, -1, -1, -1, 'Rogue - Eviscerate'), -- Shouldn't scale with SP. +(703, -1, 0, -1, 0.07, 'Rogue - Garrote'), -- Shouldn't scale with SP. +(1776, 0, -1, 0.21, -1, 'Rogue - Gouge'), -- Shouldn't scale with SP. +(1943, -1, 0, -1, -1, 'Rogue - Rupture'), -- Shouldn't scale with SP. +(8680, 0, -1, 0.1, -1, 'Rogue - Instant Poison'), -- Shouldn't scale with SP. +(26688, 0, -1, 0, -1, 'Rogue - Anesthetic Poison'), -- Shouldn't scale with SP nor AP. +(13218, 0, -1, 0.04, -1, 'Rogue - Wound Poison'); -- Shouldn't scale with SP. + + -- Warlock Healthstones Shouldn't scale with SP. +DELETE FROM `spell_bonus_data` WHERE `entry` IN (6262, 23468, 23469, 6263, 23470, 23471, 5720, 23472, 23473, 5723, 23474, 23475, 11732, 23476, 23477, 27235, 27236, 27237, 47874, 47873, 47872, 47875, 47876, 47877); +INSERT INTO `spell_bonus_data` (`entry`,`direct_bonus`,`dot_bonus`,`ap_bonus`,`ap_dot_bonus`,`comments`) VALUES +(6262, 0, -1, 0, -1, 'Warlock - HS - Minor Healthstone (with 0/2 Improved Healthstone)'), +(23468, 0, -1, 0, -1, 'Warlock - HS - Minor Healthstone (with 1/2 Improved Healthstone)'), +(23469, 0, -1, 0, -1, 'Warlock - HS - Minor Healthstone (with 2/2 Improved Healthstone)'), +(6263, 0, -1, 0, -1, 'Warlock - HS - Lesser Healthstone (with 0/2 Improved Healthstone)'), +(23470, 0, -1, 0, -1, 'Warlock - HS - Lesser Healthstone (with 1/2 Improved Healthstone)'), +(23471, 0, -1, 0, -1, 'Warlock - HS - Lesser Healthstone (with 2/2 Improved Healthstone)'), +(5720, 0, -1, 0, -1, 'Warlock - HS - Healthstone (with 0/2 Improved Healthstone)'), +(23472, 0, -1, 0, -1, 'Warlock - HS - Healthstone (with 1/2 Improved Healthstone)'), +(23473, 0, -1, 0, -1, 'Warlock - HS - Healthstone (with 2/2 Improved Healthstone)'), +(5723, 0, -1, 0, -1, 'Warlock - HS - Greater Healthstone (with 0/2 Improved Healthstone)'), +(23474, 0, -1, 0, -1, 'Warlock - HS - Greater Healthstone (with 1/2 Improved Healthstone)'), +(23475, 0, -1, 0, -1, 'Warlock - HS - Greater Healthstone (with 2/2 Improved Healthstone)'), +(11732, 0, -1, 0, -1, 'Warlock - HS - Major Healthstone (with 0/2 Improved Healthstone)'), +(23476, 0, -1, 0, -1, 'Warlock - HS - Major Healthstone (with 1/2 Improved Healthstone)'), +(23477, 0, -1, 0, -1, 'Warlock - HS - Major Healthstone (with 2/2 Improved Healthstone)'), +(27235, 0, -1, 0, -1, 'Warlock - HS - Master Healthstone (with 0/2 Improved Healthstone)'), +(27236, 0, -1, 0, -1, 'Warlock - HS - Master Healthstone (with 1/2 Improved Healthstone)'), +(27237, 0, -1, 0, -1, 'Warlock - HS - Master Healthstone (with 2/2 Improved Healthstone)'), +(47874, 0, -1, 0, -1, 'Warlock - HS - Demonic Healthstone (with 0/2 Improved Healthstone)'), +(47873, 0, -1, 0, -1, 'Warlock - HS - Demonic Healthstone (with 1/2 Improved Healthstone)'), +(47872, 0, -1, 0, -1, 'Warlock - HS - Demonic Healthstone (with 2/2 Improved Healthstone)'), +(47875, 0, -1, 0, -1, 'Warlock - HS - Fel Healthstone (with 0/2 Improved Healthstone)'), +(47876, 0, -1, 0, -1, 'Warlock - HS - Fel Healthstone (with 1/2 Improved Healthstone)'), +(47877, 0, -1, 0, -1, 'Warlock - HS - Fel Healthstone (with 2/2 Improved Healthstone)'); diff --git a/sql/updates/world/2012_06_14_03_world_spell_bonus_data.sql b/sql/updates/world/2012_06_14_03_world_spell_bonus_data.sql new file mode 100644 index 00000000000..dc59f152e33 --- /dev/null +++ b/sql/updates/world/2012_06_14_03_world_spell_bonus_data.sql @@ -0,0 +1,94 @@ +-- Death Knight +DELETE FROM `spell_bonus_data` WHERE `entry` IN (58621, 47632, 47633, 50444, 70890, 50526, 48982, 59754, 49184); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(58621, 0, 0, 0.08, 0, 'Death Knight - Glyph of Chains of Ice'), -- Shouldn't scale with SP. +(47632, 0, 0, 0.15, 0, 'Death Knight - Death Coil'), -- Shouldn't scale with SP. +(47633, 0, 0, 0.15, 0, 'Death Knight - Death Coil (Heal)'), -- Shouldn't scale with SP. +(50444, 0, 0, 0.105, 0, 'Death Knight - Corpse Explosion (Triggered)'), -- Shouldn't scale with SP. +(70890, 0, 0, 0, 0, 'Death Knight - Scourge Strike (Shadow)'), -- Shouldn't scale with SP. +(50526, 0, 0, 0, 0, 'Death Knight - Wandering Plague (Triggered)'), -- Shouldn't scale with SP. +(48982, 0, 0, 0, 0, 'Death Knight - Rune Tap'), -- Shouldn't scale with SP. +(59754, 0, 0, 0, 0, 'Death Knight - Glyph of Rune Tap (Triggered)'), -- Shouldn't scale with SP. +(49184, 0, 0, 0.2, 0, 'Death Knight - Howling Blast'); -- Shouldn't scale with SP. + +-- Druid +DELETE FROM `spell_bonus_data` WHERE `entry` IN (33745, 9007); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(33745, 0, 0, 0.01, 0.01, 'Druid - Lacerate ($AP*0.05/number of ticks)'), -- Direct damage should scale with AP, based on DrDamage addon(3.3.5a). +(9007, 0, 0, 0, 0.03, 'Druid - Pounce Bleed (Triggered)'); -- Shouldn't scale with SP. Increase AP coefficient, based on DrDamage addon(3.3.5a) and Wowwiki.com. + +-- Hunter +DELETE FROM `spell_bonus_data` WHERE `entry` IN (56641, 42243, 3674, 19306, 1495, 63468, 136); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(56641, 0, 0, 0.1, 0, 'Hunter - Steady Shot'), -- Shouldn't scale with SP. +(42243, 0, 0, 0.0837, 0, 'Hunter - Volley (Triggered)'), -- Shouldn't scale with SP. +(3674, 0, 0, 0, 0.023, 'Hunter - Black Arrow ($RAP*0.1 / number of ticks)'), -- Shouldn't scale with SP. Increase AP coefficient, based on DrDamage addon(3.3.5a). +(19306, 0, 0, 0.2, 0, 'Hunter - Counterattack'), -- Shouldn't scale with SP. +(1495, 0, 0, 0.2, 0, 'Hunter - Mongoose Bite'), -- Shouldn't scale with SP. +(63468, 0, 0, 0, 0, 'Hunter - Piercing Shots'), -- Shouldn't scale with SP. +(136, 0, 0, 0, 0, 'Hunter - Mend Pet'); -- Shouldn't scale with SP. + +-- Mage +DELETE FROM `spell_bonus_data` WHERE `entry` IN (133, 44614, 44457, 44461); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(133, 1, 0, 0, 0, 'Mage - Fireball'), -- DoT componenet shouldn't scale. +(44614, 0.8571, 0, 0, 0, 'Mage - Frostfire Bolt'), -- DoT componenet shouldn't scale. +(44457, 0, 0.2, 0, 0, 'Mage - Living Bomb ($SP*0.8 / number of ticks)'), -- Direct damage bonus correction. +(44461, 0.4286, 0, 0, 0, 'Mage - Living Bomb (Triggered)'); -- Direct damage bonus correction. + +-- Paladin +DELETE FROM `spell_bonus_data` WHERE `entry` IN (633, 54158, 20467, 20187, 31803, 53742, 31804, 53733); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(633, 0, 0, 0, 0, 'Paladin - Lay on Hands'), -- Shouldn't scale with SP. +(54158, 0.27, 0, 0.175, 0, 'Paladin - Judgement (Seal of Light, Seal of Wisdom, Seal of Justice)'), -- Increase coefficient, based on Wowwiki.com. +(20467, 0.14, 0, 0.115, 0, 'Paladin - Judgement of Command'), -- Decrease coefficient, based on Wowwiki.com. +(20187, 0.355, 0, 0.225, 0, 'Paladin - Judgement of Righteousness'), -- Increase coefficient, based on Wowwiki.com. +(31803, 0, 0.0132, 0, 0.0252, 'Paladin - Holy Vengeance'), -- Decrease coefficient, based on DrDamage addon(3.3.5a) and Wowwiki.com. +(53742, 0, 0.0132, 0, 0.0252, 'Paladin - Blood Corruption'), -- Decrease coefficient, based on DrDamage addon(3.3.5a) and Wowwiki.com. +(31804, 0.24, 0, 0.15, 0, 'Paladin - Judgement of Vengeance'), -- Increase coefficient, based on Wowwiki.com. +(53733, 0.24, 0, 0.15, 0, 'Paladin - Judgement of Corruption'); -- Increase coefficient, based on Wowwiki.com. + +-- Priest +DELETE FROM `spell_bonus_data` WHERE `entry` = 7001; +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(7001, 0, 0.626, 0, 0, 'Priest - Lightwell Renew ($SP*1.878 / number of ticks)'); -- Increase coefficient, based on DrDamage addon(3.3.5a). + +-- Rogue +DELETE FROM `spell_bonus_data` WHERE `entry` IN (32645, 2098, 703, 1776, 1943, 8680, 26688, 13218); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(32645, 0, 0, 0, 0, 'Rogue - Envenom'), -- Shouldn't scale with SP. +(2098, 0, 0, 0, 0, 'Rogue - Eviscerate'), -- Shouldn't scale with SP. +(703, 0, 0, 0, 0.07, 'Rogue - Garrote'), -- Shouldn't scale with SP. +(1776, 0, 0, 0.21, 0, 'Rogue - Gouge'), -- Shouldn't scale with SP. +(1943, 0, 0, 0, 0, 'Rogue - Rupture'), -- Shouldn't scale with SP. +(8680, 0, 0, 0.1, 0, 'Rogue - Instant Poison'), -- Shouldn't scale with SP. +(26688, 0, 0, 0, 0, 'Rogue - Anesthetic Poison'), -- Shouldn't scale with SP nor AP. +(13218, 0, 0, 0.04, 0, 'Rogue - Wound Poison'); -- Shouldn't scale with SP. + + -- Warlock Healthstones Shouldn't scale with SP. +DELETE FROM `spell_bonus_data` WHERE `entry` IN (6262, 23468, 23469, 6263, 23470, 23471, 5720, 23472, 23473, 5723, 23474, 23475, 11732, 23476, 23477, 27235, 27236, 27237, 47874, 47873, 47872, 47875, 47876, 47877); +INSERT INTO `spell_bonus_data` (`entry`,`direct_bonus`,`dot_bonus`,`ap_bonus`,`ap_dot_bonus`,`comments`) VALUES +(6262, 0, 0, 0, 0, 'Warlock - HS - Minor Healthstone (with 0/2 Improved Healthstone)'), +(23468, 0, 0, 0, 0, 'Warlock - HS - Minor Healthstone (with 1/2 Improved Healthstone)'), +(23469, 0, 0, 0, 0, 'Warlock - HS - Minor Healthstone (with 2/2 Improved Healthstone)'), +(6263, 0, 0, 0, 0, 'Warlock - HS - Lesser Healthstone (with 0/2 Improved Healthstone)'), +(23470, 0, 0, 0, 0, 'Warlock - HS - Lesser Healthstone (with 1/2 Improved Healthstone)'), +(23471, 0, 0, 0, 0, 'Warlock - HS - Lesser Healthstone (with 2/2 Improved Healthstone)'), +(5720, 0, 0, 0, 0, 'Warlock - HS - Healthstone (with 0/2 Improved Healthstone)'), +(23472, 0, 0, 0, 0, 'Warlock - HS - Healthstone (with 1/2 Improved Healthstone)'), +(23473, 0, 0, 0, 0, 'Warlock - HS - Healthstone (with 2/2 Improved Healthstone)'), +(5723, 0, 0, 0, 0, 'Warlock - HS - Greater Healthstone (with 0/2 Improved Healthstone)'), +(23474, 0, 0, 0, 0, 'Warlock - HS - Greater Healthstone (with 1/2 Improved Healthstone)'), +(23475, 0, 0, 0, 0, 'Warlock - HS - Greater Healthstone (with 2/2 Improved Healthstone)'), +(11732, 0, 0, 0, 0, 'Warlock - HS - Major Healthstone (with 0/2 Improved Healthstone)'), +(23476, 0, 0, 0, 0, 'Warlock - HS - Major Healthstone (with 1/2 Improved Healthstone)'), +(23477, 0, 0, 0, 0, 'Warlock - HS - Major Healthstone (with 2/2 Improved Healthstone)'), +(27235, 0, 0, 0, 0, 'Warlock - HS - Master Healthstone (with 0/2 Improved Healthstone)'), +(27236, 0, 0, 0, 0, 'Warlock - HS - Master Healthstone (with 1/2 Improved Healthstone)'), +(27237, 0, 0, 0, 0, 'Warlock - HS - Master Healthstone (with 2/2 Improved Healthstone)'), +(47874, 0, 0, 0, 0, 'Warlock - HS - Demonic Healthstone (with 0/2 Improved Healthstone)'), +(47873, 0, 0, 0, 0, 'Warlock - HS - Demonic Healthstone (with 1/2 Improved Healthstone)'), +(47872, 0, 0, 0, 0, 'Warlock - HS - Demonic Healthstone (with 2/2 Improved Healthstone)'), +(47875, 0, 0, 0, 0, 'Warlock - HS - Fel Healthstone (with 0/2 Improved Healthstone)'), +(47876, 0, 0, 0, 0, 'Warlock - HS - Fel Healthstone (with 1/2 Improved Healthstone)'), +(47877, 0, 0, 0, 0, 'Warlock - HS - Fel Healthstone (with 2/2 Improved Healthstone)'); diff --git a/sql/updates/world/2012_06_14_03_world_spell_ranks.sql b/sql/updates/world/2012_06_14_03_world_spell_ranks.sql new file mode 100644 index 00000000000..f6641f2f095 --- /dev/null +++ b/sql/updates/world/2012_06_14_03_world_spell_ranks.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_ranks` WHERE `first_spell_id`=64694; +INSERT INTO `spell_ranks` (`first_spell_id`,`spell_id`,`rank`) VALUES +(64694,64694,1), +(64694,65263,2), +(64694,65264,3); diff --git a/sql/updates/world/2012_06_14_04_world_spell_script_names.sql b/sql/updates/world/2012_06_14_04_world_spell_script_names.sql new file mode 100644 index 00000000000..00ceb1df9e9 --- /dev/null +++ b/sql/updates/world/2012_06_14_04_world_spell_script_names.sql @@ -0,0 +1,62 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN (-633,781,-746,1515,6495,-8050,-16972,31789,-34914,-44457,-48181,-30108,34438,34439,35183,43522,65812,68154,68155,68156,52610,61336,-33763,40133,40132,43421,52551,53608,57762,59990,66093,67957,67958,67959,7057,28832,28833,28834,28835,27831,55638,31447,32960,33654,33671,50810,61546,50811,61547,52942,59837,63322,47977,48025,54729,71342,72286,74856,75614,75973); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(-633, 'spell_pal_lay_on_hands'), +(781, 'spell_hun_disengage'), +(-746, 'spell_gen_bandage'), +(1515, 'spell_hun_tame_beast'), +(6495, 'spell_sha_sentry_totem'), +(-8050, 'spell_sha_flame_shock'), +(-16972,'spell_dru_predatory_strikes'), +(31789, 'spell_pal_righteous_defense'), +(-34914,'spell_pri_vampiric_touch'), +(-44457,'spell_mage_living_bomb'), +(-48181,'spell_warl_haunt'), +(-30108,'spell_warl_unstable_affliction'), +(34438, 'spell_warl_unstable_affliction'), -- using class spell script for generic spell because it uses class spell effect +(34439, 'spell_warl_unstable_affliction'), +(35183, 'spell_warl_unstable_affliction'), +(43522, 'spell_hexlord_unstable_affliction'), +(65812, 'spell_faction_champion_warl_unstable_affliction'), +(68154, 'spell_faction_champion_warl_unstable_affliction'), +(68155, 'spell_faction_champion_warl_unstable_affliction'), +(68156, 'spell_faction_champion_warl_unstable_affliction'), +(52610, 'spell_dru_savage_roar'), +(61336, 'spell_dru_survival_instincts'), +(-33763,'spell_dru_lifebloom'), +(40133, 'spell_gen_summon_fire_elemental'), +(40132, 'spell_gen_summon_earth_elemental'), +(43421, 'spell_hexlord_lifebloom'), +(52551, 'spell_tur_ragepaw_lifebloom'), +(53608, 'spell_cenarion_scout_lifebloom'), +(57762, 'spell_twisted_visage_lifebloom'), +(59990, 'spell_twisted_visage_lifebloom'), +(66093, 'spell_faction_champion_dru_lifebloom'), +(67957, 'spell_faction_champion_dru_lifebloom'), +(67958, 'spell_faction_champion_dru_lifebloom'), +(67959, 'spell_faction_champion_dru_lifebloom'), +(7057, 'spell_shadowfang_keep_haunting_spirits'), +(28832, 'spell_four_horsemen_mark'), +(28833, 'spell_four_horsemen_mark'), +(28834, 'spell_four_horsemen_mark'), +(28835, 'spell_four_horsemen_mark'), +(27831, 'spell_gothik_shadow_bolt_volley'), +(55638, 'spell_gothik_shadow_bolt_volley'), +(31447, 'spell_mark_of_kazrogal'), +(32960, 'spell_mark_of_kazzak'), +(33654, 'spell_gruul_shatter'), +(33671, 'spell_gruul_shatter_effect'), +(50810, 'spell_krystallus_shatter'), +(61546, 'spell_krystallus_shatter'), +(50811, 'spell_krystallus_shatter_effect'), +(61547, 'spell_krystallus_shatter_effect'), +(52942, 'spell_loken_pulsing_shockwave'), +(59837, 'spell_loken_pulsing_shockwave'), +(63322, 'spell_general_vezax_saronite_vapors'), +(47977, 'spell_magic_broom'), +(48025, 'spell_headless_horseman_mount'), +(54729, 'spell_winged_steed_of_the_ebon_blade'), +(71342, 'spell_big_love_rocket'), +(72286, 'spell_invincible'), +(74856, 'spell_blazing_hippogryph'), +(75614, 'spell_celestial_steed'), +(75973, 'spell_x53_touring_rocket'); diff --git a/sql/updates/world/2012_06_14_05_world_spelldifficulty_dbc.sql b/sql/updates/world/2012_06_14_05_world_spelldifficulty_dbc.sql new file mode 100644 index 00000000000..1f218027f91 --- /dev/null +++ b/sql/updates/world/2012_06_14_05_world_spelldifficulty_dbc.sql @@ -0,0 +1,6 @@ +SET @DIFF := 3268; -- set by TDB team +DELETE FROM `spelldifficulty_dbc` WHERE `id` BETWEEN @DIFF+0 AND @DIFF+2; +INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`,`spellid2`,`spellid3`) VALUES +(@DIFF+0,50811,61547,0,0), +(@DIFF+1,57762,59990,0,0), +(@DIFF+2,57763,61489,0,0); diff --git a/sql/updates/world/2012_06_14_06_world_conditions.sql b/sql/updates/world/2012_06_14_06_world_conditions.sql new file mode 100644 index 00000000000..43d422e9239 --- /dev/null +++ b/sql/updates/world/2012_06_14_06_world_conditions.sql @@ -0,0 +1,7 @@ +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry` IN (19938,30877); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(17,0,19938,0,0,1,1,17743,0,0,0,0,'','Awaken Peon'), +(17,0,30877,0,0,31,1,3,17326,0,0,0,'','Tag Murloc'); + +-- Lifebinder's Gift +UPDATE `conditions` SET `SourceGroup`=7 WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (62584,64185); diff --git a/sql/updates/world/2012_06_14_07_world_spell_bonus_data.sql b/sql/updates/world/2012_06_14_07_world_spell_bonus_data.sql new file mode 100644 index 00000000000..aa9c1b732c4 --- /dev/null +++ b/sql/updates/world/2012_06_14_07_world_spell_bonus_data.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_bonus_data` WHERE `entry`=63544; +INSERT INTO `spell_bonus_data` (`entry`,`direct_bonus`,`dot_bonus`,`ap_bonus`,`ap_dot_bonus`,`comments`) VALUES +(63544,0,0,0,0,'Priest - Empowered Renew'); diff --git a/sql/updates/world/2012_06_14_08_world_spell_script_names.sql b/sql/updates/world/2012_06_14_08_world_spell_script_names.sql new file mode 100644 index 00000000000..a9faa529143 --- /dev/null +++ b/sql/updates/world/2012_06_14_08_world_spell_script_names.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `spell_id`=-139; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(-139,'spell_priest_renew'); diff --git a/sql/updates/world/2012_06_14_09_world_sai.sql b/sql/updates/world/2012_06_14_09_world_sai.sql new file mode 100644 index 00000000000..3beb7c06326 --- /dev/null +++ b/sql/updates/world/2012_06_14_09_world_sai.sql @@ -0,0 +1,45 @@ +-- Fix up quest 9539 "Totem of Coo" +-- Totem of Akida SAI +SET @ENTRY := 17360; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,19,0,100,0,9539,0,0,0,85,30437,0,0,0,0,0,7,0,0,0,0,0,0,0,'Totem of Akida - Quest accepted - Cast Spell on player'); +-- Stillpine Ancestor Akida SAI +SET @ENTRY := 17379; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,54,0,100,0,0,1,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Just Summoned - Run Script'), +-- Script +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,3,0,16995,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Script - set model'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Script - turn to player'), +(@ENTRY*100,9,2,0,0,0,100,0,0,0,0,0,11,25035,0,0,0,0,0,1,0,0,0,0,0,0,0.01745319,'Stillpine Ancestor Akida - Script - Cast Spell'), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Script - Set run on'), +(@ENTRY*100,9,4,0,0,0,100,0,4000,4000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Script - say 0'), +(@ENTRY*100,9,5,0,0,0,100,0,1000,1000,0,0,69,0,0,0,0,0,0,8,0,0,0,-4154.224,-12514.75,45.35527,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,6,0,0,0,100,0,2000,2000,0,0,69,0,0,0,0,0,0,8,0,0,0,-4123.563,-12517.23,44.9127,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,7,0,0,0,100,0,3500,3500,0,0,69,0,0,0,0,0,0,8,0,0,0,-4091.881,-12524,42.37354,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,8,0,0,0,100,0,5500,5500,0,0,69,0,0,0,0,0,0,8,0,0,0,-4058.039,-12538.57,43.96096,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,9,0,0,0,100,0,4500,4500,0,0,69,0,0,0,0,0,0,8,0,0,0,-4026.534,-12568.4,45.82222,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,10,0,0,0,100,0,3000,3000,0,0,69,0,0,0,0,0,0,8,0,0,0,-4000.155,-12598.55,54.19722,0,'Stillpine Ancestor Akida - Script - move to'), -- +(@ENTRY*100,9,11,0,0,0,100,0,7500,7500,0,0,69,0,0,0,0,0,0,8,0,0,0,-3977.5,-12627.22,63.1442,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,12,0,0,0,100,0,3500,3500,0,0,69,0,0,0,0,0,0,8,0,0,0,-3952.254,-12660.37,74.23783,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,13,0,0,0,100,0,6500,6500,0,0,69,0,0,0,0,0,0,8,0,0,0,-3933.183,-12698.27,85.65151,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,14,0,0,0,100,0,4500,4500,0,0,69,0,0,0,0,0,0,8,0,0,0,-3925.843,-12718.81,89.94553,0,'Stillpine Ancestor Akida - Script - move to'), -- +(@ENTRY*100,9,15,0,0,0,100,0,3500,3500,0,0,69,0,0,0,0,0,0,8,0,0,0,-3915.914,-12743.41,98.56779,0,'Stillpine Ancestor Akida - Script - move to'), +(@ENTRY*100,9,16,0,0,0,100,0,4500,4500,0,0,66,0,0,0,0,0,0,19,17361,10,0,0,0,0,0,'Stillpine Ancestor Akida - Script - turn to Totem of Coo'), +(@ENTRY*100,9,17,0,0,0,100,0,2000,2000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Script - say 1'), +(@ENTRY*100,9,18,0,0,0,100,0,3000,3000,0,0,11,30428,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Script - cast spell'), +(@ENTRY*100,9,19,0,0,0,100,0,1000,1000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Akida - Script - despawn'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=17379; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17379,0,0, '%s urges you to follow him.',16,0,100,0,0,0, 'Stillpine Ancestor Akida'), +(17379,1,0, '%s points to the totem of Coo.',16,0,100,25,0,0, 'Stillpine Ancestor Akida'); +-- add missing spells to db +DELETE FROM `spell_dbc` WHERE `Id` IN (30426,30437); +INSERT INTO `spell_dbc` (`Id`,`SchoolMask`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`Comment`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`DmgMultiplier1`,`DmgMultiplier2`,`AreaGroupId`,`EffectMiscValueB1`) VALUES +(30426,0,0,0,256,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,40,12,0,-1,0,0,28,6,0,0,0,0,0,0,0,0,0,0,0,0,0,32,1,0,0,0,0,15,0,0,0,4,0,0,0,0,0,0,0,17379,0,0,0,0,0,'Stillpine Ancestor Akida',0,0,0,0,0,0,0,1,1,0,64), +(30437,0,0,0,2304,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,36,3,0,-1,0,0,6,0,0,1,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,0,23,0,0,1000,0,0,0,0,0,0,0,0,30426,0,0,'Stillpine Ancestor Akida TRIGGER',0,0,0,0,0,0,0,1,0,0,0); diff --git a/sql/updates/world/2012_06_14_10_world_eai.sql b/sql/updates/world/2012_06_14_10_world_eai.sql new file mode 100644 index 00000000000..355646fbd69 --- /dev/null +++ b/sql/updates/world/2012_06_14_10_world_eai.sql @@ -0,0 +1,2 @@ +-- Remove Stillpine Ancestor Akida EAI +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=17379; diff --git a/sql/updates/world/2012_06_14_11_world_sai.sql b/sql/updates/world/2012_06_14_11_world_sai.sql new file mode 100644 index 00000000000..1d01b02f86b --- /dev/null +++ b/sql/updates/world/2012_06_14_11_world_sai.sql @@ -0,0 +1,48 @@ +-- Fix up quest 9540 "Totem of Tikti" +-- Totem of Coo SAI +SET @ENTRY := 17361; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,19,0,100,0,9540,0,0,0,85,30442,0,0,0,0,0,7,0,0,0,0,0,0,0,'Totem of Coo - Quest accepted - Cast Spell on player'); +-- Stillpine Ancestor Coo SAI +SET @ENTRY := 17391; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,54,0,100,0,0,1,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Just Summoned - Run Script'), +-- Script +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,3,0,16995,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - set model'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - turn to player'), +(@ENTRY*100,9,2,0,0,0,100,0,0,0,0,0,11,25035,0,0,0,0,0,1,0,0,0,0,0,0,0.01745319,'Stillpine Ancestor Coo - Script - Cast Spell'), +(@ENTRY*100,9,3,0,0,0,100,0,3000,3000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - say 0'), +(@ENTRY*100,9,4,0,0,0,100,0,1000,1000,0,0,69,0,0,0,0,0,0,8,0,0,0,-3926.039,-12746.71,96.06779,0,'Stillpine Ancestor Coo - Script - move to'), +(@ENTRY*100,9,5,0,0,0,100,0,1000,1000,0,0,69,0,0,0,0,0,0,8,0,0,0,-3926.326,-12753.71,98.44279,0,'Stillpine Ancestor Coo - Script - move to'), +(@ENTRY*100,9,6,0,0,0,100,0,2000,2000,0,0,69,0,0,0,0,0,0,8,0,0,0,-3924.268,-12761.45,101.6928,0,'Stillpine Ancestor Coo - Script - move to'), +(@ENTRY*100,9,7,0,0,0,100,0,6000,6000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - say 1'), +(@ENTRY*100,9,8,0,0,0,100,0,4000,4000,0,0,11,30424,0,0,0,0,0,7,0,0,0,0,0,0,0.01745319,'Stillpine Ancestor Coo - Script - Cast Spell'), +(@ENTRY*100,9,9,0,0,0,100,0,1000,1000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - say 2'), +(@ENTRY*100,9,10,0,0,0,100,0,4000,4000,0,0,11,30473,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - cast spell'), +(@ENTRY*100,9,11,0,0,0,100,0,0,0,0,0,3,0,17019,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - set model'), +(@ENTRY*100,9,12,0,0,0,100,0,3000,3000,0,0,60,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - Fly on'), +(@ENTRY*100,9,13,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,-3926.068,-12767.33,104.3799,0,'Stillpine Ancestor Coo - Script - move to'), +(@ENTRY*100,9,14,0,0,0,100,0,1000,1000,0,0,69,0,0,0,0,0,0,8,0,0,0,-3923.497,-12794.98,98.46323,0,'Stillpine Ancestor Coo - Script - move to'), +(@ENTRY*100,9,15,0,0,0,100,0,4000,4000,0,0,69,0,0,0,0,0,0,8,0,0,0,-3922.687,-12832.4,89.24097,0,'Stillpine Ancestor Coo - Script - move to'), +(@ENTRY*100,9,16,0,0,0,100,0,8000,8000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Coo - Script - despawn'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=17391; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17391,0,0, '%s motions for you to follow him.',16,0,100,0,0,0, 'Stillpine Ancestor Coo'), +(17391,1,0, '[Furbolg] Ritk kin''chikx azul azure summit...',12,0,100,0,0,0, 'Stillpine Ancestor Coo'), +(17391,2,0, '[Furbolg] Coo xip fly... Jump ilos river. Find Tikti.',12,0,100,0,0,0, 'Stillpine Ancestor Coo'); +-- add missing spells to db +DELETE FROM `spell_dbc` WHERE `Id` IN (30429,30442); +INSERT INTO `spell_dbc` (`Id`,`SchoolMask`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`Comment`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`DmgMultiplier1`,`DmgMultiplier2`,`AreaGroupId`,`EffectMiscValueB1`) VALUES +(30429,0,0,0,256,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,40,12,0,-1,0,0,28,6,0,0,0,0,0,0,0,0,0,0,0,0,0,32,1,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,17391,0,0,0,0,0,'Stillpine Ancestor Coo',0,0,0,0,0,0,0,1,1,0,64), +(30442,0,0,0,2304,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,36,3,0,-1,0,0,6,0,0,1,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,0,23,0,0,1000,0,0,0,0,0,0,0,0,30429,0,0,'Stillpine Ancestor Coo TRIGGER',0,0,0,0,0,0,0,1,0,0,0); +-- Delete bad spawn of Stillpine Ancestor Coo +DELETE FROM `creature` WHERE `guid`=86512; +DELETE FROM `creature_addon` WHERE `guid`=86512; +-- Remove Stillpine Ancestor Akida EAI +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=17391; diff --git a/sql/updates/world/2012_06_15_00_world_spell_script_names.sql b/sql/updates/world/2012_06_15_00_world_spell_script_names.sql new file mode 100644 index 00000000000..040ad3c87ba --- /dev/null +++ b/sql/updates/world/2012_06_15_00_world_spell_script_names.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` = 27819; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(27819, 'spell_kelthuzad_detonate_mana'); diff --git a/sql/updates/world/2012_06_15_01_world_sai.sql b/sql/updates/world/2012_06_15_01_world_sai.sql new file mode 100644 index 00000000000..501c3aa1c40 --- /dev/null +++ b/sql/updates/world/2012_06_15_01_world_sai.sql @@ -0,0 +1,32 @@ +-- Fix up quest 9544 "The Prophecy of Akida" +-- Totem of Vark SAI +SET @ENTRY := 17364; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +UPDATE `creature_template_addon` SET `bytes2`=1,`auras`='18950' WHERE `entry`=17364; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,19,0,100,0,9544,0,0,0,85,30453,0,0,0,0,0,7,0,0,0,0,0,0,0,'Totem of Vark - Quest accepted - Cast Spell on player'); +-- Stillpine Ancestor Vark SAI +SET @ENTRY := 17410; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,54,0,100,0,0,1,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Vark - Just Summoned - Run Script'), +-- Script +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,3,0,17109,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Vark - Script - set model'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,11,25035,0,0,0,0,0,1,0,0,0,0,0,0,0.01745319,'Stillpine Ancestor Vark - Script - Cast Spell'), +(@ENTRY*100,9,2,0,0,0,100,0,0,0,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Vark - Script - Set run on'), +(@ENTRY*100,9,3,0,0,0,100,0,2000,2000,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Stillpine Ancestor Vark - Script - turn to player'), +(@ENTRY*100,9,4,0,0,0,100,0,2000,2000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Vark - Script - say 0'), +(@ENTRY*100,9,5,0,0,0,100,0,8000,8000,0,0,11,30428,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Vark - Script - cast spell'), +(@ENTRY*100,9,6,0,0,0,100,0,3000,3000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Vark - Script - despawn'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=17410; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17410,0,0, '[Furbolg] Bear witness to the savage acts of our adversaries, $N. They steal our young... our weak... Imprisoned here, they are left to the devices of the Bristlelimb. Set them free, Promised One!',12,0,100,0,0,0, 'Stillpine Ancestor Vark'); +-- add missing spells to db +DELETE FROM `spell_dbc` WHERE `Id` IN (30453,30454); +INSERT INTO `spell_dbc` (`Id`,`SchoolMask`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`Comment`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`DmgMultiplier1`,`DmgMultiplier2`,`AreaGroupId`,`EffectMiscValueB1`) VALUES +(30454,0,0,0,256,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,40,12,0,-1,0,0,28,6,0,0,0,0,0,0,0,0,0,0,0,0,0,32,1,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,17410,0,0,0,0,0,'Stillpine Ancestor Vark',0,0,0,0,0,0,0,1,1,0,64), +(30453,0,0,0,2304,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,36,3,0,-1,0,0,6,0,0,1,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,0,23,0,0,1000,0,0,0,0,0,0,0,0,30454,0,0,'Stillpine Ancestor Vark TRIGGER',0,0,0,0,0,0,0,1,0,0,0); diff --git a/sql/updates/world/2012_06_15_02_world_sai.sql b/sql/updates/world/2012_06_15_02_world_sai.sql new file mode 100644 index 00000000000..f813ae2996b --- /dev/null +++ b/sql/updates/world/2012_06_15_02_world_sai.sql @@ -0,0 +1,44 @@ +-- Fix up quest 9312 "The Emitter" +-- Technician Zhanaa SAI +SET @ENTRY := 17071; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY*100 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,20,0,100,0,9312,0,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Technician Zhanaa - Quest Completed - Run Script'), +-- Script +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,83,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Technician Zhanaa - Script - Remove npc flags'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,9,0,0,0,0,0,0,20,181286,0,0,0,0,0,0,'Technician Zhanaa - Script - Activate go'), +(@ENTRY*100,9,2,0,0,0,100,0,0,0,0,0,12,16550,1,39000,0,0,0,8,0,0,0,-4187.708,-13738.72,75.65491,1.850049,'Technician Zhanaa - Script - Spawn '), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,64,2,0,0,0,0,0,7,0,0,0,0,0,0,0,'Technician Zhanaa - Script - store invoker'), -- Send target +(@ENTRY*100,9,4,0,0,0,100,0,1000,1000,0,0,100,2,0,0,0,0,0,19,16550,10,0,0,0,0,0,'Technician Zhanaa - Script - send target'), -- Send target +(@ENTRY*100,9,5,0,0,0,100,0,1000,1000,0,0,45,0,1,0,0,0,0,19,16550,10,0,0,0,0,0,'Technician Zhanaa - Script - set data'), +(@ENTRY*100,9,6,0,0,0,100,0,1000,1000,0,0,66,0,0,0,0,0,0,19,16550,10,0,0,0,0,0,'Technician Zhanaa - Script - turn to Image of Technician Dyvuun'), +(@ENTRY*100,9,7,0,0,0,100,0,2000,2000,0,0,5,70,0,0,0,0,0,1,0,0,0,0,0,0,0,'Technician Zhanaa - Script - emote'), +(@ENTRY*100,9,8,0,0,0,100,0,39000,39000,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Technician Zhanaa - Script - turn to invoker'), +(@ENTRY*100,9,9,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Technician Zhanaa - Script - Say 0'), +(@ENTRY*100,9,10,0,0,0,100,0,6000,6000,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,1.919862,'Technician Zhanaa - Script - turn to'), +(@ENTRY*100,9,11,0,0,0,100,0,1000,1000,0,0,81,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Technician Zhanaa - Script - add npc flags'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'This is great news! Your efforts have indeed saved us, $N!',12,0,100,0,0,0, 'Technician Zhanaa'); +-- Image of Technician Dyvuun SAI +SET @ENTRY := 16550; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='',`InhabitType`=4 WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY*100 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,38,0,100,0,0,1,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Image of Technician Dyvuun - On data set - Run Script'), +-- Script +(@ENTRY*100,9,0,0,0,0,100,0,2000,2000,0,0,66,0,0,0,0,0,0,19,17071,10,0,0,0,0,0,'Image of Technician Dyvuun - Script - turn to Technician Zhanaa'), +(@ENTRY*100,9,1,0,0,0,100,0,2000,2000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Image of Technician Dyvuun - Script - Say 0'), +(@ENTRY*100,9,2,0,0,0,100,0,10000,10000,0,0,66,0,0,0,0,0,0,12,2,0,0,0,0,0,0,'Image of Technician Dyvuun - Script - turn to Stored target'), -- use target +(@ENTRY*100,9,3,0,0,0,100,0,4000,4000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Image of Technician Dyvuun - Script - Say 1'), +(@ENTRY*100,9,4,0,0,0,100,0,5000,5000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Image of Technician Dyvuun - Script - Say 2'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@ENTRY,0,0, 'By the seven Ata''mal crystals! Others have survived the crash! Zhanaa, is that you? It is so good to see you again!',12,0,100,0,0,0, 'Image of Technician Dyvuun'), +(@ENTRY,1,0, 'And who do we have here? No doubt th... crzzzk ...ade this communication possible? I give you greetings fro... psshzzzk... Azure Watch.',12,0,100,0,0,0, 'Image of Technician Dyvuun'), +(@ENTRY,2,0, 'Judging by your signal, we put you... ust southeast of the larger part of the island we crashed onto. Cross the Crystalbrook River to ge... kshhhhk zzzt. Sorry, there''s a lot of stat...',12,0,100,0,0,0, 'Image of Technician Dyvuun'); diff --git a/sql/updates/world/2012_06_16_00_world_sai.sql b/sql/updates/world/2012_06_16_00_world_sai.sql new file mode 100644 index 00000000000..a714e498bc9 --- /dev/null +++ b/sql/updates/world/2012_06_16_00_world_sai.sql @@ -0,0 +1,46 @@ +-- Fix up quest 9541 "Totem of Yor" +-- Totem of Tikti SAI +SET @ENTRY := 17362; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,19,0,100,0,9541,0,0,0,85,30443,0,0,0,0,0,7,0,0,0,0,0,0,0,'Totem of Tikti - Quest accepted - Cast Spell on player'); +-- Stillpine Ancestor Tikti SAI +SET @ENTRY := 17392; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,54,0,100,0,0,1,0,0,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Just Summoned - Run Script'), +-- Script +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,3,0,16999,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - set model'), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - turn to player'), +(@ENTRY*100,9,2,0,0,0,100,0,0,0,0,0,11,25035,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - Cast Spell'), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,59,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - Set run on'), +(@ENTRY*100,9,4,0,0,0,100,0,2000,2000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - say 0'), +(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,-3885.665,-13096.55,3.563835,0,'Stillpine Ancestor Tikti - Script - move to'), +(@ENTRY*100,9,6,0,0,0,100,0,16000,16000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - say 1'), +(@ENTRY*100,9,7,0,0,0,100,0,6000,6000,0,0,11,30430,2,0,0,0,0,7,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - Cast Spell on player'), +(@ENTRY*100,9,8,0,0,0,100,0,2000,2000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - say 2'), +(@ENTRY*100,9,9,0,0,0,100,0,1000,1000,0,0,11,30431,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - Cast Spell'), +(@ENTRY*100,9,10,0,0,0,100,0,0,0,0,0,3,0,17000,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - set model'), +(@ENTRY*100,9,11,0,0,0,100,0,3000,3000,0,0,69,0,0,0,0,0,0,8,0,0,0,-3939.131,-13024.07,-5.92465,0,'Stillpine Ancestor Tikti - Script - move to'), +(@ENTRY*100,9,12,0,0,0,100,0,25000,25000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Stillpine Ancestor Tikti - Script - despawn'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=17392; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17392,0,0, '%s asks you to follow him.',16,0,100,0,0,0, 'Stillpine Ancestor Tikti'), +(17392,1,0, '[Furbolg] Far you mixik tak come. Gaze upon the kitch''kal river. Follow. Ilog to Yor.',12,0,100,0,0,0, 'Stillpine Ancestor Tikti'), +(17392,2,0, '[Furbolg] Go... Search yitix''kil bottom river. South!',12,0,100,0,0,0, 'Stillpine Ancestor Tikti'); +-- add missing spells to db +DELETE FROM `spell_dbc` WHERE `Id` IN (30432,30443); +INSERT INTO `spell_dbc` (`Id`,`SchoolMask`,`Dispel`,`Mechanic`,`Attributes`,`AttributesEx`,`AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`Stances`,`StancesNot`,`Targets`,`CastingTimeIndex`,`AuraInterruptFlags`,`ProcFlags`,`ProcChance`,`ProcCharges`,`MaxLevel`,`BaseLevel`,`SpellLevel`,`DurationIndex`,`RangeIndex`,`StackAmount`,`EquippedItemClass`,`EquippedItemSubClassMask`,`EquippedItemInventoryTypeMask`,`Effect1`,`Effect2`,`Effect3`,`EffectDieSides1`,`EffectDieSides2`,`EffectDieSides3`,`EffectRealPointsPerLevel1`,`EffectRealPointsPerLevel2`,`EffectRealPointsPerLevel3`,`EffectBasePoints1`,`EffectBasePoints2`,`EffectBasePoints3`,`EffectMechanic1`,`EffectMechanic2`,`EffectMechanic3`,`EffectImplicitTargetA1`,`EffectImplicitTargetA2`,`EffectImplicitTargetA3`,`EffectImplicitTargetB1`,`EffectImplicitTargetB2`,`EffectImplicitTargetB3`,`EffectRadiusIndex1`,`EffectRadiusIndex2`,`EffectRadiusIndex3`,`EffectApplyAuraName1`,`EffectApplyAuraName2`,`EffectApplyAuraName3`,`EffectAmplitude1`,`EffectAmplitude2`,`EffectAmplitude3`,`EffectMultipleValue1`,`EffectMultipleValue2`,`EffectMultipleValue3`,`EffectMiscValue1`,`EffectMiscValue2`,`EffectMiscValue3`,`EffectTriggerSpell1`,`EffectTriggerSpell2`,`EffectTriggerSpell3`,`Comment`,`MaxTargetLevel`,`SpellFamilyName`,`SpellFamilyFlags1`,`SpellFamilyFlags2`,`MaxAffectedTargets`,`DmgClass`,`PreventionType`,`DmgMultiplier1`,`DmgMultiplier2`,`AreaGroupId`,`EffectMiscValueB1`) VALUES +(30432,0,0,0,256,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,40,12,0,-1,0,0,28,6,0,0,0,0,0,0,0,0,0,0,0,0,0,32,1,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,17392,0,0,0,0,0,'Stillpine Ancestor Tikti',0,0,0,0,0,0,0,1,1,0,64), +(30443,0,0,0,2304,268435456,0,0,0,0,0,0,0,1,0,0,101,0,0,0,0,36,3,0,-1,0,0,6,0,0,1,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,0,23,0,0,1000,0,0,0,0,0,0,0,0,30432,0,0,'Stillpine Ancestor Tikti TRIGGER',0,0,0,0,0,0,0,1,0,0,0); +-- Delete bad spawn of Stillpine Ancestor Tikti +DELETE FROM `creature` WHERE `guid`=86513; +DELETE FROM `creature_addon` WHERE `guid`=86513; +-- Remove Stillpine Ancestor Tikti EAI +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=17392; +-- Remove Hack from quest_template +UPDATE `quest_template` SET `SourceSpellId`=0 WHERE `Id`=9541; diff --git a/sql/updates/world/2012_06_16_01_world_creature.sql b/sql/updates/world/2012_06_16_01_world_creature.sql new file mode 100644 index 00000000000..d44b568f79b --- /dev/null +++ b/sql/updates/world/2012_06_16_01_world_creature.sql @@ -0,0 +1,6 @@ +-- Add missing Storm Totem spawn to Borean Tundra +SET @GUID := 12925; +DELETE FROM `creature` WHERE `guid`=@GUID; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@GUID,26048,571,1,1,0,0,3409.903,4128.829,18.13754,5.742133,300,0,0,1,0,0); +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|16777216 WHERE `entry`=26048; diff --git a/sql/updates/world/2012_06_17_00_world_creature.sql b/sql/updates/world/2012_06_17_00_world_creature.sql new file mode 100644 index 00000000000..53e101c5d60 --- /dev/null +++ b/sql/updates/world/2012_06_17_00_world_creature.sql @@ -0,0 +1,3 @@ +-- Fix Storm Totem flags +UPDATE `creature_template` SET `npcflag`=`npcflag`|16777216 WHERE `entry`=26048; +UPDATE `creature_template` SET `flags_extra`=`flags_extra`&~16777216 WHERE `entry`=26048; diff --git a/sql/updates/world/2012_06_17_01_world_creature.sql b/sql/updates/world/2012_06_17_01_world_creature.sql new file mode 100644 index 00000000000..c5d50fdde1e --- /dev/null +++ b/sql/updates/world/2012_06_17_01_world_creature.sql @@ -0,0 +1,4 @@ +-- Add aura missing aura to Nerub'ar Scarab +DELETE FROM `creature_addon` WHERE `guid` IN (SELECT `guid` FROM creature WHERE id=25652); +DELETE FROM `creature_template_addon` WHERE `entry`=25652; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (25652,1,'45814'); diff --git a/sql/updates/world/2012_06_17_02_world_creature.sql b/sql/updates/world/2012_06_17_02_world_creature.sql new file mode 100644 index 00000000000..a309ada3498 --- /dev/null +++ b/sql/updates/world/2012_06_17_02_world_creature.sql @@ -0,0 +1,9 @@ +-- Add missing Gan'jo spawn to Grizzly Hills +SET @GUID := 42187; +SET @ENTRY := 26924; +DELETE FROM `creature` WHERE `guid`=@GUID; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@GUID,@ENTRY,571,1,2,0,0,4834.98,-4754.5,32.5689,3.97935,180,0,0,1,0,0); +-- Add Aura to Gan'jo +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@ENTRY,1,'17327'); diff --git a/sql/updates/world/2012_06_18_00_world_creature.sql b/sql/updates/world/2012_06_18_00_world_creature.sql new file mode 100644 index 00000000000..23538c33f73 --- /dev/null +++ b/sql/updates/world/2012_06_18_00_world_creature.sql @@ -0,0 +1,26 @@ +SET @CGUID := 88615; +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+00 AND @CGUID+22; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`MovementType`) VALUES +(@CGUID+00,39190,631,12,1,505.1563,-2536.863,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+01,39190,631,12,1,502.6493,-2531.328,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+02,39190,631,12,1,503.8246,-2508.141,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+03,39190,631,12,1,495.3629,-2538.215,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+04,39190,631,12,1,506.8715,-2515.552,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+05,39190,631,12,1,481.3021,-2509.222,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+06,39190,631,12,1,481.5382,-2527.332,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+07,39190,631,12,1,500.0807,-2523.289,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+08,39190,631,12,1,486.6632,-2517.747,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+09,39190,631,12,1,513.8802,-2511.795,1069.596,0,10,10,1), -- Wicked Spirit +(@CGUID+10,39190,631,12,1,499.6406,-2500.783,1069.656,0,10,10,1), -- Wicked Spirit +(@CGUID+11,39190,631,12,1,513.7101,-2530.931,1069.596,0,10,10,1), -- Wicked Spirit +(@CGUID+12,39190,631,12,1,502.6811,-2522.542,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+13,39190,631,12,1,518.7483,-2521.240,1069.596,0,10,10,1), -- Wicked Spirit +(@CGUID+14,39190,631,12,1,478.9774,-2517.446,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+15,39190,631,12,1,489.0104,-2538.535,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+16,39190,631,12,1,511.6320,-2522.373,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+17,39190,631,12,1,500.8976,-2527.198,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+18,39190,631,12,1,484.7934,-2533.592,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+19,39190,631,12,1,490.4132,-2504.323,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+20,39190,631,12,1,485.0298,-2527.724,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+21,39190,631,12,1,494.2899,-2511.384,1069.598,0,10,10,1), -- Wicked Spirit +(@CGUID+22,39190,631,12,1,491.7170,-2532.490,1069.598,0,10,10,1); -- Wicked Spirit diff --git a/sql/updates/world/2012_06_18_01_world_spell_script_names.sql b/sql/updates/world/2012_06_18_01_world_spell_script_names.sql new file mode 100644 index 00000000000..5f227a887d7 --- /dev/null +++ b/sql/updates/world/2012_06_18_01_world_spell_script_names.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` = 23880; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(23880, 'spell_warr_bloodthirst_heal'); diff --git a/sql/updates/world/2012_06_18_02_world_sai.sql b/sql/updates/world/2012_06_18_02_world_sai.sql new file mode 100644 index 00000000000..0c036d3d5f0 --- /dev/null +++ b/sql/updates/world/2012_06_18_02_world_sai.sql @@ -0,0 +1,41 @@ +-- Fix quest 11895 "Master the Storm" +-- Storm Totem SAI +SET @ENTRY := 26048; +UPDATE `creature_template` SET `npcflag`=`npcflag`&~16777216,`AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,11,0,100,0,0,0,0,0,81,16777216,0,0,0,0,0,1,0,0,0,0,0,0,0,'Storm Totem - On spawn - set npcflag'), +(@ENTRY,0,1,2,73,0,100,0,0,0,0,0,12,26045,2,300000,0,0,0,8,0,0,0,3403.829,4133.074,18.13754,5.759586,'Storm Totem - On Spellclick - Spawn Storm Tempest'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,81,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Storm Totem - On spawn - remove npcflag'); +-- Storm Tempest SAI +SET @ENTRY := 26045; +UPDATE `creature_template` SET `unit_flags`=0,`AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=26045; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY*100 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,63,0,100,0,0,0,0,0,11,8609,2,0,0,0,0,1,0,0,0,0,0,0,0,'Storm Totem - On spawn - cast aura'), +(@ENTRY,0,1,0,1,0,100,1,1000,1000,1000,1000,12,23837,2,120000,0,0,0,8,0,0,0,3403.871,4133.031,18.13754,5.67232,'Storm Totem - OOC - Spawn ELM General Purpose Bunny'), +(@ENTRY,0,2,0,60,0,100,1,1000,1000,7000,8000,11,40136,2,0,0,0,0,19,23837,5,0,0,0,0,0,'Storm Totem - Update Event - cast aura'), +(@ENTRY,0,3,4,4,0,100,1,0,0,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,'Storm Totem - On Aggro - Say 0'), +(@ENTRY,0,4,0,61,0,100,0,0,0,0,0,21,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Storm Totem - On Aggro - Prevent combat movement'), +(@ENTRY,0,5,0,0,0,100,0,0,30,6000,7500,11,15659,0,0,0,0,0,2,0,0,0,0,0,0,0,'Storm Totem - Combat - Cast Chain Lightning'), +(@ENTRY,0,6,0,0,0,100,0,8000,11000,9000,14000,11,31272,0,0,0,0,0,2,0,0,0,0,0,0,0,'Storm Totem - Combat - Cast Wind Shock'), +(@ENTRY,0,7,8,6,0,100,0,0,0,0,0,51,0,0,0,0,0,0,9,23837,0,10,0,0,0,0,'Storm Totem - On death - despawn trigger'), +(@ENTRY,0,8,9,61,0,100,0,0,0,0,0,81,16777216,0,0,0,0,0,19,26048,10,0,0,0,0,0,'Storm Totem - On death - set npc flags on totem'), +(@ENTRY,0,9,0,61,0,100,0,0,0,0,0,85,46424,2,0,0,0,0,16,0,0,0,0,0,0,0,'Storm Totem - Combat - Cast Power of the Storm'); +-- Sage Earth and Sky SAI +SET @ENTRY := 25982; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,20,0,100,0,11895,0,0,0,28,46424,0,0,0,0,0,7,0,0,0,0,0,0,0,'Sage Earth and Sky - On Quest reward - remove aura from player'); +-- NPC talk text insert from sniff +DELETE FROM `creature_text` WHERE `entry`=26045; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(26045,0,0, 'You will not master me, puny $r!',12,0,100,0,0,0, 'Storm Tempest'); +-- Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry`=26048; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(22,2,26048,0,0,9,0,11895,0,0,0,0, '', 'Storm Totem - Allow sai action only if quest has been taken'), +(22,2,26048,0,0,28,0,11895,0,0,1,0, '', 'Storm Totem - Allow sai action only if quest has not been completed'); diff --git a/sql/updates/world/2012_06_18_03_world_sai.sql b/sql/updates/world/2012_06_18_03_world_sai.sql new file mode 100644 index 00000000000..833c64c8d9d --- /dev/null +++ b/sql/updates/world/2012_06_18_03_world_sai.sql @@ -0,0 +1,39 @@ +-- Fix Quest 13231 The Broken Front and 13232 Finish Me! +-- Dying Soldier SAI +SET @ENTRY := 31304; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,62,0,100,0,10040,0,0,0,11,58955,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Cast Alliance Quest Aura on player'), +(@ENTRY,0,1,2,62,0,100,0,10040,3,0,0,11,58955,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Cast Alliance Quest Aura on player'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Close Gossip'), +(@ENTRY,0,3,4,62,0,100,0,10040,1,0,0,85,59226,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Player cast Finish It on npc'), +(@ENTRY,0,4,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Close Gossip'), +(@ENTRY,0,6,7,8,0,100,0,59226,0,0,0,11,3240,2,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Spellhit - Cast Bloody Explosion on self'), +(@ENTRY,0,7,0,61,0,100,0,0,0,0,0,33,31312,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Give Kill credit to player'); +-- Update Gossip +SET @GOSSIP := 10040; +-- Add conditions for gossip text +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=@GOSSIP; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,@GOSSIP,13948,0,28,13231,0,0,0,0,'','Only show gossip text 13948 if player has quest 13231 Complete'), +(14,@GOSSIP,13948,0,14,13232,0,0,0,0,'','Only show gossip text 13948 if player has quest 13232 Not Taken'), +(14,@GOSSIP,14035,0,9,13232,0,0,0,0,'','Only show gossip text 14035 if player has quest 13232 active'); +-- Add conditions for gossip options +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=@GOSSIP; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,@GOSSIP,0,0,9,13231,0,0,0,0,'','Only show gossip option 0 if player has if player has quest 13231 active'), +(15,@GOSSIP,1,0,9,13232,0,0,0,0,'','Only show gossip option 1 if player has if player has quest 13232 active'), +(15,@GOSSIP,3,0,28,13231,0,0,0,0,'','Only show gossip option 3 if player has quest 13231 Complete'), +(15,@GOSSIP,3,0,14,13232,0,0,0,0,'','Only show gossip option 3 if player has quest 13232 Not Taken'); +-- Update Gossip options +UPDATE `gossip_menu_option` SET `action_menu_id`=10041 WHERE `menu_id`=10040 AND `id`=0; +-- Fix npcflags for Dying Soldier +UPDATE `creature_template` SET `npcflag`=1 WHERE `entry`=31304; +UPDATE `creature` SET `npcflag`=3 WHERE `guid`=122230; +UPDATE `creature` SET `npcflag`=0 WHERE `guid`=122233; +-- Quest conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN (19,20) AND `SourceEntry`=13232; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(19,0,13232,0,28,13231,0,0,0,0, '', 'Quest 13232 Finish Me! Requires Quest 13231 The Broken Front to be complete'), +(20,0,13232,0,28,13231,0,0,0,0, '', 'Quest 13232 Finish Me! Requires Quest 13231 The Broken Front to be complete'); diff --git a/sql/updates/world/2012_06_19_00_world_sai.sql b/sql/updates/world/2012_06_19_00_world_sai.sql new file mode 100644 index 00000000000..fdfc5aec5f8 --- /dev/null +++ b/sql/updates/world/2012_06_19_00_world_sai.sql @@ -0,0 +1,25 @@ +-- Fix Quest 13231 The Broken Front and 13232 Finish Me! +-- Dying Soldier SAI +SET @ENTRY := 31304; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,62,0,100,0,10040,0,0,0,11,58955,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Cast Alliance Quest Aura on player'), +(@ENTRY,0,1,2,62,0,100,0,10040,3,0,0,81,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Set npcflag'), +(@ENTRY,0,2,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Close Gossip'), +(@ENTRY,0,3,4,62,0,100,0,10040,1,0,0,85,59226,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Player cast Finish It on npc'), +(@ENTRY,0,4,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Close Gossip'), +(@ENTRY,0,6,7,8,0,100,0,59226,0,0,0,11,3240,2,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Spellhit - Cast Bloody Explosion on self'), +(@ENTRY,0,7,0,61,0,100,0,0,0,0,0,33,31312,0,0,0,0,0,7,0,0,0,0,0,0,0,'Dying Soldier - On Gossip Option Select - Give Kill credit to player'), +(@ENTRY,0,8,9,25,0,100,0,0,0,0,0,81,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Spawn - Set npcflag'), +(@ENTRY,0,9,0,61,0,100,0,0,0,0,0,8,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Spawn - Set react state'), +(@ENTRY,0,10,0,19,0,100,0,13232,0,0,0,81,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dying Soldier - On Quest accept - Set npcflag'); +-- Creature updates +UPDATE `creature_template` SET `npcflag`=3,`RegenHealth`=0 WHERE `entry`=31304; +UPDATE `creature` SET `npcflag`=0 WHERE `guid`=122230; +UPDATE `creature` SET `curhealth`=37 WHERE `id`=31304; + +-- Start Fixing Quest 13228 The Broken Front and 13230 No Mercy! +-- Creature updates +UPDATE `creature_template` SET `npcflag`=3,`RegenHealth`=0 WHERE `entry`=31273; +UPDATE `creature` SET `curhealth`=37 WHERE `id`=31273; diff --git a/sql/updates/world/2012_06_19_01_world_gossip.sql b/sql/updates/world/2012_06_19_01_world_gossip.sql new file mode 100644 index 00000000000..7800d2a9740 --- /dev/null +++ b/sql/updates/world/2012_06_19_01_world_gossip.sql @@ -0,0 +1,161 @@ +-- Creature Gossip_menu_id Update from sniff +UPDATE `creature_template` SET `gossip_menu_id`=8871 WHERE `entry`=4501; -- Draz'Zilb +UPDATE `creature_template` SET `gossip_menu_id`=4004 WHERE `entry`=4885; -- Gregor MacVince +UPDATE `creature_template` SET `gossip_menu_id`=541 WHERE `entry`=4895; -- Smiling Jim +UPDATE `creature_template` SET `gossip_menu_id`=4122 WHERE `entry`=4900; -- Alchemist Narett +UPDATE `creature_template` SET `gossip_menu_id`=8840 WHERE `entry`=4921; -- Guard Byron +UPDATE `creature_template` SET `gossip_menu_id`=1186 WHERE `entry`=4926; -- Krog +UPDATE `creature_template` SET `gossip_menu_id`=1161 WHERE `entry`=4944; -- Captain Garran Vimes +UPDATE `creature_template` SET `gossip_menu_id`=5301 WHERE `entry`=4967; -- Archmage Tervosh +UPDATE `creature_template` SET `gossip_menu_id`=2465 WHERE `entry`=4968; -- Lady Jaina Proudmoore +UPDATE `creature_template` SET `gossip_menu_id`=8793 WHERE `entry`=5086; -- Captain Wymor +UPDATE `creature_template` SET `gossip_menu_id`=2916 WHERE `entry`=6546; -- Tabetha +UPDATE `creature_template` SET `gossip_menu_id`=4091 WHERE `entry`=8141; -- Captain Evencane +UPDATE `creature_template` SET `gossip_menu_id`=4355 WHERE `entry`=11052; -- Timothy Worthington +UPDATE `creature_template` SET `gossip_menu_id`=5382 WHERE `entry`=12939; -- Doctor Gustaf VanHowzen +UPDATE `creature_template` SET `gossip_menu_id`=8761 WHERE `entry`=23567; -- Inspector Tarem +UPDATE `creature_template` SET `gossip_menu_id`=8788 WHERE `entry`=23568; -- Captain Darill +UPDATE `creature_template` SET `gossip_menu_id`=8837 WHERE `entry`=23569; -- Renn McGill +UPDATE `creature_template` SET `gossip_menu_id`=8801 WHERE `entry`=23579; -- Brogg +UPDATE `creature_template` SET `gossip_menu_id`=8811 WHERE `entry`=23600; -- Apprentice Morlann +UPDATE `creature_template` SET `gossip_menu_id`=8812 WHERE `entry`=23601; -- Apprentice Garion +UPDATE `creature_template` SET `gossip_menu_id`=8762 WHERE `entry`=23602; -- Deserter Agitator +UPDATE `creature_template` SET `gossip_menu_id`=8782 WHERE `entry`=23704; -- Cassa Crimsonwing +UPDATE `creature_template` SET `gossip_menu_id`=8787 WHERE `entry`=23723; -- Sergeant Lukas +UPDATE `creature_template` SET `gossip_menu_id`=8830 WHERE `entry`=23797; -- Moxie Steelgrille +UPDATE `creature_template` SET `gossip_menu_id`=8831 WHERE `entry`=23835; -- Sergeant Amelyn +UPDATE `creature_template` SET `gossip_menu_id`=8826 WHERE `entry`=23896; -- "Dirty" Michael Crowe +UPDATE `creature_template` SET `gossip_menu_id`=8835 WHERE `entry`=23949; -- Lieutenant Nath +UPDATE `creature_template` SET `gossip_menu_id`=8836 WHERE `entry`=23950; -- Lieutenant Khand +UPDATE `creature_template` SET `gossip_menu_id`=8912 WHERE `entry`=24208; -- "Little" Logok +UPDATE `creature_template` SET `gossip_menu_id`=9342 WHERE `entry`=26546; -- Ludin Farrow + +-- Gossip Menu insert from sniff +DELETE FROM `gossip_menu` WHERE `entry`=541 AND `text_id`=1058; +DELETE FROM `gossip_menu` WHERE `entry`=1161 AND `text_id`=1793; +DELETE FROM `gossip_menu` WHERE `entry`=1162 AND `text_id`=1794; +DELETE FROM `gossip_menu` WHERE `entry`=1186 AND `text_id`=1818; +DELETE FROM `gossip_menu` WHERE `entry`=1187 AND `text_id`=1819; +DELETE FROM `gossip_menu` WHERE `entry`=1188 AND `text_id`=1820; +DELETE FROM `gossip_menu` WHERE `entry`=2465 AND `text_id`=3157; +DELETE FROM `gossip_menu` WHERE `entry`=2916 AND `text_id`=3590; +DELETE FROM `gossip_menu` WHERE `entry`=4004 AND `text_id`=5855; +DELETE FROM `gossip_menu` WHERE `entry`=4091 AND `text_id`=4991; +DELETE FROM `gossip_menu` WHERE `entry`=4122 AND `text_id`=5049; +DELETE FROM `gossip_menu` WHERE `entry`=4355 AND `text_id`=5571; +DELETE FROM `gossip_menu` WHERE `entry`=5301 AND `text_id`=6333; +DELETE FROM `gossip_menu` WHERE `entry`=5382 AND `text_id`=6414; +DELETE FROM `gossip_menu` WHERE `entry`=8761 AND `text_id`=11126; +DELETE FROM `gossip_menu` WHERE `entry`=8762 AND `text_id`=11136; +DELETE FROM `gossip_menu` WHERE `entry`=8782 AND `text_id`=11224; +DELETE FROM `gossip_menu` WHERE `entry`=8787 AND `text_id`=11243; +DELETE FROM `gossip_menu` WHERE `entry`=8788 AND `text_id`=11245; +DELETE FROM `gossip_menu` WHERE `entry`=8793 AND `text_id`=11264; +DELETE FROM `gossip_menu` WHERE `entry`=8801 AND `text_id`=11281; +DELETE FROM `gossip_menu` WHERE `entry`=8811 AND `text_id`=11309; +DELETE FROM `gossip_menu` WHERE `entry`=8812 AND `text_id`=11311; +DELETE FROM `gossip_menu` WHERE `entry`=8826 AND `text_id`=11376; +DELETE FROM `gossip_menu` WHERE `entry`=8830 AND `text_id`=11403; +DELETE FROM `gossip_menu` WHERE `entry`=8831 AND `text_id`=11406; +DELETE FROM `gossip_menu` WHERE `entry`=8835 AND `text_id`=11426; +DELETE FROM `gossip_menu` WHERE `entry`=8836 AND `text_id`=11428; +DELETE FROM `gossip_menu` WHERE `entry`=8837 AND `text_id`=11432; +DELETE FROM `gossip_menu` WHERE `entry`=8840 AND `text_id`=11457; +DELETE FROM `gossip_menu` WHERE `entry`=8871 AND `text_id`=11567; +DELETE FROM `gossip_menu` WHERE `entry`=8912 AND `text_id`=11797; +DELETE FROM `gossip_menu` WHERE `entry`=9342 AND `text_id`=12642; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(541,1058), +(1161,1793), +(1162,1794), +(1186,1818), +(1187,1819), +(1188,1820), +(2465,3157), +(2916,3590), +(4004,5855), +(4091,4991), +(4122,5049), +(4355,5571), +(5301,6333), +(5382,6414), +(8761,11126), +(8762,11136), +(8782,11224), +(8787,11243), +(8788,11245), +(8793,11264), +(8801,11281), +(8811,11309), +(8812,11311), +(8826,11376), +(8830,11403), +(8831,11406), +(8835,11426), +(8836,11428), +(8837,11432), +(8840,11457), +(8871,11567), +(8912,11797), +(9342,12642); + +-- Creature Gossip_menu_option insert from sniff +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (1161,4122,4355,5382,8761,8762) AND `id`=0; +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (1186,8826,8912) AND `id` IN (0,1); +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`)VALUES +(1161,0,0,'What have you heard of the Shady Rest Inn?',1,1,1162,0,0,0,''), +(1186,0,0,'The Burning Inn.',1,1,1187,0,0,0,''), +(1186,1,0,'Paval Reethe.',1,1,1188,0,0,0,''), +(4122,0,3,'Train me.',5,16,0,0,0,0,''), +(4355,0,3,'Train me.',5,16,0,0,0,0,''), +(5382,0,3,'Train me.',5,16,0,0,0,0,''), +(8761,0,0,'Can you spread the reflective dust again?',1,1,0,0,0,0,''), +(8762,0,0,'Your propaganda won''t work on me. Spout your treasonous filth elsewhere, traitor!',1,1,0,0,0,0,''), +(8826,0,3,'Train me.',5,16,0,0,0,0,''), +(8826,1,1,'Show me what you have for sale.',3,128,0,0,0,0,''), +(8912,0,5,'Make this inn your home.',8,65536,0,0,0,0,''), +(8912,1,1,'I want to browse your goods.',3,128,0,0,0,0,''); + +SET @NPC_DESERTER := 23602; +SET @NPC_INSPECTOR := 23567; +SET @SPELL_DISCOVERED_SUB := 42219; + +-- Insert creature_text from sniff +DELETE FROM `creature_text` WHERE `entry`=@NPC_DESERTER; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(@NPC_DESERTER,0,0,'It''s good to see you defending Theramore with pride, friend.',12,7,100,25,0,0,'Deserter Agitator'), +(@NPC_DESERTER,0,1,'When you''re off duty, let''s go to the inn. I''ll buy a round and we can reminisce about the good old days.',12,7,100,1,0,0,'Deserter Agitator'), +(@NPC_DESERTER,0,2,'Wouldn''t you like to bring those days back? I have some friends who know just the way to do that...''',12,7,100,1,0,0,'Deserter Agitator'), +(@NPC_DESERTER,1,0,'These people will know Admiral Proudmoore for the true hero he was!',12,7,100,5,0,0,'Deserter Agitator'), +(@NPC_DESERTER,1,1,'You can''t stop us from exposing the truth about Jaina''s cowardice!',12,7,100,5,0,0,'Deserter Agitator'), +(@NPC_DESERTER,1,2,'If you think you can stop us, you''re mistaken, ''friend.''',12,7,100,5,0,0,'Deserter Agitator'), +(@NPC_DESERTER,1,3,'It''s people like you who weaken the Alliance and invite the Horde to take away all we''ve fought for!',12,7,100,5,0,0,'Deserter Agitator'); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry`=@SPELL_DISCOVERED_SUB; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=8762 AND `SourceEntry`=0; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,@SPELL_DISCOVERED_SUB,0,0,31,0,3,23602,0,0,0,'','Spell Discovered (Sub) only targets Deserter Agitator'), +(15,8762,0,0,0,9,0,11126,0,0,0,0,'','Show gossip option only if player has taken quest 11126'); + +-- SmartAI +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_INSPECTOR,@NPC_DESERTER) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@NPC_DESERTER*100,@NPC_DESERTER*100+1) AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@NPC_INSPECTOR,0,0,1,62,0,100,0,8761,0,0,0,11,42169,0,0,0,0,0,7,0,0,0,0,0,0,0,'Inspector Tarem - On Gossip option select - Cast Reflective Dust'), +(@NPC_INSPECTOR,0,1,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Inspector Tarem - On Gossip option select - Close Gossip'), + +(@NPC_DESERTER,0,0,0,25,0,100,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Deserter Agitator - On reset - Set faction default'), +(@NPC_DESERTER,0,1,0,1,0,100,0,0,1,30000,40000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Deserter Agitator - On update OOC - Say line'), +(@NPC_DESERTER,0,2,3,62,0,100,0,8762,0,0,0,11,42203,0,0,0,0,0,7,0,0,0,0,0,0,0,'Deserter Agitator - On Gossip option select - Cast Discovered'), +(@NPC_DESERTER,0,3,0,61,0,100,0,0,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Deserter Agitator - On Gossip option select - Close Gossip'), +(@NPC_DESERTER,0,4,5,8,0,100,0,@SPELL_DISCOVERED_SUB,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Deserter Agitator - On spellhit Discovered (Sub) - Turn to invoker'), +(@NPC_DESERTER,0,5,6,61,0,100,0,0,0,0,0,1,1,0,0,0,0,0,7,0,0,0,0,0,0,0,'Deserter Agitator - On spellhit Discovered (Sub) - Say line'), +(@NPC_DESERTER,0,6,0,61,0,100,0,0,0,0,0,87,@NPC_DESERTER*100,@NPC_DESERTER*100+1,0,0,0,0,1,0,0,0,0,0,0,0,'Deserter Agitator - On spellhit Discovered (Sub) - Run script'), + +(@NPC_DESERTER*100,9,0,0,0,0,100,0,2000,2000,0,0,2,14,0,0,0,0,0,1,0,0,0,0,0,0,0,'Deserter Agitator''s script 0 - Set faction monster'), +(@NPC_DESERTER*100,9,1,0,0,0,100,0,0,0,0,0,49,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'Deserter Agitator''s script 0 - Attack'), + +(@NPC_DESERTER*100+1,9,0,0,0,0,100,0,0,0,0,0,83,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Deserter Agitator''s script 1 - Remove npcflag gossip'), +(@NPC_DESERTER*100+1,9,1,0,0,0,100,0,0,0,0,0,33,@NPC_DESERTER,0,0,0,0,0,7,0,0,0,0,0,0,0,'Deserter Agitator''s script 1 - Credit'), +(@NPC_DESERTER*100+1,9,2,0,0,0,100,0,30000,30000,0,0,82,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Deserter Agitator''s script 1 - Add npcflag gossip'); diff --git a/sql/updates/world/2012_06_19_02_world_misc.sql b/sql/updates/world/2012_06_19_02_world_misc.sql new file mode 100644 index 00000000000..32aa493f4f7 --- /dev/null +++ b/sql/updates/world/2012_06_19_02_world_misc.sql @@ -0,0 +1,98 @@ +-- Add missing spawns +SET @GUID := 42875; +SET @ENTRY := 26257; +DELETE FROM `creature` WHERE `guid` IN (@GUID,@GUID+1); +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@GUID,@ENTRY,571,1,1,0,0,3369.694,2528.735,197.4004,3.490659,180,0,0,1,0,0), +(@GUID+1,@ENTRY,571,1,1,0,0,3346.363,2534.127,197.4004,4.258604,180,0,0,1,0,0); +-- Add SAI +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (-42875,-42876,-109574,-109575) AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(-42875,0,0,0,1,0,100,1,1000,1000,30000,30000,11,46906,2,0,0,0,0,10,115101,27853,0,0,0,0,0,'Surge Needle Sorcerer - OOC - Cast Surge Needle Beam'), +(-42875,0,1,0,0,0,100,0,3000,4000,3000,5000,11,51797,0,0,0,0,0,2,0,0,0,0,0,0,0,'Surge Needle Sorcerer - Combat - Cast Arcane Blast on victim'), +(-42876,0,0,0,1,0,100,1,1000,1000,30000,30000,11,46906,2,0,0,0,0,10,115101,27853,0,0,0,0,0,'Surge Needle Sorcerer - OOC - Cast Surge Needle Beam'), +(-42876,0,1,0,0,0,100,0,3000,4000,3000,5000,11,51797,0,0,0,0,0,2,0,0,0,0,0,0,0,'Surge Needle Sorcerer - Combat - Cast Arcane Blast on victim'), +(-109574,0,0,0,1,0,100,1,1000,1000,30000,30000,11,46906,2,0,0,0,0,10,115101,27853,0,0,0,0,0,'Surge Needle Sorcerer - OOC - Cast Surge Needle Beam'), +(-109574,0,1,0,0,0,100,0,3000,4000,3000,5000,11,51797,0,0,0,0,0,2,0,0,0,0,0,0,0,'Surge Needle Sorcerer - Combat - Cast Arcane Blast on victim'), +(-109575,0,0,0,1,0,100,1,1000,1000,30000,30000,11,46906,2,0,0,0,0,10,115101,27853,0,0,0,0,0,'Surge Needle Sorcerer - OOC - Cast Surge Needle Beam'), +(-109575,0,1,0,0,0,100,0,3000,4000,3000,5000,11,51797,0,0,0,0,0,2,0,0,0,0,0,0,0,'Surge Needle Sorcerer - Combat - Cast Arcane Blast on victim'); +-- Add missing go +SET @GUID := 325; +SET @ENTRY := 188448; +DELETE FROM `gameobject` WHERE `guid` IN (@GUID); +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@GUID,@ENTRY,571,1,1,3346.398,2534.092,197.3171,2.82743,0,0,0.9876881,0.1564362,180,255,1); + +-- Pathing for Nexus Guardian +SET @NPC := 111304; +SET @PATH := @NPC*10; +DELETE FROM `creature` WHERE `guid`=@NPC; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`) VALUES +(@NPC,26276,571,1,1,0,0,3560.472,1769.351,171.9977,1.91463,120,0,0,1,0,2); +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes1`,`bytes2`) VALUES (@NPC,@PATH,50331648,1); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,3560.472,1769.351,171.9977,0,0,0,100,0), +(@PATH,2,3567.688,1720.065,171.9977,0,0,0,100,0), +(@PATH,3,3575.305,1671.264,171.9977,0,0,0,100,0), +(@PATH,4,3614.985,1641.572,171.9977,0,0,0,100,0), +(@PATH,5,3661.11,1627.888,179.4142,0,0,0,100,0), +(@PATH,6,3710.721,1625.472,184.0807,0,0,0,100,0), +(@PATH,7,3758.05,1626.899,186.8029,0,0,0,100,0), +(@PATH,8,3806.817,1636.863,186.8029,0,0,0,100,0), +(@PATH,9,3855.013,1638.274,186.8029,0,0,0,100,0), +(@PATH,10,3893.953,1607.221,186.8029,0,0,0,100,0), +(@PATH,11,3908.07,1563.533,186.8029,0,0,0,100,0), +(@PATH,12,3892.732,1516.304,186.8029,0,0,0,100,0), +(@PATH,13,3853.05,1486.712,186.8029,0,0,0,100,0), +(@PATH,14,3804.016,1484.734,186.8029,0,0,0,100,0), +(@PATH,15,3768.95,1518.886,186.8029,0,0,0,100,0), +(@PATH,16,3741.332,1558.961,193.6083,0,0,0,100,0), +(@PATH,17,3735.918,1607.949,197.9415,0,0,0,100,0), +(@PATH,18,3726.846,1656.945,201.9971,0,0,0,100,0), +(@PATH,19,3706.031,1701.895,208.3303,0,0,0,100,0), +(@PATH,20,3693.807,1748.982,208.3303,0,0,0,100,0), +(@PATH,21,3686.946,1791.952,208.3303,0,0,0,100,0), +(@PATH,22,3684.135,1840.943,208.3303,0,0,0,100,0), +(@PATH,23,3693.31,1889.799,208.3303,0,0,0,100,0), +(@PATH,24,3710.331,1936.957,208.3303,0,0,0,100,0), +(@PATH,25,3708.896,1985.871,203.9415,0,0,0,100,0), +(@PATH,26,3711.546,2034.778,199.0248,0,0,0,100,0), +(@PATH,27,3700.25,2079.795,185.8581,0,0,0,100,0), +(@PATH,28,3671.014,2118.18,175.6918,0,0,0,100,0), +(@PATH,29,3627.495,2141.961,170.8588,0,0,0,100,0), +(@PATH,30,3582.266,2162.844,165.0257,0,0,0,100,0), +(@PATH,31,3536.079,2181.72,161.0814,0,0,0,100,0), +(@PATH,32,3492.185,2203.827,153.3039,0,0,0,100,0), +(@PATH,33,3449.847,2227.899,147.0816,0,0,0,100,0), +(@PATH,34,3411.07,2258.388,138.6929,0,0,0,100,0), +(@PATH,35,3372.244,2288.043,130.0542,0,0,0,100,0), +(@PATH,36,3334.966,2320.363,127.8878,0,0,0,100,0), +(@PATH,37,3302.867,2358.885,123.2211,0,0,0,100,0), +(@PATH,38,3272.494,2397.996,120.9432,0,0,0,100,0), +(@PATH,39,3239.637,2434.888,118.8322,0,0,0,100,0), +(@PATH,40,3212.678,2476.519,116.0821,0,0,0,100,0), +(@PATH,41,3211.545,2525.56,108.0818,0,0,0,100,0), +(@PATH,42,3250.958,2578.278,107.5538,0,0,0,100,0), +(@PATH,43,3293.958,2602.603,107.5538,0,0,0,100,0), +(@PATH,44,3342.687,2610.276,112.9983,0,0,0,100,0), +(@PATH,45,3386.911,2594.68,123.2483,0,0,0,100,0), +(@PATH,46,3415.89,2554.956,128.7483,0,0,0,100,0), +(@PATH,47,3424.978,2506.423,128.7483,0,0,0,100,0), +(@PATH,48,3417.17,2457.855,128.7483,0,0,0,100,0), +(@PATH,49,3403.204,2427.43,128.7483,0,0,0,100,0), +(@PATH,50,3373.681,2392.189,128.7483,0,0,0,100,0), +(@PATH,51,3355.053,2347.842,128.7483,0,0,0,100,0), +(@PATH,52,3358.651,2298.717,128.7483,0,0,0,100,0), +(@PATH,53,3365.574,2249.818,135.9983,0,0,0,100,0), +(@PATH,54,3382.769,2202.925,136.9983,0,0,0,100,0), +(@PATH,55,3406.081,2159.531,144.9981,0,0,0,100,0), +(@PATH,56,3435.854,2119.649,151.8868,0,0,0,100,0), +(@PATH,57,3465.756,2080.089,151.8868,0,0,0,100,0), +(@PATH,58,3482.463,2041.774,142.5257,0,0,0,100,0), +(@PATH,59,3503.596,1996.099,137.0257,0,0,0,100,0), +(@PATH,60,3521.709,1951.099,137.0257,0,0,0,100,0), +(@PATH,61,3531.027,1914.229,150.5535,0,0,0,100,0), +(@PATH,62,3542.625,1866.008,158.9424,0,0,0,100,0), +(@PATH,63,3550.662,1817.174,163.9979,0,0,0,100,0); diff --git a/sql/updates/world/2012_06_20_00_world_gossip.sql b/sql/updates/world/2012_06_20_00_world_gossip.sql new file mode 100644 index 00000000000..b4d61887223 --- /dev/null +++ b/sql/updates/world/2012_06_20_00_world_gossip.sql @@ -0,0 +1,132 @@ +-- Insert npc_text from sniff +DELETE FROM `npc_text` WHERE `ID`=11428; +INSERT INTO `npc_text` (`ID`,`text0_0`,`text0_1`,`lang0`,`prob0`,`em0_0`,`em0_1`,`em0_2`,`em0_3`,`em0_4`,`em0_5`,`text1_0`,`text1_1`,`lang1`,`prob1`,`em1_0`,`em1_1`,`em1_2`,`em1_3`,`em1_4`,`em1_5`,`text2_0`,`text2_1`,`lang2`,`prob2`,`em2_0`,`em2_1`,`em2_2`,`em2_3`,`em2_4`,`em2_5`,`text3_0`,`text3_1`,`lang3`,`prob3`,`em3_0`,`em3_1`,`em3_2`,`em3_3`,`em3_4`,`em3_5`,`text4_0`,`text4_1`,`lang4`,`prob4`,`em4_0`,`em4_1`,`em4_2`,`em4_3`,`em4_4`,`em4_5`,`text5_0`,`text5_1`,`lang5`,`prob5`,`em5_0`,`em5_1`,`em5_2`,`em5_3`,`em5_4`,`em5_5`,`text6_0`,`text6_1`,`lang6`,`prob6`,`em6_0`,`em6_1`,`em6_2`,`em6_3`,`em6_4`,`em6_5`,`text7_0`,`text7_1`,`lang7`,`prob7`,`em7_0`,`em7_1`,`em7_2`,`em7_3`,`em7_4`,`em7_5`,`WDBVerified`) VALUES +(11428,'Are you here to relieve me? I''m certain it''s almost time. Well, if you want to relieve me anyway, let me know. I could use a drink or three.','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,12340); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=23567; +UPDATE `creature_template` SET `AIName`='SmartAI', `ScriptName`='' WHERE `entry`=23602; + +-- Creature Gossip_menu_id Update from sniff +UPDATE `creature_template` SET `gossip_menu_id`=7981 WHERE `entry`=19217; -- Ravandwyr <Kirin Tor Apprentice> +UPDATE `creature_template` SET `gossip_menu_id`=7996 WHERE `entry`=19488; -- Custodian Dieworth <Keeper of Kirin'Var> +UPDATE `creature_template` SET `gossip_menu_id`=7995 WHERE `entry`=19489; -- Lieutenant-Sorcerer Morran +UPDATE `creature_template` SET `gossip_menu_id`=7991 WHERE `entry`=19569; -- Netherologist Coppernickels <B.O.O.M.> +UPDATE `creature_template` SET `gossip_menu_id`=7994 WHERE `entry`=19578; -- Bot-Specialist Alley <B.O.O.M.> +UPDATE `creature_template` SET `gossip_menu_id`=8001 WHERE `entry`=19617; -- Boots <B.O.O.M. Master Mixologist> +UPDATE `creature_template` SET `gossip_menu_id`=8003 WHERE `entry`=19634; -- Lead Sapper Blastfizzle <B.O.O.M. Sap Foreman> +UPDATE `creature_template` SET `gossip_menu_id`=8024 WHERE `entry`=19644; -- Image of Archmage Vargoth +UPDATE `creature_template` SET `gossip_menu_id`=8008 WHERE `entry`=19645; -- Papa Wheeler <B.O.O.M. Mech Tech> +UPDATE `creature_template` SET `gossip_menu_id`=8030 WHERE `entry`=19709; -- Chief Engineer Trep <B.O.O.M. Engineering> +UPDATE `creature_template` SET `gossip_menu_id`=8032 WHERE `entry`=19728; -- Mama Wheeler <B.O.O.M. Mech Tech> +UPDATE `creature_template` SET `gossip_menu_id`=8048 WHERE `entry`=19880; -- Nether-Stalker Khay'ji +UPDATE `creature_template` SET `gossip_menu_id`=8054 WHERE `entry`=20066; -- Gahruj +UPDATE `creature_template` SET `gossip_menu_id`=8055 WHERE `entry`=20067; -- Zuben Elgenubi +UPDATE `creature_template` SET `gossip_menu_id`=8056 WHERE `entry`=20068; -- Zuben Eschamali +UPDATE `creature_template` SET `gossip_menu_id`=8071 WHERE `entry`=20071; -- Wind Trader Marid +UPDATE `creature_template` SET `gossip_menu_id`=8063 WHERE `entry`=20092; -- Dealer Hazzin <General Provisioner> +UPDATE `creature_template` SET `gossip_menu_id`=8068 WHERE `entry`=20110; -- Tyri +UPDATE `creature_template` SET `gossip_menu_id`=8070 WHERE `entry`=20112; -- Wind Trader Tuluman <Weapon Merchant> +UPDATE `creature_template` SET `gossip_menu_id`=8084 WHERE `entry`=20194; -- Dealer Dunar <General Provisioner> +UPDATE `creature_template` SET `gossip_menu_id`=8101 WHERE `entry`=20281; -- Drijya +UPDATE `creature_template` SET `gossip_menu_id`=8106 WHERE `entry`=20389; -- Lee Sparks <The Taskmaster> +UPDATE `creature_template` SET `gossip_menu_id`=8107 WHERE `entry`=20393; -- Foreman Sundown +UPDATE `creature_template` SET `gossip_menu_id`=8120 WHERE `entry`=20448; -- Commander Ameer <The Protectorate> +UPDATE `creature_template` SET `gossip_menu_id`=8180 WHERE `entry`=20449; -- Researcher Navuud <The Protectorate> +UPDATE `creature_template` SET `gossip_menu_id`=8183 WHERE `entry`=20450; -- Flesh Handler Viridius +UPDATE `creature_template` SET `gossip_menu_id`=8126 WHERE `entry`=20463; -- Apprentice Andrethan +UPDATE `creature_template` SET `gossip_menu_id`=8128 WHERE `entry`=20551; -- Agent Araxes <The Protectorate> +UPDATE `creature_template` SET `gossip_menu_id`=8231 WHERE `entry`=20810; -- Mehrdad +UPDATE `creature_template` SET `gossip_menu_id`=8229 WHERE `entry`=20903; -- Protectorate Nether Drake +UPDATE `creature_template` SET `gossip_menu_id`=8207 WHERE `entry`=20907; -- Professor Dabiri +UPDATE `creature_template` SET `gossip_menu_id`=8228 WHERE `entry`=20985; -- Captain Saeed +UPDATE `creature_template` SET `gossip_menu_id`=8308 WHERE `entry`=21493; -- Kablamm Farflinger <Transportation Engineer> +UPDATE `creature_template` SET `gossip_menu_id`=8542 WHERE `entry`=22427; -- Zarevhi +UPDATE `creature_template` SET `gossip_menu_id`=8710 WHERE `entry`=23396; -- Krixel Pinchwhistle <Classic Alliance Mail & Plate> +UPDATE `creature_template` SET `gossip_menu_id`=9781 WHERE `entry`=29145; -- Pulik Swiftsnip <Barber> + +-- Gossip Menu insert from sniff +DELETE FROM `gossip_menu` WHERE `entry`=7981 AND `text_id` IN (9826,9828); +DELETE FROM `gossip_menu` WHERE `entry`=7991 AND `text_id`=9841; +DELETE FROM `gossip_menu` WHERE `entry`=7994 AND `text_id`=9846; +DELETE FROM `gossip_menu` WHERE `entry`=7995 AND `text_id`=9847; +DELETE FROM `gossip_menu` WHERE `entry`=7996 AND `text_id`=9848; +DELETE FROM `gossip_menu` WHERE `entry`=8001 AND `text_id`=9863; +DELETE FROM `gossip_menu` WHERE `entry`=8003 AND `text_id`=9869; +DELETE FROM `gossip_menu` WHERE `entry`=8008 AND `text_id`=9875; +DELETE FROM `gossip_menu` WHERE `entry`=8024 AND `text_id`=9901; +DELETE FROM `gossip_menu` WHERE `entry`=8030 AND `text_id`=9916; +DELETE FROM `gossip_menu` WHERE `entry`=8032 AND `text_id`=9919; +DELETE FROM `gossip_menu` WHERE `entry`=8048 AND `text_id`=9937; +DELETE FROM `gossip_menu` WHERE `entry`=8054 AND `text_id`=9947; +DELETE FROM `gossip_menu` WHERE `entry`=8055 AND `text_id`=9948; +DELETE FROM `gossip_menu` WHERE `entry`=8056 AND `text_id`=9949; +DELETE FROM `gossip_menu` WHERE `entry`=8063 AND `text_id`=9959; +DELETE FROM `gossip_menu` WHERE `entry`=8068 AND `text_id`=9968; +DELETE FROM `gossip_menu` WHERE `entry`=8070 AND `text_id`=9970; +DELETE FROM `gossip_menu` WHERE `entry`=8071 AND `text_id`=9971; +DELETE FROM `gossip_menu` WHERE `entry`=8084 AND `text_id`=9994; +DELETE FROM `gossip_menu` WHERE `entry`=8101 AND `text_id`=10019; +DELETE FROM `gossip_menu` WHERE `entry`=8106 AND `text_id`=10031; +DELETE FROM `gossip_menu` WHERE `entry`=8107 AND `text_id`=10032; +DELETE FROM `gossip_menu` WHERE `entry`=8120 AND `text_id`=10058; +DELETE FROM `gossip_menu` WHERE `entry`=8121 AND `text_id`=10061; +DELETE FROM `gossip_menu` WHERE `entry`=8122 AND `text_id`=10060; +DELETE FROM `gossip_menu` WHERE `entry`=8123 AND `text_id`=10059; +DELETE FROM `gossip_menu` WHERE `entry`=8126 AND `text_id`=10064; +DELETE FROM `gossip_menu` WHERE `entry`=8128 AND `text_id`=10065; +DELETE FROM `gossip_menu` WHERE `entry`=8180 AND `text_id`=10152; +DELETE FROM `gossip_menu` WHERE `entry`=8183 AND `text_id`=10179; +DELETE FROM `gossip_menu` WHERE `entry`=8207 AND `text_id`=10202; +DELETE FROM `gossip_menu` WHERE `entry`=8228 AND `text_id`=10229; +DELETE FROM `gossip_menu` WHERE `entry`=8229 AND `text_id`=10230; +DELETE FROM `gossip_menu` WHERE `entry`=8231 AND `text_id`=10233; +DELETE FROM `gossip_menu` WHERE `entry`=8308 AND `text_id`=10365; +DELETE FROM `gossip_menu` WHERE `entry`=8542 AND `text_id`=10687; +DELETE FROM `gossip_menu` WHERE `entry`=8710 AND `text_id`=10957; +DELETE FROM `gossip_menu` WHERE `entry`=9781 AND `text_id`=13459; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(7981,9828),(7981, 9826),(7991,9841),(7994,9846),(7995,9847), +(7996,9848),(8001,9863),(8003,9869),(8008,9875),(8024,9901), +(8030,9916),(8032,9919),(8048,9937),(8054,9947),(8055,9948), +(8056,9949),(8063,9959),(8068,9968),(8070,9970),(8071,9971), +(8084,9994),(8101,10019),(8106,10031),(8107,10032),(8120,10058), +(8121,10061),(8122,10060),(8123,10059),(8126,10064),(8128,10065), +(8180,10152),(8183,10179),(8207,10202),(8228,10229),(8229,10230), +(8231,10233),(8308,10365),(8542,10687),(8710,10957),(9781,13459); + +-- Insert npc_text from sniff +DELETE FROM `npc_text` WHERE `ID` IN (10059,10061); +INSERT INTO `npc_text` (`ID`,`text0_0`,`text0_1`,`lang0`,`prob0`,`em0_0`,`em0_1`,`em0_2`,`em0_3`,`em0_4`,`em0_5`,`text1_0`,`text1_1`,`lang1`,`prob1`,`em1_0`,`em1_1`,`em1_2`,`em1_3`,`em1_4`,`em1_5`,`text2_0`,`text2_1`,`lang2`,`prob2`,`em2_0`,`em2_1`,`em2_2`,`em2_3`,`em2_4`,`em2_5`,`text3_0`,`text3_1`,`lang3`,`prob3`,`em3_0`,`em3_1`,`em3_2`,`em3_3`,`em3_4`,`em3_5`,`text4_0`,`text4_1`,`lang4`,`prob4`,`em4_0`,`em4_1`,`em4_2`,`em4_3`,`em4_4`,`em4_5`,`text5_0`,`text5_1`,`lang5`,`prob5`,`em5_0`,`em5_1`,`em5_2`,`em5_3`,`em5_4`,`em5_5`,`text6_0`,`text6_1`,`lang6`,`prob6`,`em6_0`,`em6_1`,`em6_2`,`em6_3`,`em6_4`,`em6_5`,`text7_0`,`text7_1`,`lang7`,`prob7`,`em7_0`,`em7_1`,`em7_2`,`em7_3`,`em7_4`,`em7_5`,`WDBVerified`) VALUES +(10059,'The Ethereum were the ruling class of ethereal on my homeworld of K''aresh. Tragically, we were forced to evacuate K''aresh shortly before the void lord, Dimensius, unleashed his void armies upon the world and utterly decimated all that stood in his way. For this act, the Ethereum vowed vengeance. They have been tracking Dimensius ever since...$B$BThe Protectorate, however, were not a reaction to Dimensius. We were a reaction to Ethereum.','',0,1,0,1,0,1,0,1,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,1,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340), +(10061,'We feel that the Ethereum are as great a threat to our existence as Dimensius. Both must be stopped...','',0,1,0,1,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,'','',0,0,0,0,0,0,0,0,12340); + +-- Creature Gossip_menu_option insert from sniff +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (8001,8063,8070,8084,8103,8120,8121,8122,8123,8126,8710) AND `id`=0; +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(8001, 0, 1, 'Boots, what do you have back there that goes down smooth?', 3, 128, 0, 0, 0, 0, ''), +(8063, 0, 1, 'Dealer Hazzin, what do you have to offer?', 3, 128, 0, 0, 0, 0, ''), +(8070, 0, 1, 'What do you have to sell, Tuluman?', 3, 128, 0, 0, 0, 0, ''), +(8084, 0, 1, 'Dealer Dunar, I wish to browse your wares.', 3, 128, 0, 0, 0, 0, ''), +(8103, 0, 5, 'Make this inn your home.', 8, 65536, 0, 0, 0, 0, ''), +(8120, 0, 0, 'What are Ethereum?', 1, 1, 8123, 0, 0, 0, ''), +(8121, 0, 0, 'I think I understand now. Can I help with any of this? The Ethereum and void creatures are a threat to our survival as well.', 1, 1, 8120, 0, 0, 0, ''), +(8122, 0, 0, 'So what is your purpose?', 1, 1, 8121, 0, 0, 0, ''), +(8123, 0, 0, 'I don''t understand. What do you mean, Ameer?', 1, 1, 8122, 0, 0, 0, ''), +(8126, 0, 1, 'I wish to browse your wares.', 3, 128, 0, 0, 0, 0, ''), +(8710, 0, 1, 'Let me browse your goods.', 3, 128, 0, 0, 0, 0, ''); + +-- Conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=7981 AND `SourceEntry`=9828; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,7981,9828,0,0,9,0,10173,0,0,0,0,'','Ravandwyr - Show different gossip if player has taken quest 10173'); + +-- Remove some old script text +DELETE FROM `script_texts` WHERE `entry` BETWEEN -1000649 AND -1000641; + +-- Add missing loot +DELETE FROM `creature_loot_template` WHERE `entry`=30524 AND `item`=35490; +INSERT INTO `creature_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +(30524,35490,-100,1,0,1,1); + +-- Add a missing gossip +UPDATE `creature_template` SET `gossip_menu_id`=1100 WHERE `entry`=4963; diff --git a/sql/updates/world/2012_06_20_01_world_sai.sql b/sql/updates/world/2012_06_20_01_world_sai.sql new file mode 100644 index 00000000000..989550de185 --- /dev/null +++ b/sql/updates/world/2012_06_20_01_world_sai.sql @@ -0,0 +1,26 @@ +-- Razormaw SAI fixes quest 9689 +SET @ENTRY := 17592; +UPDATE `creature_template` SET `AIName`= 'SmartAI',`ScriptName`='' WHERE `entry`=@ENTRY; +DELETE FROM `creature_template_addon` WHERE `entry`=@ENTRY; +INSERT INTO `creature_template_addon` (`entry`,`bytes1`,`bytes2`) VALUES (@ENTRY,50331648,1); +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,6000,6000,7000,9000,11,31279,0,0,0,0,0,2,0,0,0,0,0,0,0,'Razormaw - Combat - Cast Swipe'), +(@ENTRY,0,1,0,0,0,100,0,26000,30000,26000,30000,11,8873,0,0,0,0,0,1,0,0,0,0,0,0,0,'Razormaw - Combat - Cast Flame Breath'), +(@ENTRY,0,2,0,0,0,50,0,12000,12000,12000,12000,11,14100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Razormaw - Combat - Cast Terrifying Roar'), +(@ENTRY,0,3,0,11,0,100,0,0,0,0,0,53,1,@ENTRY,0,0,0,0,1,0,0,0,0,0,0,0,'Razormaw - On spawn - Load Path'), +(@ENTRY,0,4,0,40,0,100,0,10,@ENTRY,0,0,19,256,0,0,0,0,0,1,0,0,0,0,0,0,0,'Razormaw - On Reach waypoint - Remove unitflag'); +-- Waypoints for Razormaw +DELETE FROM `waypoints` WHERE `entry` IN (@ENTRY); +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(@ENTRY,1,-1045.958,-12583.85,111.7434, 'Razormaw'), +(@ENTRY,2,-1045.115,-12583.31,111.7434, 'Razormaw'), +(@ENTRY,3,-1213.006,-12663.19,200.4278, 'Razormaw'), +(@ENTRY,4,-1204.485,-12626.66,200.4278, 'Razormaw'), +(@ENTRY,5,-1204.906,-12599.65,188.7889, 'Razormaw'), +(@ENTRY,6,-1206.845,-12579.84,173.2892, 'Razormaw'), +(@ENTRY,7,-1203.169,-12555.49,160.956, 'Razormaw'), +(@ENTRY,8,-1201.284,-12529.25,134.3167, 'Razormaw'), +(@ENTRY,9,-1204.178,-12483.84,115.039, 'Razormaw'), +(@ENTRY,10,-1204.349,-12465.61,104.7762, 'Razormaw'), +(@ENTRY,11,-1205.651,-12460.52,97.53908, 'Razormaw'); diff --git a/sql/updates/world/2012_06_20_02_world_gossip.sql b/sql/updates/world/2012_06_20_02_world_gossip.sql new file mode 100644 index 00000000000..c20cb99aa4a --- /dev/null +++ b/sql/updates/world/2012_06_20_02_world_gossip.sql @@ -0,0 +1,17 @@ + -- Prince Toreth <Dragon Riders of Loreth'Aran> +UPDATE `creature_template` SET `gossip_menu_id`=7478 WHERE `entry`=17674; +-- Creature Gossip_menu insert from sniff +DELETE FROM `gossip_menu` WHERE `entry`=7474 AND `text_id`=9060; +DELETE FROM `gossip_menu` WHERE `entry`=7475 AND `text_id`=9059; +DELETE FROM `gossip_menu` WHERE `entry`=7476 AND `text_id`=9058; +DELETE FROM `gossip_menu` WHERE `entry`=7477 AND `text_id`=9057; +DELETE FROM `gossip_menu` WHERE `entry`=7478 AND `text_id`=9056; +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(7474,9060),(7475, 9059),(7476,9058),(7477,9057),(7478,9056); +-- Creature Gossip_menu_option insert from sniff +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (7478,7477,7476,7475) AND `id`=0; +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(7478,0,0, 'Why do you suffer?',1,1,7477,0,0,0, ''), +(7477,0,0, 'What is Ysera and how were you blessed?',1,1,7476,0,0,0, ''), +(7476,0,0, 'Until what?',1,1,7475,0,0,0, ''), +(7475,0,0, 'So why are you still here?',1,1,7474,0,0,0, ''); diff --git a/sql/updates/world/2012_06_24_00_world_gossip.sql b/sql/updates/world/2012_06_24_00_world_gossip.sql new file mode 100644 index 00000000000..f8aa5213bf4 --- /dev/null +++ b/sql/updates/world/2012_06_24_00_world_gossip.sql @@ -0,0 +1,296 @@ +-- Conditions for Spell "Stamp Out Bonfire" +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (45437); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +-- Alliance Bonfires +(13,1,45437,0,0,31,0,5,187564,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,1,31,0,5,187914,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,2,31,0,5,187916,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,3,31,0,5,187917,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,4,31,0,5,187919,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,5,31,0,5,187920,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,6,31,0,5,187921,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,7,31,0,5,187922,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,8,31,0,5,187923,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,9,31,0,5,187924,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,10,31,0,5,187925,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,11,31,0,5,187926,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,12,31,0,5,187927,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,13,31,0,5,187928,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,14,31,0,5,187929,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,15,31,0,5,187930,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,16,31,0,5,187931,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,17,31,0,5,187932,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,18,31,0,5,187933,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,19,31,0,5,187934,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,20,31,0,5,187935,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,21,31,0,5,187936,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,22,31,0,5,187937,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,23,31,0,5,187938,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,24,31,0,5,187939,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,25,31,0,5,187940,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,26,31,0,5,187941,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,27,31,0,5,187942,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,28,31,0,5,187943,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,29,31,0,5,187944,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,30,31,0,5,187945,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,31,31,0,5,187946,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,32,31,0,5,194032,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,33,31,0,5,194035,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,34,31,0,5,194036,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,35,31,0,5,194038,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,36,31,0,5,194040,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,37,31,0,5,194044,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,38,31,0,5,194045,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,39,31,0,5,194049,0,0,0,'','Spell can hit go target'), +-- Horde Bonfires +(13,1,45437,0,40,31,0,5,187559,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,41,31,0,5,187947,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,42,31,0,5,187948,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,43,31,0,5,187949,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,44,31,0,5,187950,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,45,31,0,5,187951,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,46,31,0,5,187952,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,47,31,0,5,187953,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,48,31,0,5,187954,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,49,31,0,5,187955,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,50,31,0,5,187956,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,51,31,0,5,187957,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,52,31,0,5,187958,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,53,31,0,5,187959,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,54,31,0,5,187960,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,55,31,0,5,187961,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,56,31,0,5,187962,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,57,31,0,5,187963,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,58,31,0,5,187964,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,59,31,0,5,187965,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,60,31,0,5,187966,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,61,31,0,5,187967,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,62,31,0,5,187968,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,63,31,0,5,187969,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,64,31,0,5,187970,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,65,31,0,5,187971,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,66,31,0,5,187972,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,67,31,0,5,187973,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,68,31,0,5,187974,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,69,31,0,5,187975,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,70,31,0,5,194033,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,71,31,0,5,194034,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,72,31,0,5,194037,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,73,31,0,5,194039,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,74,31,0,5,194042,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,75,31,0,5,194043,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,76,31,0,5,194046,0,0,0,'','Spell can hit go target'), +(13,1,45437,0,77,31,0,5,194048,0,0,0,'','Spell can hit go target'); + +-- Add Triggered spell +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=45458; +INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES +(45458,45437,1,'Holiday - Midsummer, Stamp Out Bonfire, Quest Complete triggers Stamp Out Bonfire'); + +-- Add script to bonfires +UPDATE `gameobject_template` SET `ScriptName`= 'go_midsummer_bonfire' WHERE `entry` IN (187559,187564,187914,187916,187917,187919,187920,187921,187922,187923,187924,187925,187926,187927,187928,187929,187930,187931,187932,187933,187934,187935,187936,187937,187938,187939,187940,187941,187942,187943,187944,187945,187946,187947,187948,187949,187950,187951,187952,187953,187954,187955,187956,187957,187958,187959,187960,187961,187962,187963,187964,187965,187966,187967,187968,187969,187970,187971,187972,187973,187974,187975,194032,194033,194034,194035,194036,194037,194038,194039,194040,194042,194043,194044,194045,194046,194048,194049); + +-- Add gossip to Horde Bonfires +DELETE FROM `gossip_menu` WHERE `entry` IN (9370,9353,9355,9379,9380,9381,9382,9383,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9371,9372,9373,9374,9375,9376,9377,9378,10228,10231,10232,10235,10236,10239,10241,10242); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(9370,12374),(9353,12374),(9355,12374),(9379,12374),(9380,12374),(9381,12374),(9382,12374), +(9383,12374),(9356,12374),(9357,12374),(9358,12374),(9359,12374),(9360,12374),(9361,12374), +(9362,12374),(9363,12374),(9364,12374),(9365,12374),(9366,12374),(9367,12374),(9368,12374), +(9369,12374),(9371,12374),(9372,12374),(9373,12374),(9374,12374),(9375,12374),(9376,12374), +(9377,12374),(9378,12374),(10228,12374),(10231,12374),(10232,12374),(10235,12374),(10236,12374), +(10239,12374),(10241,12374),(10242,12374); + +-- Creature Gossip_menu_option inserts for Horde bonfires +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (9370,9353,9355,9379,9380,9381,9382,9383,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9371,9372,9373,9374,9375,9376,9377,9378,10228,10231,10232,10235,10236,10239,10241,10242) AND `id`=0; +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(9370,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9353,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9355,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9379,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9380,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9381,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9382,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9383,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9356,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9357,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9358,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9359,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9360,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9361,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9362,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9363,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9364,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9365,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9366,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9367,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9368,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9369,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9371,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9372,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9373,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9374,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9375,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9376,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9377,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(9378,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10228,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10231,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10232,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10235,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10236,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10239,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10241,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''), +(10242,0,0, 'Stamp out the Horde bonfire!',1,1,0,0,0,0, ''); + +-- Add conditons for Horde Bonfires +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceEntry`=0 AND `SourceGroup` IN (9370,9353,9355,9379,9380,9381,9382,9383,9356,9357,9358,9359,9360,9361,9362,9363,9364,9365,9366,9367,9368,9369,9371,9372,9373,9374,9375,9376,9377,9378,10228,10231,10232,10235,10236,10239,10241,10242); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,9370,0,0,0,8,0,11581,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9353,0,0,0,8,0,11764,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9355,0,0,0,8,0,11765,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9379,0,0,0,8,0,11766,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9380,0,0,0,8,0,11767,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9381,0,0,0,8,0,11768,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9382,0,0,0,8,0,11769,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9383,0,0,0,8,0,11770,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9356,0,0,0,8,0,11771,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9357,0,0,0,8,0,11772,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9358,0,0,0,8,0,11773,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9359,0,0,0,8,0,11774,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9360,0,0,0,8,0,11775,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9361,0,0,0,8,0,11776,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9362,0,0,0,8,0,11777,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9363,0,0,0,8,0,11778,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9364,0,0,0,8,0,11779,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9365,0,0,0,8,0,11780,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9366,0,0,0,8,0,11781,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9367,0,0,0,8,0,11782,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9368,0,0,0,8,0,11783,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9369,0,0,0,8,0,11784,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9371,0,0,0,8,0,11785,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9372,0,0,0,8,0,11786,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9373,0,0,0,8,0,11787,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9374,0,0,0,8,0,11799,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9375,0,0,0,8,0,11800,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9376,0,0,0,8,0,11801,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9377,0,0,0,8,0,11802,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9378,0,0,0,8,0,11803,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10228,0,0,0,8,0,13441,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10231,0,0,0,8,0,13450,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10232,0,0,0,8,0,13451,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10235,0,0,0,8,0,13453,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10236,0,0,0,8,0,13454,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10239,0,0,0,8,0,13455,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10241,0,0,0,8,0,13457,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10242,0,0,0,8,0,13458,0,0,0,0,'','Show gossip option only if player has quest'); + +-- Fix required side for Alliance quest +UPDATE `quest_template` SET `RequiredRaces`=1101 WHERE `Id` IN (11581,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,11776,11777,11778,11779,11780,11781,11782,11783,11784,11785,11786,11787,11799,11800,11801,11802,11803,13441,13450,13451,13453,13454,13455,13457,13458); + +-- Fix Faction for Horde bonfires +UPDATE `gameobject_template` SET `faction`=1732 WHERE `entry` IN (187949,187955,187958,187960,187962,187965,187967,187974,194037,194039,194042,194043,194046,194048); + +-- Add gossip to Alliance Bonfires +DELETE FROM `gossip_menu` WHERE `entry` IN (9406,9352,9354,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9407,9408,9409,9410,9411,9412,9413,10227,10230,10233,10234,10237,10238,10240,10243); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(9406,12377),(9352,12377),(9354,12377),(9384,12377),(9385,12377),(9386,12377),(9387,12377),(9388,12377), +(9389,12377),(9390,12377),(9391,12377),(9392,12377),(9393,12377),(9394,12377),(9395,12377),(9396,12377), +(9397,12377),(9398,12377),(9399,12377),(9400,12377),(9401,12377),(9402,12377),(9403,12377),(9404,12377), +(9405,12377),(9407,12377),(9408,12377),(9409,12377),(9410,12377),(9411,12377),(9412,12377),(9413,12377), +(10227,12377),(10230,12377),(10233,12377),(10234,12377),(10237,12377),(10238,12377),(10240,12377),(10243,12377); + +-- Creature Gossip_menu_option insert from sniff +DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (9406,9352,9354,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9407,9408,9409,9410,9411,9412,9413,10227,10230,10233,10234,10237,10238,10240,10243) AND `id`=0; +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(9406,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9352,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9354,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9384,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9385,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9386,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9387,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9388,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9389,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9390,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9391,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9392,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9393,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9394,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9395,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9396,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9397,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9398,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9399,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9400,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9401,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9402,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9403,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9404,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9405,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9407,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9408,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9409,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9410,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9411,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9412,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(9413,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10227,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10230,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10233,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10234,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10237,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10238,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10240,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''), +(10243,0,0, 'Stamp out the Alliance bonfire!',1,1,0,0,0,0, ''); + +-- Add conditons for Alliance Bonfires +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceEntry`=0 AND `SourceGroup` IN (9406,9352,9354,9384,9385,9386,9387,9388,9389,9390,9391,9392,9393,9394,9395,9396,9397,9398,9399,9400,9401,9402,9403,9404,9405,9407,9408,9409,9410,9411,9412,9413,10227,10230,10233,10234,10237,10238,10240,10243); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,9406,0,0,0,8,0,11580,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9352,0,0,0,8,0,11732,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9354,0,0,0,8,0,11734,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9384,0,0,0,8,0,11735,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9385,0,0,0,8,0,11736,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9386,0,0,0,8,0,11737,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9387,0,0,0,8,0,11738,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9388,0,0,0,8,0,11739,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9389,0,0,0,8,0,11740,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9390,0,0,0,8,0,11741,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9391,0,0,0,8,0,11742,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9392,0,0,0,8,0,11743,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9393,0,0,0,8,0,11744,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9394,0,0,0,8,0,11745,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9395,0,0,0,8,0,11746,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9396,0,0,0,8,0,11747,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9397,0,0,0,8,0,11748,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9398,0,0,0,8,0,11749,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9399,0,0,0,8,0,11750,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9400,0,0,0,8,0,11751,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9401,0,0,0,8,0,11752,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9402,0,0,0,8,0,11753,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9403,0,0,0,8,0,11754,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9404,0,0,0,8,0,11755,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9405,0,0,0,8,0,11756,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9407,0,0,0,8,0,11757,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9408,0,0,0,8,0,11758,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9409,0,0,0,8,0,11759,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9410,0,0,0,8,0,11760,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9411,0,0,0,8,0,11761,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9412,0,0,0,8,0,11762,0,0,0,0,'','Show gossip option only if player has quest'), +(15,9413,0,0,0,8,0,11763,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10227,0,0,0,8,0,13440,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10230,0,0,0,8,0,13442,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10233,0,0,0,8,0,13443,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10234,0,0,0,8,0,13444,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10237,0,0,0,8,0,13445,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10238,0,0,0,8,0,13446,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10240,0,0,0,8,0,13447,0,0,0,0,'','Show gossip option only if player has quest'), +(15,10243,0,0,0,8,0,13449,0,0,0,0,'','Show gossip option only if player has quest'); + +-- Fix required side for Horde quest +UPDATE `quest_template` SET `RequiredRaces`=690 WHERE `Id` IN (11580,11732,11734,11735,11736,11737,11738,11739,11740,11741,11742,11743,11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,11762,11763,13440,13442,13443,13444,13445,13446,13447,13449); + +-- Fix Faction for Alliance bonfires +UPDATE `gameobject_template` SET `faction`=1735 WHERE `entry` IN (187564,187914,187916,187917); +UPDATE `gameobject_template` SET `faction`=1735 WHERE `entry` BETWEEN 187919 AND 187946; +UPDATE `gameobject_template` SET `faction`=1735 WHERE `entry` IN (194032,194035,194036,194038,194040,194044,194045,194049); diff --git a/sql/updates/world/2012_06_24_01_world_quest.sql b/sql/updates/world/2012_06_24_01_world_quest.sql new file mode 100644 index 00000000000..ec0d39b0c62 --- /dev/null +++ b/sql/updates/world/2012_06_24_01_world_quest.sql @@ -0,0 +1,167 @@ +DELETE FROM `gameobject_questrelation` WHERE `id` IN (187564,187914,187916,187917,187919,187920,187921,187922,187923,187924,187925,187926,187927,187928,187929,187930,187931,187931,187932,187933,187934,187935,187936,187937,187938,187939,187940,187941,187942,187943,187944,187945,187946,194032,194035,194036,194038,194040,194044,194045,194049); +INSERT INTO `gameobject_questrelation` (`id`,`quest`) VALUES +(187564,11580), +(187914,11732), +(187916,11734), +(187917,11735), +(187919,11736), +(187920,11737), +(187921,11738), +(187922,11739), +(187923,11740), +(187924,11741), +(187925,11742), +(187926,11743), +(187927,11744), +(187928,11745), +(187929,11746), +(187930,11747), +(187931,11748), +(187932,11749), +(187933,11750), +(187934,11751), +(187935,11752), +(187936,11753), +(187937,11754), +(187938,11755), +(187939,11756), +(187940,11757), +(187941,11758), +(187942,11759), +(187943,11760), +(187944,11761), +(187945,11762), +(187946,11763), +(194032,13440), +(194035,13442), +(194036,13443), +(194038,13444), +(194040,13445), +(194044,13446), +(194045,13447), +(194049,13449); + +DELETE FROM `gameobject_involvedrelation` WHERE `id` IN (187564,187914,187916,187917,187919,187920,187921,187922,187923,187924,187925,187926,187927,187928,187929,187930,187931,187931,187932,187933,187934,187935,187936,187937,187938,187939,187940,187941,187942,187943,187944,187945,187946,194032,194035,194036,194038,194040,194044,194045,194049); +INSERT INTO `gameobject_involvedrelation` (`id`,`quest`) VALUES +(187564,11580), +(187914,11732), +(187916,11734), +(187917,11735), +(187919,11736), +(187920,11737), +(187921,11738), +(187922,11739), +(187923,11740), +(187924,11741), +(187925,11742), +(187926,11743), +(187927,11744), +(187928,11745), +(187929,11746), +(187930,11747), +(187931,11748), +(187932,11749), +(187933,11750), +(187934,11751), +(187935,11752), +(187936,11753), +(187937,11754), +(187938,11755), +(187939,11756), +(187940,11757), +(187941,11758), +(187942,11759), +(187943,11760), +(187944,11761), +(187945,11762), +(187946,11763), +(194032,13440), +(194035,13442), +(194036,13443), +(194038,13444), +(194040,13445), +(194044,13446), +(194045,13447), +(194049,13449); + +DELETE FROM `gameobject_questrelation` WHERE `id` IN (187559,187947,187948,187949,187950,187951,187952,187953,187954,187955,187956,187957,187958,187959,187960,187961,187962,187963,187964,187965,187966,187967,187968,187969,187970,187971,187972,187973,187974,187975,194033,194034,194037,194039,194042,194043,194046,194048); +INSERT INTO `gameobject_questrelation` (`id`,`quest`) VALUES +(187559,11581), +(187947,11764), +(187948,11765), +(187949,11766), +(187950,11767), +(187951,11768), +(187952,11769), +(187953,11770), +(187954,11771), +(187955,11772), +(187956,11773), +(187957,11774), +(187958,11775), +(187959,11776), +(187960,11777), +(187961,11778), +(187962,11779), +(187963,11780), +(187964,11781), +(187965,11782), +(187966,11783), +(187967,11784), +(187968,11785), +(187969,11786), +(187970,11787), +(187971,11799), +(187972,11800), +(187973,11801), +(187974,11802), +(187975,11803), +(194033,13441), +(194034,13450), +(194037,13451), +(194039,13453), +(194042,13454), +(194043,13455), +(194046,13457), +(194048,13458); + +DELETE FROM `gameobject_involvedrelation` WHERE `id` IN (187559,187947,187948,187949,187950,187951,187952,187953,187954,187955,187956,187957,187958,187959,187960,187961,187962,187963,187964,187965,187966,187967,187968,187969,187970,187971,187972,187973,187974,187975,194033,194034,194037,194039,194042,194043,194046,194048); +INSERT INTO `gameobject_involvedrelation` (`id`,`quest`) VALUES +(187559,11581), +(187947,11764), +(187948,11765), +(187949,11766), +(187950,11767), +(187951,11768), +(187952,11769), +(187953,11770), +(187954,11771), +(187955,11772), +(187956,11773), +(187957,11774), +(187958,11775), +(187959,11776), +(187960,11777), +(187961,11778), +(187962,11779), +(187963,11780), +(187964,11781), +(187965,11782), +(187966,11783), +(187967,11784), +(187968,11785), +(187969,11786), +(187970,11787), +(187971,11799), +(187972,11800), +(187973,11801), +(187974,11802), +(187975,11803), +(194033,13441), +(194034,13450), +(194037,13451), +(194039,13453), +(194042,13454), +(194043,13455), +(194046,13457), +(194048,13458); diff --git a/sql/updates/world/2012_06_24_02_world_gameobject.sql b/sql/updates/world/2012_06_24_02_world_gameobject.sql new file mode 100644 index 00000000000..4894365462e --- /dev/null +++ b/sql/updates/world/2012_06_24_02_world_gameobject.sql @@ -0,0 +1,30 @@ +-- Burning Steppes Mid Summer Festival Go Spawns +SET @OGUID := 17820; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+19; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@OGUID+0,181302,0,1,1,-8265.07,-2627.144,135.0536,1.989672,0,0,0,1,120,255,1), +(@OGUID+1,181302,0,1,1,-8263.305,-2627.122,134.5683,2.949595,0,0,0,1,120,255,1), +(@OGUID+2,181305,0,1,1,-8258.544,-2624.803,133.4996,5.98648,0,0,0,1,120,255,1), +(@OGUID+3,181306,0,1,1,-8262.327,-2628.302,134.2665,2.007128,0,0,0,1,120,255,1), +(@OGUID+4,181307,0,1,1,-8257.901,-2625.303,134.469,1.658062,0,0,0,1,120,255,1), +(@OGUID+5,181355,0,1,1,-8260.892,-2601.407,133.1487,0.8552105,0,0,0,1,120,255,1), +(@OGUID+6,181355,0,1,1,-8262.448,-2606.505,133.4136,0.2443456,0,0,0,1,120,255,1), +(@OGUID+7,181355,0,1,1,-8245.146,-2606.867,133.1535,0.8552105,0,0,0,1,120,255,1), +(@OGUID+8,181355,0,1,1,-8264.143,-2611.291,133.4626,5.201083,0,0,0,1,120,255,1), +(@OGUID+9,181355,0,1,1,-8246.274,-2611.94,133.1546,4.66003,0,0,0,1,120,255,1), +(@OGUID+10,181355,0,1,1,-8247.434,-2616.645,133.1546,5.846854,0,0,0,1,120,255,1), +(@OGUID+11,181355,0,1,1,-8267.189,-2635.668,134.4242,0.1745321,0,0,0,1,120,255,1), +(@OGUID+12,181355,0,1,1,-8252.989,-2636.582,133.1547,3.211419,0,0,0,1,120,255,1), +(@OGUID+13,181605,0,1,1,-8261.666,-2638.048,133.3969,5.777041,0,0,0,1,120,255,1), +(@OGUID+14,187922,0,1,1,-8249.528,-2625.985,133.1546,1.727875,0,0,0,1,120,255,1), +(@OGUID+15,188020,0,1,1,-8267.534,-2642.816,133.9444,4.555311,0,0,0,1,120,255,1), +(@OGUID+16,188020,0,1,1,-8256.433,-2643.724,133.1869,4.468043,0,0,0,1,120,255,1), +(@OGUID+17,188020,0,1,1,-8258.073,-2601.522,133.1487,1.274088,0,0,0,1,120,255,1), +(@OGUID+18,188020,0,1,1,-8247.378,-2604.626,133.15,1.326448,0,0,0,1,120,255,1), +(@OGUID+19,188021,0,1,1,-8261.987,-2623.612,133.4952,1.361356,0,0,0,1,120,255,1); +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+19; +INSERT INTO `game_event_gameobject` (`eventEntry`,`guid`) VALUES +(1,@OGUID+0),(1,@OGUID+1),(1,@OGUID+2),(1,@OGUID+3),(1,@OGUID+4), +(1,@OGUID+5),(1,@OGUID+6),(1,@OGUID+7),(1,@OGUID+8),(1,@OGUID+9), +(1,@OGUID+10),(1,@OGUID+11),(1,@OGUID+12),(1,@OGUID+13),(1,@OGUID+14), +(1,@OGUID+15),(1,@OGUID+16),(1,@OGUID+17),(1,@OGUID+18),(1,@OGUID+19); diff --git a/sql/updates/world/2012_06_24_03_world_gameobject.sql b/sql/updates/world/2012_06_24_03_world_gameobject.sql new file mode 100644 index 00000000000..b98ef4b6dbe --- /dev/null +++ b/sql/updates/world/2012_06_24_03_world_gameobject.sql @@ -0,0 +1,28 @@ +-- Chillwind Camp Mid Summer Festival Go Spawns +SET @OGUID := 17845; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+17; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@OGUID+0,181300,0,1,1,945.1077,-1435.984,62.91423,5.288348,0,0,0,1,120,255,1), +(@OGUID+1,181302,0,1,1,1004.427,-1443.667,62.28303,2.949595,0,0,0,1,120,255,1), +(@OGUID+2,181302,0,1,1,1004.097,-1446.269,61.98349,1.989672,0,0,0,1,120,255,1), +(@OGUID+3,181305,0,1,1,1009.866,-1446.948,62.31522,3.490667,0,0,0,1,120,255,1), +(@OGUID+4,181306,0,1,1,1002.772,-1445.215,62.09951,2.007128,0,0,0,1,120,255,1), +(@OGUID+5,181307,0,1,1,1009.089,-1446.896,63.24824,1.658062,0,0,0,1,120,255,1), +(@OGUID+6,181355,0,1,1,995.8973,-1439.065,63.6682,0.8552105,0,0,0,1,120,255,1), +(@OGUID+7,181355,0,1,1,1010.988,-1450.932,62.06363,4.66003,0,0,0,1,120,255,1), +(@OGUID+8,181355,0,1,1,988.3309,-1455.517,60.69862,5.846854,0,0,0,1,120,255,1), +(@OGUID+9,181355,0,1,1,934.7761,-1439.972,63.46706,2.251473,0,0,0,1,120,255,1), +(@OGUID+10,181605,0,1,1,1002.282,-1432.47,64.05733,5.777041,0,0,0,1,120,255,1), +(@OGUID+11,187576,0,1,1,973.3299,-1430.872,67.15336,3.141593,0,0,0,1,120,255,1), +(@OGUID+12,187939,0,1,1,999.0452,-1453.844,60.73637,3.68265,0,0,0,1,120,255,1), +(@OGUID+13,188020,0,1,1,1011.989,-1434.024,63.98868,6.230826,0,0,0,1,120,255,1), +(@OGUID+14,188020,0,1,1,1017.408,-1450.234,62.41806,5.166176,0,0,0,1,120,255,1), +(@OGUID+15,188020,0,1,1,987.117,-1451.32,61.76295,3.717554,0,0,0,1,120,255,1), +(@OGUID+16,188020,0,1,1,990.5877,-1460.205,60.6304,3.595379,0,0,0,1,120,255,1), +(@OGUID+17,188021,0,1,1,1006.964,-1448.083,62.19069,5.148723,0,0,0,1,120,255,1); +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+19; +INSERT INTO `game_event_gameobject` (`eventEntry`,`guid`) VALUES +(1,@OGUID+0),(1,@OGUID+1),(1,@OGUID+2),(1,@OGUID+3),(1,@OGUID+4), +(1,@OGUID+5),(1,@OGUID+6),(1,@OGUID+7),(1,@OGUID+8),(1,@OGUID+9), +(1,@OGUID+10),(1,@OGUID+11),(1,@OGUID+12),(1,@OGUID+13),(1,@OGUID+14), +(1,@OGUID+15),(1,@OGUID+16),(1,@OGUID+17); diff --git a/sql/updates/world/2012_06_24_04_world_gameobject.sql b/sql/updates/world/2012_06_24_04_world_gameobject.sql new file mode 100644 index 00000000000..2fa34ee18c3 --- /dev/null +++ b/sql/updates/world/2012_06_24_04_world_gameobject.sql @@ -0,0 +1,30 @@ +-- The Forgotten Coast Alliance Mid Summer Festival Go Spawns +SET @OGUID := 21003; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+19; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@OGUID+0,188021,1,1,1,-4398.083,2187.373,12.25118,6.03884,0,0,0,1,120,255,1), +(@OGUID+1,181302,1,1,1,-4396.901,2188.478,12.71206,2.949595,0,0,0,1,120,255,1), +(@OGUID+2,181302,1,1,1,-4392.186,2182.861,12.36883,4.694937,0,0,0,1,120,255,1), +(@OGUID+3,181305,1,1,1,-4396.205,2185.561,12.88021,2.268925,0,0,0,1,120,255,1), +(@OGUID+4,181306,1,1,1,-4396.394,2190.134,12.45671,2.007128,0,0,0,1,120,255,1), +(@OGUID+5,181307,1,1,1,-4397.196,2185.575,13.85373,1.658062,0,0,0,1,120,255,1), +(@OGUID+6,181388,1,1,1,-4273.38,2246.32,10.7598,5.637414,0,0,0,1,120,255,1), +(@OGUID+7,181355,1,1,1,-4399.59,2167.158,11.20139,5.201083,0,0,0,1,120,255,1), +(@OGUID+8,181355,1,1,1,-4405.212,2185.207,12.17883,0.8552105,0,0,0,1,120,255,1), +(@OGUID+9,181355,1,1,1,-4402.662,2193.127,11.89757,5.846854,0,0,0,1,120,255,1), +(@OGUID+10,181355,1,1,1,-4387.453,2180.198,11.91319,4.66003,0,0,0,1,120,255,1), +(@OGUID+11,181355,1,1,1,-4385.776,2188.759,11.18229,0.8552105,0,0,0,1,120,255,1), +(@OGUID+12,181355,1,1,1,-4388.712,2208.042,10.41075,1.186823,0,0,0,1,120,255,1), +(@OGUID+13,181355,1,1,1,-4289.17,2237.73,9.40999,1.675514,0,0,0,1,120,255,1), +(@OGUID+14,181605,1,1,1,-4399.495,2171.792,11.82118,5.777041,0,0,0,1,120,255,1), +(@OGUID+15,187929,1,1,1,-4392.564,2198.469,10.85703,2.460913,0,0,0,1,120,255,1), +(@OGUID+16,188020,1,1,1,-4408.799,2171.87,12.71528,2.82743,0,0,0,1,120,255,1), +(@OGUID+17,188020,1,1,1,-4392.096,2168.01,13.40625,6.0912,0,0,0,1,120,255,1), +(@OGUID+18,188020,1,1,1,-4396.503,2207.885,9.430555,2.775069,0,0,0,1,120,255,1), +(@OGUID+19,188020,1,1,1,-4382.582,2200.814,9.956597,5.829401,0,0,0,1,120,255,1); +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+19; +INSERT INTO `game_event_gameobject` (`eventEntry`,`guid`) VALUES +(1,@OGUID+0),(1,@OGUID+1),(1,@OGUID+2),(1,@OGUID+3),(1,@OGUID+4), +(1,@OGUID+5),(1,@OGUID+6),(1,@OGUID+7),(1,@OGUID+8),(1,@OGUID+9), +(1,@OGUID+10),(1,@OGUID+11),(1,@OGUID+12),(1,@OGUID+13),(1,@OGUID+14), +(1,@OGUID+15),(1,@OGUID+16),(1,@OGUID+17),(1,@OGUID+18),(1,@OGUID+19); diff --git a/sql/updates/world/2012_06_25_00_world_spell_script_names.sql b/sql/updates/world/2012_06_25_00_world_spell_script_names.sql new file mode 100644 index 00000000000..51f3e19f5bc --- /dev/null +++ b/sql/updates/world/2012_06_25_00_world_spell_script_names.sql @@ -0,0 +1 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` = -66188; diff --git a/sql/updates/world/2012_06_25_01_world_gameobject.sql b/sql/updates/world/2012_06_25_01_world_gameobject.sql new file mode 100644 index 00000000000..5cadd915990 --- /dev/null +++ b/sql/updates/world/2012_06_25_01_world_gameobject.sql @@ -0,0 +1,64 @@ +-- Azuremyst Isle Alliance Mid Summer Festival Go Spawns +SET @OGUID := 70509; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+47; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@OGUID+0,181355,530,1,1,-4196.215,-11595.27,-125.4084,1.239183,0,0,0,1,120,255,1), +(@OGUID+1,181355,530,1,1,-4155.241,-11635.47,-98.17558,5.375615,0,0,0,1,120,255,1), +(@OGUID+2,181355,530,1,1,-4200.809,-11604.3,-125.62,0.4712385,0,0,0,1,120,255,1), +(@OGUID+3,181355,530,1,1,-4167.556,-11641.12,-98.394,1.134463,0,0,0,1,120,255,1), +(@OGUID+4,181355,530,1,1,-4229.965,-11608.42,-126.2826,0.8377575,0,0,0,1,120,255,1), +(@OGUID+5,181355,530,1,1,-4207.486,-11645.04,-143.677,0.1047193,0,0,0,1,120,255,1), +(@OGUID+6,181355,530,1,1,-4185.567,-11653.06,-143.4488,5.044002,0,0,0,1,120,255,1), +(@OGUID+7,181355,530,1,1,-4225.973,-11648.08,-143.8641,5.881761,0,0,0,1,120,255,1), +(@OGUID+8,181355,530,1,1,-4244.824,-11657.96,-143.6249,1.727875,0,0,0,1,120,255,1), +(@OGUID+9,181355,530,1,1,-4209.638,-11675.42,-143.2441,5.899214,0,0,0,1,120,255,1), +(@OGUID+10,181355,530,1,1,-4204.821,-11678.49,-143.1916,0.4014249,0,0,0,1,120,255,1), +(@OGUID+11,181355,530,1,1,-4163.965,-11666.74,-143.2581,4.677484,0,0,0,1,120,255,1), +(@OGUID+12,181355,530,1,1,-4253.186,-11675.28,-143.7647,4.677484,0,0,0,1,120,255,1), +(@OGUID+13,181355,530,1,1,-4178.041,-11713.54,-143.6017,0.7853968,0,0,0,1,120,255,1), +(@OGUID+14,181355,530,1,1,-4154.533,-11704.79,-143.3194,5.98648,0,0,0,1,120,255,1), +(@OGUID+15,181355,530,1,1,-4194.735,-11728.54,-143.4515,3.246347,0,0,0,1,120,255,1), +(@OGUID+16,181355,530,1,1,-4186.29,-11803.01,-133.1742,0.6108634,0,0,0,1,120,255,1), +(@OGUID+17,181355,530,1,1,-4228.949,-11818.94,-115.9345,0.802851,0,0,0,1,120,255,1), +(@OGUID+18,181355,530,1,1,-4210.176,-11796.16,-133.2452,1.570796,0,0,0,1,120,255,1), +(@OGUID+19,181355,530,1,1,-4185.515,-11746.04,-132.2725,3.036838,0,0,0,1,120,255,1), +(@OGUID+20,181355,530,1,1,-4221.807,-11830.92,-115.8959,5.305802,0,0,0,1,120,255,1), +(@OGUID+21,181355,530,1,1,-4161.4,-11800.58,-132.1952,4.555311,0,0,0,1,120,255,1), +(@OGUID+22,181355,530,1,1,-4217.298,-12296.37,2.797,4.66003,0,0,0,1,120,255,1), +(@OGUID+23,181355,530,1,1,-4208.977,-12291.46,1.564008,0.8552105,0,0,0,1,120,255,1), +(@OGUID+24,181355,530,1,1,-4231.342,-12311.88,4.430907,4.694937,0,0,0,1,120,255,1), +(@OGUID+25,181355,530,1,1,-4236.268,-12321.97,3.524465,0.5410506,0,0,0,1,120,255,1), +(@OGUID+26,181355,530,1,1,-4191.353,-12302.24,0.068963,3.211419,0,0,0,1,120,255,1), +(@OGUID+27,181355,530,1,1,-4196.024,-12313.57,0.370297,0.1745321,0,0,0,1,120,255,1), +(@OGUID+28,181355,530,1,1,-4215.688,-12343.17,5.164443,1.186823,0,0,0,1,120,255,1), +(@OGUID+29,181355,530,1,1,-4234.849,-12332.25,4.627616,5.846854,0,0,0,1,120,255,1), +(@OGUID+30,181355,530,1,1,-4207.028,-12336.08,2.900289,5.201083,0,0,0,1,120,255,1), +(@OGUID+31,181355,530,1,1,-4214.633,-12476,45.07409,5.497789,0,0,0,1,120,255,1), +(@OGUID+32,181302,530,1,1,-4224.03,-12301.6,4.06688,6.248279,0,0,0,1,120,255,1), +(@OGUID+33,181302,530,1,1,-4225.604,-12301.49,4.273456,1.937312,0,0,0,1,120,255,1), +(@OGUID+34,181305,530,1,1,-4219.088,-12304.94,2.68953,0.1396245,0,0,0,1,120,255,1), +(@OGUID+35,181306,530,1,1,-4224.28,-12299.62,4.223075,2.478367,0,0,0,1,120,255,1), +(@OGUID+36,181307,530,1,1,-4219.073,-12304.1,3.637502,0.01745246,0,0,0,1,120,255,1), +(@OGUID+37,181605,530,1,1,-4204.668,-12321.07,2.198824,5.777041,0,0,0,1,120,255,1), +(@OGUID+38,187917,530,1,1,-4223.843,-12318.37,2.47695,2.932139,0,0,0,1,120,255,1), +(@OGUID+39,188020,530,1,1,-4205.284,-12290.93,1.317262,0.7330382,0,0,0,1,120,255,1), +(@OGUID+40,188020,530,1,1,-4193.06,-12298.27,0.561426,0.9075702,0,0,0,1,120,255,1), +(@OGUID+41,188020,530,1,1,-4218.465,-12342.38,5.182833,1.361356,0,0,0,1,120,255,1), +(@OGUID+42,188020,530,1,1,-4231.875,-12334.86,4.329966,1.378809,0,0,0,1,120,255,1), +(@OGUID+43,188021,530,1,1,-4221.665,-12306.13,2.295757,5.654869,0,0,0,1,120,255,1), +(@OGUID+44,187667,530,1,1,-4216.924,-12483.89,48.3932,6.230826,0,0,0,1,120,255,1), +(@OGUID+45,187667,530,1,1,-4216.502,-12480.64,48.98628,6.213374,0,0,0,1,120,255,1), +(@OGUID+46,181392,530,1,1,-4213.729,-11685.4,-130.8234,0.9424766,0,0,0,1,120,255,1), +(@OGUID+47,181392,530,1,1,-4145.799,-11745.62,-124.1529,2.024579,0,0,0,1,120,255,1); +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+47; +INSERT INTO `game_event_gameobject` (`eventEntry`,`guid`) VALUES +(1,@OGUID+0),(1,@OGUID+1),(1,@OGUID+2),(1,@OGUID+3),(1,@OGUID+4), +(1,@OGUID+5),(1,@OGUID+6),(1,@OGUID+7),(1,@OGUID+8),(1,@OGUID+9), +(1,@OGUID+10),(1,@OGUID+11),(1,@OGUID+12),(1,@OGUID+13),(1,@OGUID+14), +(1,@OGUID+15),(1,@OGUID+16),(1,@OGUID+17),(1,@OGUID+18),(1,@OGUID+19), +(1,@OGUID+20),(1,@OGUID+21),(1,@OGUID+22),(1,@OGUID+23),(1,@OGUID+24), +(1,@OGUID+25),(1,@OGUID+26),(1,@OGUID+27),(1,@OGUID+28),(1,@OGUID+29), +(1,@OGUID+30),(1,@OGUID+31),(1,@OGUID+32),(1,@OGUID+33),(1,@OGUID+34), +(1,@OGUID+35),(1,@OGUID+36),(1,@OGUID+37),(1,@OGUID+38),(1,@OGUID+39), +(1,@OGUID+40),(1,@OGUID+41),(1,@OGUID+42),(1,@OGUID+43),(1,@OGUID+44), +(1,@OGUID+45),(1,@OGUID+46),(1,@OGUID+47); diff --git a/sql/updates/world/2012_06_25_02_world_gameobject.sql b/sql/updates/world/2012_06_25_02_world_gameobject.sql new file mode 100644 index 00000000000..f526f071bac --- /dev/null +++ b/sql/updates/world/2012_06_25_02_world_gameobject.sql @@ -0,0 +1,85 @@ +-- Blades Edge Alliance Mid Summer Festival Go Spawns +SET @OGUID := 70557; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+37; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@OGUID+0,187576,530,1,1,1989.314,6784.465,167.9164,4.537859,0,0,0,1,120,255,1), +(@OGUID+1,181391,530,1,1,1989.554,6785.711,165.7517,4.607672,0,0,0,1,120,255,1), +(@OGUID+2,181392,530,1,1,1955.625,6885.821,167.1296,4.468043,0,0,0,1,120,255,1), +(@OGUID+3,181392,530,1,1,2032.214,6819.37,181.5125,3.874631,0,0,0,1,120,255,1), +(@OGUID+4,181392,530,1,1,2031.963,6825.553,181.5333,2.426008,0,0,0,1,120,255,1), +(@OGUID+5,181392,530,1,1,2038.565,6819.838,181.4885,5.550147,0,0,0,1,120,255,1), +(@OGUID+6,181392,530,1,1,2038.027,6826.094,181.4816,0.8377575,0,0,0,1,120,255,1), +(@OGUID+7,181392,530,1,1,2063.305,6759.898,173.2681,4.694937,0,0,0,1,120,255,1), +(@OGUID+8,181392,530,1,1,2062.016,6825.854,184.7832,4.729844,0,0,0,1,120,255,1), +(@OGUID+9,181393,530,1,1,2051.89,6831.638,177.0355,1.588249,0,0,0,1,120,255,1), +(@OGUID+10,181393,530,1,1,2072.185,6832.028,176.9799,1.588249,0,0,0,1,120,255,1), +(@OGUID+11,181401,530,1,1,2055.827,6759.792,173.2742,4.729844,0,0,0,1,120,255,1), +(@OGUID+12,181401,530,1,1,2066.258,6730.639,181.5167,1.518436,0,0,0,1,120,255,1), +(@OGUID+13,181401,530,1,1,2070.803,6759.671,173.2742,4.694937,0,0,0,1,120,255,1), +(@OGUID+14,181401,530,1,1,2066.148,6726.275,181.5531,4.747296,0,0,0,1,120,255,1), +(@OGUID+15,181401,530,1,1,1937.434,6838.64,177.4422,3.194002,0,0,0,1,120,255,1), +(@OGUID+16,181401,530,1,1,1941.395,6838.657,177.4772,0.01745246,0,0,0,1,120,255,1), +(@OGUID+17,181302,530,1,1,2023.801,6594.566,135.5013,2.949595,0,0,0,1,120,255,1), +(@OGUID+18,181302,530,1,1,2021.781,6590.525,135.2787,1.989672,0,0,0,1,120,255,1), +(@OGUID+19,181305,530,1,1,2018.895,6592.329,135.5139,6.126106,0,0,0,1,120,255,1), +(@OGUID+20,181306,530,1,1,2022.451,6595.768,135.6441,2.007128,0,0,0,1,120,255,1), +(@OGUID+21,181307,530,1,1,2018.828,6591.42,136.4855,1.658062,0,0,0,1,120,255,1), +(@OGUID+22,181355,530,1,1,2021.774,6603.31,136.6191,0.1745321,0,0,0,1,120,255,1), +(@OGUID+23,181355,530,1,1,2030.021,6607.951,137.7898,3.211419,0,0,0,1,120,255,1), +(@OGUID+24,181355,530,1,1,2049.479,6600.245,137.5444,1.186823,0,0,0,1,120,255,1), +(@OGUID+25,181355,530,1,1,2017.946,6573.733,135.3068,4.66003,0,0,0,1,120,255,1), +(@OGUID+26,181355,530,1,1,2051.807,6590.619,136.7025,5.201083,0,0,0,1,120,255,1), +(@OGUID+27,181355,530,1,1,2022.703,6566.989,133.5423,0.8552105,0,0,0,1,120,255,1), +(@OGUID+28,181355,530,1,1,2049.964,6570.623,135.499,0.5410506,0,0,0,1,120,255,1), +(@OGUID+29,181355,530,1,1,2046.616,6564.632,134.1706,5.846854,0,0,0,1,120,255,1), +(@OGUID+30,181355,530,1,1,2046.616,6564.632,134.1706,5.846854,0,0,0,1,120,255,1), +(@OGUID+31,188020,530,1,1,2035.179,6608.052,137.9502,0.7330382,0,0,0,1,120,255,1), +(@OGUID+32,188020,530,1,1,2045.668,6604.812,137.8742,1.518436,0,0,0,1,120,255,1), +(@OGUID+33,188020,530,1,1,2024.833,6565.631,133.425,1.378809,0,0,0,1,120,255,1), +(@OGUID+34,188020,530,1,1,2042.706,6563.491,133.4392,1.361356,0,0,0,1,120,255,1), +(@OGUID+35,188021,530,1,1,2021.064,6593.522,135.1495,6.03884,0,0,0,1,120,255,1), +(@OGUID+36,181605,530,1,1,2046.226,6579.709,135.2484,5.777041,0,0,0,1,120,255,1), +(@OGUID+37,187919,530,1,1,2019.803,6580.186,134.3619,1.937312,0,0,0,1,120,255,1); +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+37; +INSERT INTO `game_event_gameobject` (`eventEntry`,`guid`) VALUES +(1,@OGUID+0),(1,@OGUID+1),(1,@OGUID+2),(1,@OGUID+3),(1,@OGUID+4), +(1,@OGUID+5),(1,@OGUID+6),(1,@OGUID+7),(1,@OGUID+8),(1,@OGUID+9), +(1,@OGUID+10),(1,@OGUID+11),(1,@OGUID+12),(1,@OGUID+13),(1,@OGUID+14), +(1,@OGUID+15),(1,@OGUID+16),(1,@OGUID+17),(1,@OGUID+18),(1,@OGUID+19), +(1,@OGUID+20),(1,@OGUID+21),(1,@OGUID+22),(1,@OGUID+23),(1,@OGUID+24), +(1,@OGUID+25),(1,@OGUID+26),(1,@OGUID+27),(1,@OGUID+28),(1,@OGUID+29), +(1,@OGUID+30),(1,@OGUID+31),(1,@OGUID+32),(1,@OGUID+33),(1,@OGUID+34), +(1,@OGUID+35),(1,@OGUID+36),(1,@OGUID+37); + +-- Blades Edge Horde Mid Summer Festival Go Spawns +SET @OGUID := 21478; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+20; +INSERT INTO `gameobject` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`rotation0`,`rotation1`,`rotation2`,`rotation3`,`spawntimesecs`,`animprogress`,`state`) VALUES +(@OGUID+0,181302,530,1,1,2286.953,6131.723,135.8838,0.1047193,0,0,0,1,120,255,1), +(@OGUID+1,181302,530,1,1,2286.061,6134.23,136.0696,4.782203,0,0,0,1,120,255,1), +(@OGUID+2,181305,530,1,1,2290.526,6135.19,135.9771,4.590216,0,0,0,1,120,255,1), +(@OGUID+3,181306,530,1,1,2289.731,6131.177,135.6796,4.956738,0,0,0,1,120,255,1), +(@OGUID+4,181307,530,1,1,2286.542,6131.368,135.8867,0.5934101,0,0,0,1,120,255,1), +(@OGUID+5,181355,530,1,1,2258.801,6129.346,137.7461,0.8552105,0,0,0,1,120,255,1), +(@OGUID+6,181355,530,1,1,2268.304,6125.965,137.2221,4.66003,0,0,0,1,120,255,1), +(@OGUID+7,181355,530,1,1,2255.936,6152.005,139.28,5.846854,0,0,0,1,120,255,1), +(@OGUID+8,181355,530,1,1,2266.464,6158.563,138.4691,0.5410506,0,0,0,1,120,255,1), +(@OGUID+9,181355,530,1,1,2277.704,6161.832,137.9124,0.5934101,0,0,0,1,120,255,1), +(@OGUID+10,181355,530,1,1,2298.375,6131.026,135.5555,5.201083,0,0,0,1,120,255,1), +(@OGUID+11,181355,530,1,1,2303.753,6135.784,135.0607,1.186823,0,0,0,1,120,255,1), +(@OGUID+12,181355,530,1,1,2293.306,6163.847,136.1624,0.1745321,0,0,0,1,120,255,1), +(@OGUID+13,181355,530,1,1,2302.233,6162.095,135.2117,3.211419,0,0,0,1,120,255,1), +(@OGUID+14,188020,530,1,1,2258.107,6132.874,137.3437,3.298687,0,0,0,1,120,255,1), +(@OGUID+15,188020,530,1,1,2255.474,6148.87,138.3934,3.717554,0,0,0,1,120,255,1), +(@OGUID+16,188020,530,1,1,2304.146,6139.788,134.4674,0.05235888,0,0,0,1,120,255,1), +(@OGUID+17,188020,530,1,1,2303.354,6158.675,134.4655,6.126106,0,0,0,1,120,255,1), +(@OGUID+18,188021,530,1,1,2289.121,6132.534,135.8388,1.640607,0,0,0,1,120,255,1), +(@OGUID+19,181605,530,1,1,2285.147,6157.909,136.2808,5.777041,0,0,0,1,120,255,1), +(@OGUID+20,187955,530,1,1,2274.421,6133.031,136.9586,3.036838,0,0,0,1,120,255,1); +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+20; +INSERT INTO `game_event_gameobject` (`eventEntry`,`guid`) VALUES +(1,@OGUID+0),(1,@OGUID+1),(1,@OGUID+2),(1,@OGUID+3),(1,@OGUID+4), +(1,@OGUID+5),(1,@OGUID+6),(1,@OGUID+7),(1,@OGUID+8),(1,@OGUID+9), +(1,@OGUID+10),(1,@OGUID+11),(1,@OGUID+12),(1,@OGUID+13),(1,@OGUID+14), +(1,@OGUID+15),(1,@OGUID+16),(1,@OGUID+17),(1,@OGUID+18),(1,@OGUID+19), +(1,@OGUID+20); diff --git a/sql/updates/world/2012_06_26_00_world_sai.sql b/sql/updates/world/2012_06_26_00_world_sai.sql new file mode 100644 index 00000000000..c6fe75be1e5 --- /dev/null +++ b/sql/updates/world/2012_06_26_00_world_sai.sql @@ -0,0 +1,50 @@ +-- Ample Inspiration (12828) + +SET @GOB_UDED := 191553; -- U.D.E.D. Dispenser +SET @GOSSIP_MENU := 10211; +SET @NPC_MAMMOTH := 29402; -- Ironwool Mammoth +SET @NPC_MEAT_BUNNY := 29524; -- Mammoth Meat Bunny +SET @SPELL_THROW_UDED := 54577; -- Throw U.D.E.D. +SET @SPELL_GIVE_UDED := 54576; -- Forceitem U.D.E.D. +SET @SPELL_SPAWNER := 54581; -- Mammoth Explosion Spell Spawner +SET @SPELL_MAIN_MEAT := 57444; -- Summon Main Mammoth Meat +SET @SPELL_MEAT := 54625; -- Summon Mammoth Meat +SET @SPELL_MEAT_BUNNY1 := 54627; -- Quest - Mammoth Explosion Summon Object +SET @SPELL_MEAT_BUNNY2 := 54628; -- Quest - Mammoth Explosion Summon Object +SET @SPELL_MEAT_BUNNY3 := 54623; -- Quest - Mammoth Explosion Summon Object + +DELETE FROM `spell_script_names` WHERE `spell_id`=@SPELL_THROW_UDED; + +DELETE FROM `gossip_menu_option` WHERE `menu_id`=@GOSSIP_MENU; +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`) VALUES +(@GOSSIP_MENU,0,0,'<Retrieve a bomb from the dispenser.>',1,0,0,0,0,0,NULL); + +UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI' WHERE `entry`=@GOB_UDED; +DELETE FROM `smart_scripts` WHERE `source_type`=1 AND `entryorguid`=@GOB_UDED; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@GOB_UDED,1,0,1,62,0,100,0,@GOSSIP_MENU,0,0,0,72,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'On gossip - Close gossip'), +(@GOB_UDED,1,1,0,61,0,100,0,0,0,0,0,85,@SPELL_GIVE_UDED,0,0,0,0,0,7,0,0,0,0,0,0,0,'On link - Cast Forceitem U.D.E.D.'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@NPC_MAMMOTH; +UPDATE `creature_template` SET `flags_extra`=128,`AIName`='SmartAI' WHERE `entry`=@NPC_MEAT_BUNNY; +DELETE FROM `creature_ai_scripts` WHERE `creature_id`=@NPC_MAMMOTH; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid` IN (@NPC_MAMMOTH,@NPC_MEAT_BUNNY); +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +-- Ironwool Mammoth +(@NPC_MAMMOTH,0,0,0,0,0,100,0,1000,3000,7000,10000,11,56356,0,0,0,0,0,1,0,0,0,0,0,0,0,'Cast Ironwool Coat'), +(@NPC_MAMMOTH,0,1,2,8,0,100,0,@SPELL_THROW_UDED,0,0,0,11,@SPELL_SPAWNER,0,0,0,0,0,1,0,0,0,0,0,0,0,'On spellhit - Cast Mammoth Explosion Spell Spawner'), +(@NPC_MAMMOTH,0,2,0,61,0,100,0,0,0,0,0,41,500,0,0,0,0,0,1,0,0,0,0,0,0,0,'On link - Despawn'), +-- Mammoth Meat Bunny +(@NPC_MEAT_BUNNY,0,0,0,54,0,100,1,0,0,0,0,11,@SPELL_MEAT,0,0,0,0,0,1,0,0,0,0,0,0,0,'On spawn - Cast'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=@SPELL_SPAWNER; +INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES +(@SPELL_SPAWNER,@SPELL_MAIN_MEAT,0,'Mammoth Explosion Spell Spawner link to Summon Main Mammoth Meat'), +(@SPELL_SPAWNER,@SPELL_MEAT_BUNNY1,0,'Mammoth Explosion Spell Spawner link to Quest - Mammoth Explosion Summon Object'), +(@SPELL_SPAWNER,@SPELL_MEAT_BUNNY2,0,'Mammoth Explosion Spell Spawner link to Quest - Mammoth Explosion Summon Object'), +(@SPELL_SPAWNER,@SPELL_MEAT_BUNNY3,0,'Mammoth Explosion Spell Spawner link to Quest - Mammoth Explosion Summon Object'); + +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId`=17 AND `SourceEntry`=@SPELL_THROW_UDED) OR (`SourceTypeOrReferenceId`=15 AND `SourceGroup`=@GOSSIP_MENU); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(17,0,@SPELL_THROW_UDED,0,0,31,1,3,@NPC_MAMMOTH,0,0,0,'','Require Ironwool Mammoth as target'), +(15,@GOSSIP_MENU,0,0,0,9,0,12828,0,0,0,0,'','Show gossip if quest taken'); diff --git a/sql/updates/world/2012_06_26_01_world_creature.sql b/sql/updates/world/2012_06_26_01_world_creature.sql new file mode 100644 index 00000000000..1f0dfff0b04 --- /dev/null +++ b/sql/updates/world/2012_06_26_01_world_creature.sql @@ -0,0 +1,61 @@ +UPDATE `creature_template` SET `InhabitType`=4,`flags_extra`=128,`unit_flags`=0x2000000,`ScriptName`='npc_arthas_teleport_visual' WHERE `entry`=30298; -- Invisible Stalker (Float, Uninteractible, LargeAOI) + +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_icc_soul_missile'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(72585,'spell_icc_soul_missile'); + +DELETE FROM `creature_template_addon` WHERE `entry`=30298; +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`auras`) VALUES +(30298,0,0x0,0x1,''); -- Invisible Stalker (Float, Uninteractible, LargeAOI) + +SET @CGUID:=88653; +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+47; +INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`MovementType`) VALUES +(@CGUID+00,30298,631,15,1,4357.052,2769.421,356.1364,3.141593,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+01,30298,631,15,1,4308.511,2788.476,312.6750,3.263766,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+02,30298,631,15,1,4292.898,2793.981,310.8101,1.640610,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+03,30298,631,15,1,4306.854,2752.771,299.1382,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+04,30298,631,15,1,4317.904,2743.047,299.1328,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+05,30298,631,15,1,4319.273,2799.125,299.1442,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+06,30298,631,15,1,4312.229,2735.825,299.1255,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+07,30298,631,15,1,4295.093,2743.372,299.1294,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+08,30298,631,15,1,4342.194,2719.366,312.6750,4.799655,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+09,30298,631,15,1,4284.044,2753.073,299.1465,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+10,30298,631,15,1,4331.980,2730.547,299.1442,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+11,30298,631,15,1,4331.183,2813.701,299.1328,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+12,30298,631,15,1,4292.952,2807.547,299.1372,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+13,30298,631,15,1,4284.188,2735.236,299.1377,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+14,30298,631,15,1,4323.733,2819.085,299.1255,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+15,30298,631,15,1,4308.430,2717.113,299.1333,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+16,30298,631,15,1,4304.886,2822.116,299.1333,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+17,30298,631,15,1,4336.049,2703.986,310.8101,3.176499,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+18,30298,631,15,1,4430.367,2800.603,299.1377,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+19,30298,631,15,1,4432.948,2749.438,307.1431,4.799655,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+20,30298,631,15,1,4340.452,2825.148,299.1382,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+21,30298,631,15,1,4322.498,2704.592,299.1372,0.820304,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+22,30298,631,15,1,4380.124,2816.074,312.6750,6.265732,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+23,30298,631,15,1,4330.582,2836.512,299.1294,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+24,30298,631,15,1,4418.384,2734.435,299.1372,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+25,30298,631,15,1,4429.439,2782.781,299.1465,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+26,30298,631,15,1,4380.205,2727.930,299.1328,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+27,30298,631,15,1,4371.056,2716.414,299.1382,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+28,30298,631,15,1,4399.571,2746.277,312.6750,4.799655,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+29,30298,631,15,1,4382.944,2808.139,299.1442,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+30,30298,631,15,1,4389.698,2694.647,299.1377,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+31,30298,631,15,1,4336.760,2689.307,307.1431,3.176499,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+32,30298,631,15,1,4391.995,2742.610,299.1442,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+33,30298,631,15,1,4322.008,2847.075,299.1377,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+34,30298,631,15,1,4396.241,2794.807,299.1328,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+35,30298,631,15,1,4380.467,2834.892,310.8101,6.265732,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+36,30298,631,15,1,4337.707,2850.425,299.1465,5.567600,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+37,30298,631,15,1,4392.823,2719.806,299.1255,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+38,30298,631,15,1,4406.686,2784.457,299.1382,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+39,30298,631,15,1,4381.028,2705.133,299.1294,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+40,30298,631,15,1,4371.884,2693.614,299.1465,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+41,30298,631,15,1,4405.702,2806.464,299.1255,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+42,30298,631,15,1,4418.314,2747.997,310.8101,4.799655,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+43,30298,631,15,1,4380.639,2849.595,307.1431,6.265732,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+44,30298,631,15,1,4393.958,2833.470,299.1372,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+45,30298,631,15,1,4406.588,2719.758,299.1333,2.443461,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+46,30298,631,15,1,4407.252,2820.139,299.1333,3.909538,7200,0,0), -- Invisible Stalker (Float, Uninteractible, LargeAOI) +(@CGUID+47,30298,631,15,1,4418.995,2793.132,299.1294,3.909538,7200,0,0); -- Invisible Stalker (Float, Uninteractible, LargeAOI) diff --git a/sql/updates/world/2012_06_26_02_world_creature_loot_template.sql b/sql/updates/world/2012_06_26_02_world_creature_loot_template.sql new file mode 100644 index 00000000000..3a704e61bcf --- /dev/null +++ b/sql/updates/world/2012_06_26_02_world_creature_loot_template.sql @@ -0,0 +1,6 @@ +-- Replace Furious Weapon drop with drop that should be in the Cache of Living Stone +UPDATE `reference_loot_template` SET `item` =45695 WHERE (`entry` =34361 AND `item` =45965); +-- add missing Recipe: Mighty Shadow Protection Potion on Cultist Shard Watcher +DELETE FROM `creature_loot_template` WHERE `entry`=32349 AND `item`=44568; +INSERT INTO `creature_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES +(32349,44568,0.5,1,0,1,1); diff --git a/sql/updates/world/2012_06_27_00_world_spell_script_names.sql b/sql/updates/world/2012_06_27_00_world_spell_script_names.sql new file mode 100644 index 00000000000..8210225de6e --- /dev/null +++ b/sql/updates/world/2012_06_27_00_world_spell_script_names.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN (50546); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(50546,'spell_q12066_bunny_kill_credit'); diff --git a/sql/updates/world/2012_06_27_01_world_game_graveyard_zone.sql b/sql/updates/world/2012_06_27_01_world_game_graveyard_zone.sql new file mode 100644 index 00000000000..973a1dc5296 --- /dev/null +++ b/sql/updates/world/2012_06_27_01_world_game_graveyard_zone.sql @@ -0,0 +1,3 @@ +-- fix graveyard for shattered halls, alliance to honor hold, horde to thrallmar, not the other way around +UPDATE `game_graveyard_zone` SET `faction`=67 WHERE `id`=919 AND `ghost_zone`=3714; +UPDATE `game_graveyard_zone` SET `faction`=469 WHERE `id`=920 AND `ghost_zone`=3714; diff --git a/sql/updates/world/2012_07_01_00_world_creature_text.sql b/sql/updates/world/2012_07_01_00_world_creature_text.sql new file mode 100644 index 00000000000..f59663ceab5 --- /dev/null +++ b/sql/updates/world/2012_07_01_00_world_creature_text.sql @@ -0,0 +1,66 @@ +DELETE FROM `script_texts` WHERE entry IN (-1534019, -1534020, -1534021, -1534022, -1534023, -1534024, -1534025, -1534026, -1534027, -1534028, -1534029 , -1534030); + +-- Anetheron +DELETE FROM `creature_text` WHERE `entry`=17808; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17808,0,0, 'The clock... is still... ticking.',14,0,100,0,0,10982, 'Anetheron - SAY_ONDEATH'), +(17808,1,0, 'Your hopes are lost!',14,0,100,0,0,10981, 'Anetheron - SAY_ONSLAY1'), +(17808,1,1, 'Scream for me!',14,0,100,0,0,11038, 'Anetheron - SAY_ONSLAY2'), +(17808,1,2, 'Pity, no time for a slow death!',14,0,100,0,0,11039, 'Anetheron - SAY_ONSLAY3'), +(17808,2,0, 'The swarm is eager to feed!',14,0,100,0,0,10979, 'Anetheron - SAY_SWARM1'), +(17808,2,1, 'Pestilence upon you!',14,0,100,0,0,11037, 'Anetheron - SAY_SWARM2'), +(17808,3,0, 'You look tired...',14,0,100,0,0,10978, 'Anetheron - SAY_SLEEP1'), +(17808,3,1, 'Sweet dreams...',14,0,100,0,0,11545, 'Anetheron - SAY_SLEEP2'), +(17808,4,0, 'Let fire rain from above!',14,0,100,0,0,10980, 'Anetheron - SAY_INFERNO1'), +(17808,4,1, 'Earth and sky shall burn!',14,0,100,0,0,11036, 'Anetheron - SAY_INFERNO2'), +(17808,5,0, 'You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!',14,0,100,0,0,10977, 'Anetheron - SAY_ONAGGRO'); + +-- Azgalor +DELETE FROM `creature_text` WHERE `entry`=17842; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17842,0,0, 'Your time is almost... up',14,0,100,0,0,11002, 'Azgalor - SAY_ONDEATH'), +(17842,1,0, 'Reesh, hokta!',14,0,100,0,0,11001, 'Azgalor - SAY_ONSLAY1'), +(17842,1,1, 'Don''t fight it',14,0,100,0,0,11048, 'Azgalor - SAY_ONSLAY2'), +(17842,1,2, 'No one is going to save you',14,0,100,0,0,11047, 'Azgalor - SAY_ONSLAY3'), +(17842,2,0, 'Just a taste... of what awaits you',14,0,100,0,0,11046, 'Azgalor - SAY_DOOM1'), +(17842,2,1, 'Suffer you despicable insect!',14,0,100,0,0,11000, 'Azgalor - SAY_DOOM2'), +(17842,3,0, 'Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!',14,0,100,0,0,10999, 'Azgalor - SAY_ONAGGRO'); + +-- Kazrogal +DELETE FROM `creature_text` WHERE `entry`=17888; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17888,0,0, 'Shaza-Kiel!',14,0,100,0,0,11017, 'Kazrogal - SAY_ONSLAY1'), +(17888,0,1, 'You... are nothing!',14,0,100,0,0,11053, 'Kazrogal - SAY_ONSLAY2'), +(17888,0,2, 'Miserable nuisance!',14,0,100,0,0,11054, 'Kazrogal - SAY_ONSLAY3'), +(17888,1,0, 'Your death will be a painful one.',14,0,100,0,0,11016, 'Kazrogal - SAY_MARK1'), +(17888,1,1, 'You... are marked.',14,0,100,0,0,11052, 'Kazrogal - SAY_MARK2'), +(17888,2,0, 'Cry for mercy! Your meaningless lives will soon be forfeit.',14,0,100,0,0,11015, 'Kazrogal - SAY_ONAGGRO'); + +-- Rage Winterchill +DELETE FROM `creature_text` WHERE `entry`=17767; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17767,0,0, 'You have won this battle, but not... the... war',14,0,100,0,0,11026, 'Rage Winterchill - SAY_ONDEATH'), +(17767,1,0, 'All life must perish!',14,0,100,0,0,11025, 'Rage Winterchill - SAY_ONSLAY1'), +(17767,1,1, 'Victory to the Legion!',14,0,100,0,0,11057, 'Rage Winterchill - SAY_ONSLAY2'), +(17767,2,0, 'Crumble and rot!',14,0,100,0,0,11023, 'Rage Winterchill - SAY_DECAY1'), +(17767,2,1, 'Ashes to ashes, dust to dust',14,0,100,0,0,11055, 'Rage Winterchill - SAY_DECAY2'), +(17767,3,0, 'Succumb to the icy chill... of death!',14,0,100,0,0,11024, 'Rage Winterchill - SAY_NOVA1'), +(17767,3,1, 'It will be much colder in your grave',14,0,100,0,0,11058, 'Rage Winterchill - SAY_NOVA2'), +(17767,4,0, 'The Legion''s final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!',14,0,100,0,0,11022, 'Rage Winterchill - SAY_ONAGGRO'); + +-- Archimonde +DELETE FROM `creature_text` WHERE `entry`=17968; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(17968,1,0, 'Your resistance is insignificant.',14,0,100,0,0,10987, 'Archimonde - SAY_AGGRO'), +(17968,2,0, 'This world will burn!',14,0,100,0,0,10990, 'Archimonde - SAY_DOOMFIRE1'), +(17968,2,1, 'Manach sheek-thrish!',14,0,100,0,0,11041, 'Archimonde - SAY_DOOMFIRE2'), +(17968,3,0, 'A-kreesh!',14,0,100,0,0,11041, 'Archimonde - SAY_AIR_BURST1'), +(17968,3,1, 'Away vermin!',14,0,100,0,0,10989, 'Archimonde - SAY_AIR_BURST2'), +(17968,4,0, 'All creation will be devoured!',14,0,100,0,0,11044, 'Archimonde - SAY_SLAY1'), +(17968,4,1, 'Your soul will languish for eternity.',14,0,100,0,0,10991, 'Archimonde - SAY_SLAY12'), +(17968,4,2, 'I am the coming of the end!',14,0,100,0,0,11045, 'Archimonde - SAY_SLAY3'), +(17968,5,0, 'At last it is here. Mourn and lament the passing of all you have ever known and all that would have been! Akmin-kurai!',14,0,100,0,0,10993, 'Archimonde - SAY_ENRAGE'), +(17968,6,0, 'No, it cannot be! Nooo!',14,0,100,0,0,10992, 'Archimonde - SAY_DEATH'), +(17968,7,0, 'You are mine now.',14,0,100,0,0,10988, 'Archimonde - SAY_SOUL_CHARGE1'), +(17968,7,1, 'Bow to my will.',14,0,100,0,0,11042, 'Archimonde - SAY_SOUL_CHARGE2'); + diff --git a/sql/updates/world/2012_07_02_00_world_creature_onkill_reputation.sql b/sql/updates/world/2012_07_02_00_world_creature_onkill_reputation.sql new file mode 100644 index 00000000000..a9565d36934 --- /dev/null +++ b/sql/updates/world/2012_07_02_00_world_creature_onkill_reputation.sql @@ -0,0 +1,4 @@ +-- Add 10 reputation gaining from killing NPC Monstrous Kaliri towards Sha'tari Skyguard +DELETE FROM `creature_onkill_reputation` WHERE `creature_id`=23051; +INSERT INTO `creature_onkill_reputation` (`creature_id`,`RewOnKillRepFaction1`,`MaxStanding1`,`RewOnKillRepValue1`) VALUES +(23051,1031,7,10); diff --git a/sql/updates/world/2012_07_02_01_world_sai.sql b/sql/updates/world/2012_07_02_01_world_sai.sql new file mode 100644 index 00000000000..323d9bddcb2 --- /dev/null +++ b/sql/updates/world/2012_07_02_01_world_sai.sql @@ -0,0 +1,7 @@ +-- Add SAI for Dark Ritualist <Cult of the Damned> ID: 34734 // timings are taken from other script finds +SET @Ritualist := 34734; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@Ritualist; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@Ritualist; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@Ritualist,0,0,0,0,0,100,0,3000,3000,8000,14000,11,32000,0,0,0,0,0,2,0,0,0,0,0,0,0,'Dark Ritualist - IC - Cast Mind Seer'), +(@Ritualist,0,1,0,0,0,100,0,8000,17300,17300,17300,11,32026,0,0,0,0,0,2,0,0,0,0,0,0,0,'Dark Ritualist - IC - Cast Pain Strike'); diff --git a/sql/updates/world/2012_07_02_02_world_sai.sql b/sql/updates/world/2012_07_02_02_world_sai.sql new file mode 100644 index 00000000000..6b6b0eb587c --- /dev/null +++ b/sql/updates/world/2012_07_02_02_world_sai.sql @@ -0,0 +1,189 @@ +-- Fix quest the Air Stands Still ID: 13125 + some lurking around mobs SAIs +-- Set guids: +SET @NPC := 43480; -- Underking Talonox in phase 2, in phase 128->@NPC+1 +SET @PATH := @NPC * 10; +-- @NPC+2 Salranax phase 2, +3 in phase 128 +-- @NPC+4 High Priest in phase 2 and +5 in 128 +-- Add (Salranax the Flesh Render, High Priest Yath'amon and Underking Talonox -- One for each phase they are in /used @qaywsx phase data/ ) +DELETE FROM `creature` WHERE `id` IN (30829, 30830, 30831); +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `MovementType`) VALUES +(@NPC+2,30829,571,1,2,6839.024902,594.444946,427.229523,4.5,300,0,0,0), +(@NPC+4,30831,571,1,2,6869.477539,423.287720,471.783722,1.066242,300,0,0,0), +(@NPC,30830,571,1,2,7169.797363,664.115479,492.375793,1.129528,300,0,0,0), +(@NPC+3,30829,571,1,128,6839.024902,594.444946,427.229523,4.5,300,0,0,0), +(@NPC+5,30831,571,1,128,6869.477539,423.287720,471.783722,1.066242,300,0,0,0), +(@NPC+1,30830,571,1,128,7169.797363,664.115479,492.375793,1.129528,300,0,0,0); +-- Salranax the Flesh Render SAI +UPDATE `creature_template` SET `faction_A`=2068, `faction_H`=2068, `mindmg`=240, `maxdmg`=270, `mechanic_immune_mask`=10685, `scale`=1.2 WHERE `entry`=30829; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=30829; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30829; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30829,0,1,0,8,0,100,1,57906,0,0,0,12,30840,4,5000,0,0,0,1,0,0,0,0,0,0,0,'Salranax the Flesh Render - Summons Munch on hit by horn'), +(30829,0,2,0,8,0,100,1,57906,0,0,0,49,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'On spellhit set aggro'), +(30829,0,3,0,4,0,100,1,0,0,0,0,11,18100,1,0,0,0,0,1,0,0,0,0,0,0,0,'On aggro - Frost Armor'), +(30829,0,4,0,0,0,100,0,2000,6000,4000,8000,11,15242,1,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Cast Fireball'), +(30829,0,5,0,0,0,100,0,15000,20000,15000,20000,11,15244,0,0,0,0,0,0,0,0,0,0,0,0,0,'Combat - Cast Cone of Cold'), +(30829,0,6,0,0,0,100,0,25000,26000,25000,26000,11,15122,1,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Cast Counterspell'), +(30829,0,7,0,6,0,100,0,0,0,0,0,78,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Reset script on death'), +(30829,0,8,0,25,0,100,0,0,0,0,0,28,18100,0,0,0,0,0,1,0,0,0,0,0,0,0,'Remove buff on respawn'); +-- Add SAI for Munch + weapon +UPDATE `creature_template` SET `faction_A`=290,`faction_H`=290, `equipment_id`=30840 WHERE`entry`=30840; +DELETE FROM `creature_equip_template` WHERE `entry`=30840; +INSERT INTO `creature_equip_template` VALUES +(30840,44948,0,0); +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=30840; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30840; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30840,0,1,0,4,0,100,1,0,0,0,0,12,30850,3,2000,0,0,0,1,0,0,0,0,0,0,0,'Summons portal'), +(30840,0,2,0,4,0,100,1,0,0,0,0,1,1,1000,0,0,0,0,1,0,0,0,0,0,0,0,'Welcome text'), +(30840,0,3,0,4,0,100,1,0,0,0,0,1,2,1000,0,0,0,0,1,0,0,0,0,0,0,0,'Welcome text 2'), +(30840,0,4,0,4,0,100,1,0,0,0,0,12,30851,4,1000,0,0,0,1,0,0,0,0,0,0,0,'Summons Melt'), +(30840,0,5,0,0,0,100,0,4000,6000,19000,20000,11,52372,2,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Icy Touch'), +(30840,0,6,0,0,0,100,0,4000,8000,10000,11000,11,52373,2,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Plague Strike'), +(30840,0,7,0,0,0,100,0,4000,7000,2000,3000,11,52374,0,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Blood Strike'), +(30840,0,8,0,5,0,100,1,0,0,0,0,1,3,1000,0,0,0,0,1,0,0,0,0,0,0,0,'Text 3'), +(30840,0,9,0,5,0,100,1,0,0,0,0,12,30850,2,40000,0,0,0,8,0,0,0,6831.7270020,585.404990,427.168011,0.8,'On out of combat opens portal'); +-- Munch's Texts +DELETE FROM `creature_text` WHERE `entry`=30840; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(30840,1,1,'Say hello to my little friend!',12,0,100,0,0,0,'Munch arrival'), +(30840,2,2,'Arise Melt!',12,0,100,0,0,0,'Summon Melts'), +(30840,3,3,'We are done here. I am out.',12,0,100,0,0,0,'Munch oppening portal'); +-- Switch Melts into helping faction +UPDATE `creature_template` SET `faction_A`=290, `faction_H`=290 WHERE `entry`=30851; +-- 2/3 +-- High Priest Yath'amon SAI +UPDATE `creature_template` SET `faction_A`=2068, `faction_H`=2068, `mindmg`=240, `maxdmg`=300,`mechanic_immune_mask`=10685, `scale`=1.2 WHERE `entry`=30831; -- Mana_mod /WDB/ should be exactly 40, if want insert it +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=30831; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30831; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30831,0,1,0,8,0,100,1,57906,0,0,0,12,30839,4,5000,0,0,0,1,0,0,0,0,0,0,0,'Summons Jayde on hit by horn'), +(30831,0,2,0,8,0,100,1,57906,0,0,0,49,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'On spellhit set aggro'), +(30831,0,3,0,0,0,100,0,2000,3000,6000,8000,11,61705,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Venomous Bite'), -- the spell only targets players as it should +(30831,0,4,0,0,0,100,0,2000,7000,10000,20000,11,4962,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Encasing Webs'), +(30831,0,5,0,0,0,100,0,2000,7000,8000,20000,11,38243,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Mind flay Webs'), +(30831,0,6,0,0,0,100,0,10000,15000,30000,35000,11,34322,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Psychic Scream'), +(30831,0,7,0,6,0,100,0,0,0,0,0,78,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Reset script on death'); +-- Add SAI for Jayde + weapon +UPDATE `creature_template` SET `faction_A`=290,`faction_H`=290, `mechanic_immune_mask`=20, `equipment_id`=30839,`scale`=1 WHERE `entry`=30839; +DELETE FROM `creature_equip_template` WHERE `entry`=30839; +INSERT INTO `creature_equip_template` VALUES +(30839,44926,0,0); +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=30839; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30839; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30839,0,1,0,4,0,100,1,0,0,0,0,12,30852,3,2000,0,0,0,1,0,0,0,0,0,0,0,'Summons portal'), +(30839,0,2,0,4,0,100,1,0,0,0,0,1,1,1000,0,0,0,0,1,0,0,0,0,0,0,0,'Welcome text'), +(30839,0,3,0,0,0,100,0,4000,6000,19000,20000,11,52372,2,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Icy Touch'), +(30839,0,4,0,0,0,100,0,4000,8000,10500,11000,11,52373,2,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Plague Strike'), +(30839,0,5,0,0,0,100,0,4000,7000,2000,2500,11,52374,0,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Blood Strike'), +(30839,0,6,0,5,0,100,1,0,0,0,0,1,2,1000,0,0,0,0,1,0,0,0,0,0,0,0,'Text 2'), +(30839,0,7,0,5,0,100,1,0,0,0,0,12,30852,2,40000,0,0,0,8,0,0,0,6865.674316,414.657349,472.700226,1.185621,'On out of combat opens portal'); +-- Jayde Texts +DELETE FROM `creature_text` WHERE `entry`=30839; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(30839,1,1,'Too weak to finish your own battles? Very well then...',12,0,100,0,0,0,'Jayde arrival'), +(30839,2,2,'Anything else you need help with before I go? Right, I thought not...',12,0,100,0,0,0,'Oppens portal and dissapears'); +-- 3/3 +-- Underking Talonox SAI +UPDATE `creature_template` SET `exp`=2,`faction_A`=2068,`faction_H`=2068,`InhabitType`=1,`mindmg`=320, `maxdmg`=330, `minlevel`=79, `maxlevel`=79, `mechanic_immune_mask`=10685 WHERE `entry`=30830; +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=30830; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30830; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30830,0,1,0,8,0,100,1,57906,0,0,0,12,30838,4,5000,0,0,0,1,0,0,0,0,0,0,0,'Summons Mograine on hit by horn'), +(30830,0,2,0,8,0,100,1,57906,0,0,0,49,0,0,0,0,0,0,7,0,0,0,0,0,0,0,'On spellhit set aggro'), +(30830,0,3,0,0,0,100,0,1000,2000,2000,7000,11,60802,1,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Mandible Crush'), +(30830,0,4,0,0,0,100,0,1500,2000,10000,15000,11,50283,0,0,0,0,0,0,0,2,0,0,0,0,0,'Combat - Blinding Swarm'), +(30830,0,5,0,6,0,100,0,0,0,0,0,78,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Reset script on death'); +-- Add SAI for Mograine + weapon +UPDATE `creature_template` SET `health_mod`=2401.3,`mana_mod`=1599.9,`unit_class`=2,`flags_extra`=131072, `faction_A`=290,`faction_H`=290, `minlevel`=83, `maxlevel`=83, `mindmg`=340, `maxdmg`=420, `equipment_id`=30838 WHERE`entry`=30838; +DELETE FROM `creature_equip_template` WHERE `entry`=30838; +INSERT INTO `creature_equip_template` VALUES +(30838,39344,39344,0); +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`=30838; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30838; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30838,0,1,0,4,0,100,1,0,0,0,0,12,30850,3,2000,0,0,0,1,0,0,0,0,0,0,0,'Summons portal'), +(30838,0,2,0,4,0,100,1,0,0,0,0,1,1,1000,0,0,0,0,1,0,0,0,0,0,0,0,'Welcome text'), +(30838,0,3,0,0,0,100,0,4000,6000,19000,20000,11,52372,2,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Icy Touch'), +(30838,0,4,0,0,0,100,0,4000,8000,10000,11000,11,52373,2,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Plague Strike'), +(30838,0,5,0,0,0,100,0,4000,7000,5000,5000,11,49020,0,0,0,0,0,0,0,0,0,0,0,0,0,'Combat Use - Obliterete'), +(30838,0,6,0,5,0,100,1,0,0,0,0,1,2,1000,0,0,0,0,1,0,0,0,0,0,0,0,'Text 2'), +(30838,0,7,0,5,0,100,1,0,0,0,0,12,30841,2,40000,0,0,0,8,0,0,0,7190.895508,633.476440,488.506317,1.014229,'On out of combat opens portal'); +-- Mograine Texts +DELETE FROM `creature_text` WHERE `entry`=30838; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(30838,1,1,'You challenge death itself! Come then, "King." Face the might of Mograine!',12,0,100,0,0,0,'Mograine"s arrival'), +(30838,2,1,'I will see you back at the Valley of Echoes. Suffer well, ally.',12,0,100,0,0,0,'Opens portal'); +-- Underking pathing for phase 2 +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=7169.797363,`position_y`=664.115479,`position_z`=492.375793, `orientation`=1.129528 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC,@PATH,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7169.797363,664.115479,490.875793,0,0,0,100,0), +(@PATH,2,7196.977051,627.252869,488.591461,0,0,0,100,0), +(@PATH,3,7231.509277,640.110535,484.103490,0,0,0,100,0), +(@PATH,4,7207.646484,677.654114,491.592255,0,0,0,100,0); +-- Underking pathing for phase 128 +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=7169.797363,`position_y`=664.115479,`position_z`=492.375793, `orientation`=1.129528 WHERE `guid`=@NPC+1; +DELETE FROM `creature_addon` WHERE `guid`=@NPC+1; +INSERT INTO `creature_addon` (`guid`,`path_id`,`bytes2`,`mount`,`auras`) VALUES (@NPC+1,@PATH,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`delay`,`move_flag`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,7169.797363,664.115479,490.875793,0,0,0,100,0), +(@PATH,2,7196.977051,627.252869,488.591461,0,0,0,100,0), +(@PATH,3,7231.509277,640.110535,484.103490,0,0,0,100,0), +(@PATH,4,7207.646484,677.654114,491.592255,0,0,0,100,0); +-- 0/0 Thanks to Nay for helping with Gate's data. +-- Add missing data for the teleport spell +DELETE FROM `spell_target_position` WHERE `id`=57897; -- there was none, but just in case +INSERT INTO `spell_target_position` (`id`,`target_map`,`target_position_x`,`target_position_y`,`target_position_z`,`target_orientation`) VALUES +(57897,571,6383.445801,229.091522,397.031127,1.660376); +-- Add info for Munch's Death Gate spell click +UPDATE `creature_template` SET `unit_flags`=567296,`exp`=2,`speed_run`=1,`minlevel`=80, `maxlevel`=80,`AIName`="SmartAI",`npcflag`=16777216 WHERE `entry`=30850; +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=30850; +INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`cast_flags`,`user_type`) VALUES +(30850,57897,2,1); +-- Addon data for creature 30850 (Death Gate (Munch)) +DELETE FROM `creature_template_addon` WHERE `entry`=30850; +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(30850,0,0,1,0, NULL); -- Death Gate (Munch) +-- Add info for Jayde's Death Gate spell click +UPDATE `creature_template` SET `exp`=2,`speed_run`=1,`unit_flags`=567296,`minlevel`=80, `maxlevel`=80,`unit_flags`=567296, `speed_run`=1,`AIName`="SmartAI",`npcflag`=16777216 WHERE `entry`=30852; +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=30852; +INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`cast_flags`,`user_type`) VALUES +(30852,57897,2,1); +-- Model data 27346 (creature 30852 (Death Gate (Jayde))) +UPDATE `creature_model_info` SET `bounding_radius`=1.35,`combat_reach`=1.35,`gender`=2 WHERE `modelid`=27346; -- Death Gate (Jayde) +-- Addon data for creature 30852 (Death Gate (Jayde)) +DELETE FROM `creature_template_addon` WHERE `entry`=30852; +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(30852,0,0,1,0, NULL); -- Death Gate (Jayde) +-- Add info for Mograine's Death Gate spell click +UPDATE `creature_template` SET `unit_flags`=567296,`exp`=2,`speed_run`=1,`minlevel`=80, `maxlevel`=80,`AIName`="SmartAI",`npcflag`=16777216 WHERE `entry`=30841; +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry`=30841; +INSERT INTO `npc_spellclick_spells` (`npc_entry`,`spell_id`,`cast_flags`,`user_type`) VALUES +(30841,57897,2,1); +-- Addon data for creature 30841 (Death Gate (Mograine)) +DELETE FROM `creature_template_addon` WHERE `entry`=30841; +INSERT INTO `creature_template_addon` (`entry`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(30841,0,0,1,0, NULL); -- Death Gate (Mograine) +-- Set SAI for Forgotten Depths Priest - ID: 30203 +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= 30203; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30203; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30203,0,1,0,0,0,100,0,2000,7000,10000,15000,11,4962,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Encasing Webs'), +(30203,0,2,0,0,0,100,0,2000,7000,6000,12000,11,32000,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Mind flay Webs'); +-- Set SAI for Forgotten Depths Priest - ID: 30543 +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= 30543; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=30543; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(30543,0,1,0,0,0,100,0,2000,7000,10000,15000,11,4962,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Encasing Webs'), +(30543,0,2,0,0,0,100,0,2000,7000,6000,12000,11,32000,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Mind flay Webs'); +-- Set SAI for Forgotten Depths Priest - ID: 31037 +UPDATE `creature_template` SET `AIName`= 'SmartAI' WHERE `entry`= 31037; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=31037; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(31037,0,1,0,0,0,100,0,2000,7000,10000,15000,11,4962,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Encasing Webs'), +(31037,0,2,0,0,0,100,0,2000,7000,6000,12000,11,32000,0,0,0,0,0,2,0,0,0,0,0,0,0,'Combat - Mind flay Webs'); diff --git a/sql/updates/world/2012_07_02_03_world_gossip.sql b/sql/updates/world/2012_07_02_03_world_gossip.sql new file mode 100644 index 00000000000..0c158aa7511 --- /dev/null +++ b/sql/updates/world/2012_07_02_03_world_gossip.sql @@ -0,0 +1,17 @@ +UPDATE `creature_template` SET `gossip_menu_id`=8074 WHERE `entry`=19466; -- Exarch Orelis +UPDATE `creature_template` SET `gossip_menu_id`=8216 WHERE `entry`=20920; -- Magister Theledorn +UPDATE `creature_template` SET `gossip_menu_id`=8661 WHERE `entry`=21112; -- Bossi Pentapiston <Engineering Supplies> + +DELETE FROM `gossip_menu` WHERE (`entry`=8074 AND `text_id`=9980) OR +(`entry`=8216 AND `text_id`=10211) OR +(`entry`=8304 AND `text_id`=10360) OR +(`entry`=8370 AND `text_id`=10444) OR +(`entry`=8385 AND `text_id`=10466) OR +(`entry`=8661 AND `text_id`=10889); +INSERT INTO `gossip_menu` (`entry`, `text_id`) VALUES +(8074, 9980), -- 19466 +(8216, 10211), -- 20920 +(8304, 10360), -- 21461 +(8370, 10444), -- 21755 +(8385, 10466), -- 21824 +(8661, 10889); -- 21112 diff --git a/sql/updates/world/2012_07_02_04_world_spell_script_names.sql b/sql/updates/world/2012_07_02_04_world_spell_script_names.sql new file mode 100644 index 00000000000..9054ea7ba82 --- /dev/null +++ b/sql/updates/world/2012_07_02_04_world_spell_script_names.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_script_names` WHERE `spell_id`=49838; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(49838, "spell_gen_stop_time");
\ No newline at end of file diff --git a/sql/updates/world/2012_07_04_world_spell_script_names.sql b/sql/updates/world/2012_07_04_world_spell_script_names.sql new file mode 100644 index 00000000000..9e157261409 --- /dev/null +++ b/sql/updates/world/2012_07_04_world_spell_script_names.sql @@ -0,0 +1,2 @@ +DELETE FROM `spell_script_names` WHERE `spell_id` IN (52941, -52941); +INSERT INTO `spell_script_names` VALUES (52941, 'spell_q12735_song_of_cleansing');
\ No newline at end of file diff --git a/sql/updates/world/2012_07_05_00_world_item_template_addon_434.sql b/sql/updates/world/2012_07_05_00_world_item_template_addon_434.sql new file mode 100644 index 00000000000..ae3f59185b4 --- /dev/null +++ b/sql/updates/world/2012_07_05_00_world_item_template_addon_434.sql @@ -0,0 +1 @@ +ALTER TABLE `item_template` ADD `FlagsCu` INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `Id`; diff --git a/src/server/collision/BoundingIntervalHierarchy.h b/src/server/collision/BoundingIntervalHierarchy.h index ea70fc3e322..a4bbe21006a 100755 --- a/src/server/collision/BoundingIntervalHierarchy.h +++ b/src/server/collision/BoundingIntervalHierarchy.h @@ -128,7 +128,7 @@ class BIH delete[] dat.primBound; delete[] dat.indices; } - uint32 primCount() { return objects.size(); } + uint32 primCount() const { return objects.size(); } template<typename RayCallback> void intersectRay(const Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const @@ -400,7 +400,8 @@ class BIH void buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats); - void createNode(std::vector<uint32> &tempTree, int nodeIndex, uint32 left, uint32 right) { + void createNode(std::vector<uint32> &tempTree, int nodeIndex, uint32 left, uint32 right) const + { // write leaf node tempTree[nodeIndex + 0] = (3 << 30) | left; tempTree[nodeIndex + 1] = right - left + 1; diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp index e7693a70de4..3bfed7d322d 100644 --- a/src/server/collision/Maps/TileAssembler.cpp +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -312,7 +312,7 @@ namespace VMAP // write WorldModel WorldModel model; model.setRootWmoID(raw_model.RootWMOID); - if (raw_model.groupsArray.size()) + if (!raw_model.groupsArray.empty()) { std::vector<GroupModel> groupsArray; diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp index 84c736c22e8..8b63620e783 100644 --- a/src/server/collision/Models/GameObjectModel.cpp +++ b/src/server/collision/Models/GameObjectModel.cpp @@ -176,7 +176,7 @@ bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool Sto Ray modRay(p, iInvRot * ray.direction()); float distance = MaxDist * iInvScale; bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit); - if(hit) + if (hit) { distance *= iScale; MaxDist = distance; diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp index b818232fb32..b4f3f73fc98 100644 --- a/src/server/collision/Models/WorldModel.cpp +++ b/src/server/collision/Models/WorldModel.cpp @@ -42,7 +42,7 @@ namespace VMAP const Vector3 p(ray.direction().cross(e2)); const float a = e1.dot(p); - if (abs(a) < EPS) { + if (fabs(a) < EPS) { // Determinant is ill-conditioned; abort early return false; } diff --git a/src/server/collision/RegularGrid.h b/src/server/collision/RegularGrid.h index 2867b29cfc1..00d7b0cd209 100644 --- a/src/server/collision/RegularGrid.h +++ b/src/server/collision/RegularGrid.h @@ -176,7 +176,7 @@ public: } if (cell == last_cell) break; - if(tMaxX < tMaxY) + if (tMaxX < tMaxY) { tMaxX += tDeltaX; cell.x += stepX; diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h index f4555649210..fbc8675cc47 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.h +++ b/src/server/game/AI/CoreAI/GameObjectAI.h @@ -53,7 +53,8 @@ class GameObjectAI virtual uint64 GetData64(uint32 /*id*/) { return 0; } virtual void SetData(uint32 /*id*/, uint32 /*value*/) {} virtual void OnGameEvent(bool /*start*/, uint16 /*eventId*/) {} - virtual void OnStateChanged(uint32 /*state*/, Unit* /*unit*/) { } + virtual void OnStateChanged(uint32 /*state*/, Unit* /*unit*/) {} + virtual void EventInform(uint32 /*eventId*/) {} }; class NullGameObjectAI : public GameObjectAI diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 160b406a6ea..97ae0581a18 100755 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -532,3 +532,19 @@ bool PetAI::CanAttack(Unit* target) // default, though we shouldn't ever get here return false; } + +void PetAI::ReceiveEmote(Player* player, uint32 emote) +{ + if (me->GetOwnerGUID() && me->GetOwnerGUID() == player->GetGUID()) + switch (emote) + { + case TEXT_EMOTE_COWER: + if (me->isPet() && me->ToPet()->IsPetGhoul()) + me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + break; + case TEXT_EMOTE_ANGRY: + if (me->isPet() && me->ToPet()->IsPetGhoul()) + me->HandleEmoteCommand(EMOTE_ONESHOT_COWER); + break; + } +} diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index ed3e2305556..8e5311fa000 100755 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -42,6 +42,7 @@ class PetAI : public CreatureAI void MovementInform(uint32 moveType, uint32 data); void OwnerDamagedBy(Unit* attacker); void OwnerAttacked(Unit* target); + void ReceiveEmote(Player* player, uint32 textEmote); private: bool _isVisible(Unit*) const; diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index 94ac452b9f3..68752b82e7f 100755 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -128,8 +128,6 @@ class CreatureAI : public UnitAI void OnCharmed(bool apply); - //virtual void SpellClick(Player* player) {} - // Called at reaching home after evade virtual void JustReachedHome() {} @@ -171,6 +169,8 @@ class CreatureAI : public UnitAI virtual void PassengerBoarded(Unit* /*passenger*/, int8 /*seatId*/, bool /*apply*/) {} + virtual void OnSpellClick(Unit* /*clicker*/) { } + virtual bool CanSeeAlways(WorldObject const* /*obj*/) { return false; } protected: virtual void MoveInLineOfSight(Unit* /*who*/); diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp index 517e55af457..a863f2f89cf 100755 --- a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp +++ b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp @@ -204,12 +204,17 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() temp.raw.param3 = fields[8].GetInt32(); temp.raw.param4 = fields[9].GetInt32(); + CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id); //Creature does not exist in database - if (!sObjectMgr->GetCreatureTemplate(temp.creature_id)) + if (!cInfo) { - sLog->outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, temp.creature_id); + sLog->outErrorDb("CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, creature_id); continue; } + + // Only on the first script + if (cInfo->AIName != "EventAI" && m_CreatureEventAI_Event_Map[creature_id].empty()) + sLog->outErrorDb("Creature entry %u has EventAI scripts, but its AIName is not 'EventAI' - possible AI-mismatch?", temp.creature_id); //No chance of this event occuring if (temp.event_chance == 0) @@ -735,18 +740,6 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts() } while (result->NextRow()); - for (CreatureEventAI_Event_Map::const_iterator itr = m_CreatureEventAI_Event_Map.begin(); itr != m_CreatureEventAI_Event_Map.end(); ++itr) - { - if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(itr->first)) - { - if (cInfo->AIName != "EventAI") - { - sLog->outErrorDb("Creature entry %u has EventAI scripts, but its AIName is not 'EventAI', changing to EventAI", itr->first); - const_cast<CreatureTemplate*>(cInfo)->AIName = "EventAI"; - } - } - } - sLog->outString(">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 4fac8b3cba5..ba0a94d2590 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -191,7 +191,7 @@ struct ScriptedAI : public CreatureAI //Generally used to control if MoveChase() is to be used or not in AttackStart(). Some creatures does not chase victims void SetCombatMovement(bool allowMovement); - bool IsCombatMovementAllowed() { return _isCombatMovementAllowed; } + bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; } bool EnterEvadeIfOutOfCombatArea(uint32 const diff); @@ -200,16 +200,16 @@ struct ScriptedAI : public CreatureAI // - for raid in mode 10-Heroic // - for raid in mode 25-heroic // DO NOT USE to check raid in mode 25-normal. - bool IsHeroic() { return _isHeroic; } + bool IsHeroic() const { return _isHeroic; } // return the dungeon or raid difficulty - Difficulty GetDifficulty() { return _difficulty; } + Difficulty GetDifficulty() const { return _difficulty; } // return true for 25 man or 25 man heroic mode - bool Is25ManRaid() { return _difficulty & RAID_DIFFICULTY_MASK_25MAN; } + bool Is25ManRaid() const { return _difficulty & RAID_DIFFICULTY_MASK_25MAN; } template<class T> inline - const T& DUNGEON_MODE(const T& normal5, const T& heroic10) + const T& DUNGEON_MODE(const T& normal5, const T& heroic10) const { switch (_difficulty) { @@ -225,7 +225,7 @@ struct ScriptedAI : public CreatureAI } template<class T> inline - const T& RAID_MODE(const T& normal10, const T& normal25) + const T& RAID_MODE(const T& normal10, const T& normal25) const { switch (_difficulty) { @@ -241,7 +241,7 @@ struct ScriptedAI : public CreatureAI } template<class T> inline - const T& RAID_MODE(const T& normal10, const T& normal25, const T& heroic10, const T& heroic25) + const T& RAID_MODE(const T& normal10, const T& normal25, const T& heroic10, const T& heroic25) const { switch (_difficulty) { diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 13bbbe2c338..987af82e496 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -327,7 +327,6 @@ Player* FollowerAI::GetLeaderForFollower() sLog->outDebug(LOG_FILTER_TSCR, "TSCR: FollowerAI GetLeader changed and returned new leader."); m_uiLeaderGUID = member->GetGUID(); return member; - break; } } } diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 08f1b18ffad..96fc43e0572 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -696,8 +696,9 @@ void SmartAI::OnCharmed(bool apply) GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, NULL, 0, 0, apply); } -void SmartAI::DoAction(const int32 /*param*/) +void SmartAI::DoAction(const int32 param) { + GetScript()->ProcessEventsFor(SMART_EVENT_ACTION_DONE, NULL, param); } uint32 SmartAI::GetData(uint32 /*id*/) @@ -825,27 +826,10 @@ void SmartAI::sOnGameEvent(bool start, uint16 eventId) GetScript()->ProcessEventsFor(start ? SMART_EVENT_GAME_EVENT_START : SMART_EVENT_GAME_EVENT_END, NULL, eventId); } -/* -SMART_EVENT_UPDATE_OOC -SMART_EVENT_SPELLHIT -SMART_EVENT_RANGE -SMART_EVENT_RESPAWN -SMART_EVENT_SUMMONED_UNIT -SMART_EVENT_ACCEPTED_QUEST -SMART_EVENT_REWARD_QUEST -SMART_EVENT_TARGET_BUFFED -SMART_EVENT_SUMMON_DESPAWNED -SMART_EVENT_AI_INIT -SMART_EVENT_DATA_SET -SMART_EVENT_TEXT_OVER -SMART_EVENT_TIMED_EVENT_TRIGGERED -SMART_EVENT_UPDATE -SMART_EVENT_LINK -SMART_EVENT_GOSSIP_SELECT -SMART_EVENT_JUST_CREATED -SMART_EVENT_GOSSIP_HELLO -SMART_EVENT_DEATH -*/ +void SmartAI::OnSpellClick(Unit* clicker) +{ + GetScript()->ProcessEventsFor(SMART_EVENT_ON_SPELLCLICK, clicker); +} int SmartGameObjectAI::Permissible(const GameObject* g) { @@ -937,6 +921,11 @@ void SmartGameObjectAI::OnStateChanged(uint32 state, Unit* unit) GetScript()->ProcessEventsFor(SMART_EVENT_GO_STATE_CHANGED, unit, state); } +void SmartGameObjectAI::EventInform(uint32 eventId) +{ + GetScript()->ProcessEventsFor(SMART_EVENT_GO_EVENT_INFORM, NULL, eventId); +} + class SmartTrigger : public AreaTriggerScript { public: diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h index 435aa176d4d..79cef0c3b37 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.h +++ b/src/server/game/AI/SmartScripts/SmartAI.h @@ -198,6 +198,8 @@ class SmartAI : public CreatureAI void RemoveAuras(); + void OnSpellClick(Unit* clicker); + private: uint32 mFollowCreditType; uint32 mFollowArrivedTimer; @@ -235,30 +237,31 @@ class SmartAI : public CreatureAI class SmartGameObjectAI : public GameObjectAI { -public: - SmartGameObjectAI(GameObject* g) : GameObjectAI(g), go(g) {} - ~SmartGameObjectAI() {} - - void UpdateAI(uint32 diff); - void InitializeAI(); - void Reset(); - SmartScript* GetScript() { return &mScript; } - static int Permissible(const GameObject* g); - - bool GossipHello(Player* player); - bool GossipSelect(Player* player, uint32 sender, uint32 action); - bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/); - bool QuestAccept(Player* player, Quest const* quest); - bool QuestReward(Player* player, Quest const* quest, uint32 opt); - uint32 GetDialogStatus(Player* /*player*/); - void Destroyed(Player* player, uint32 eventId); - void SetData(uint32 id, uint32 value); - void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); - void OnGameEvent(bool start, uint16 eventId); - void OnStateChanged(uint32 state, Unit* unit); - -protected: - GameObject* const go; - SmartScript mScript; + public: + SmartGameObjectAI(GameObject* g) : GameObjectAI(g), go(g) {} + ~SmartGameObjectAI() {} + + void UpdateAI(uint32 diff); + void InitializeAI(); + void Reset(); + SmartScript* GetScript() { return &mScript; } + static int Permissible(const GameObject* g); + + bool GossipHello(Player* player); + bool GossipSelect(Player* player, uint32 sender, uint32 action); + bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, const char* /*code*/); + bool QuestAccept(Player* player, Quest const* quest); + bool QuestReward(Player* player, Quest const* quest, uint32 opt); + uint32 GetDialogStatus(Player* /*player*/); + void Destroyed(Player* player, uint32 eventId); + void SetData(uint32 id, uint32 value); + void SetScript9(SmartScriptHolder& e, uint32 entry, Unit* invoker); + void OnGameEvent(bool start, uint16 eventId); + void OnStateChanged(uint32 state, Unit* unit); + void EventInform(uint32 eventId); + + protected: + GameObject* const go; + SmartScript mScript; }; #endif diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 01a9b777358..103cde80f43 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -160,9 +160,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { case SMART_ACTION_TALK: { - if (!me) - break; - ObjectList* targets = GetTargets(e, unit); Creature* talker = me; Player* targetPlayer = NULL; @@ -185,6 +182,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u delete targets; } + if (!talker) + break; + mTalkerEntry = talker->GetEntry(); mLastTextID = e.action.talk.textGroupID; mTextTimer = e.action.talk.duration; @@ -789,7 +789,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!IsUnit((*itr))) continue; - (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + if (e.action.removeAura.spell == 0) + (*itr)->ToUnit()->RemoveAllAuras(); + else + (*itr)->ToUnit()->RemoveAurasDueToSpell(e.action.removeAura.spell); + sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_REMOVEAURASFROMSPELL: Unit %u, spell %u", (*itr)->GetGUIDLow(), e.action.removeAura.spell); } @@ -1539,8 +1543,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!IsSmart()) break; - float attackDistance = (float)e.action.setRangedMovement.distance; - float attackAngle = e.action.setRangedMovement.angle / 180.0f * M_PI; + float attackDistance = float(e.action.setRangedMovement.distance); + float attackAngle = float(e.action.setRangedMovement.angle) / 180.0f * M_PI; ObjectList* targets = GetTargets(e, unit); if (targets) @@ -2016,16 +2020,16 @@ void SmartScript::InstallTemplate(SmartScriptHolder const& e) if (!go) return; //store hostage as id1 - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 1, 0, 0, 0, 0, 0, SMART_TARGET_CLOSEST_CREATURE, e.action.installTtemplate.param1, 10, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 1, 0, 0, 0, 0, 0, SMART_TARGET_CLOSEST_CREATURE, e.action.installTtemplate.param1, 10, 0, 0); //store invoker as id2 - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 2, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_STORE_TARGET_LIST, 2, 0, 0, 0, 0, 0, SMART_TARGET_NONE, 0, 0, 0, 0); //signal hostage - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_SET_DATA, 0, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 1, 0, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_SET_DATA, 0, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 1, 0, 0, 0); //when hostage raeched end point, give credit to invoker if (e.action.installTtemplate.param2) AddEvent(SMART_EVENT_DATA_SET, 0, 0, 0, 0, 0, SMART_ACTION_CALL_KILLEDMONSTER, e.action.installTtemplate.param1, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 2, 0, 0, 0); else - AddEvent(SMART_EVENT_GOSSIP_HELLO, 0, 0, 0, 0, 0, SMART_ACTION_CALL_KILLEDMONSTER, e.action.installTtemplate.param1, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 2, 0, 0, 0); + AddEvent(SMART_EVENT_GO_STATE_CHANGED, 0, 2, 0, 0, 0, SMART_ACTION_CALL_KILLEDMONSTER, e.action.installTtemplate.param1, 0, 0, 0, 0, 0, SMART_TARGET_STORED, 2, 0, 0, 0); break; } case SMARTAI_TEMPLATE_BASIC: @@ -2119,12 +2123,20 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* case SMART_TARGET_INVOKER_PARTY: if (trigger) { - l->push_back(trigger); if (Player* player = trigger->ToPlayer()) + { if (Group* group = player->GetGroup()) + { for (GroupReference* groupRef = group->GetFirstMember(); groupRef != NULL; groupRef = groupRef->next()) if (Player* member = groupRef->getSource()) l->push_back(member); + } + // We still add the player to the list if there is no group. If we do + // this even if there is a group (thus the else-check), it will add the + // same player to the list twice. We don't want that to happen. + else + l->push_back(trigger); + } } break; case SMART_TARGET_CREATURE_RANGE: @@ -2522,6 +2534,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui case SMART_EVENT_JUST_CREATED: case SMART_EVENT_GOSSIP_HELLO: case SMART_EVENT_FOLLOW_COMPLETED: + case SMART_EVENT_ON_SPELLCLICK: ProcessAction(e, unit, var0, var1, bvar, spell, gob); break; case SMART_EVENT_IS_BEHIND_TARGET: @@ -2759,6 +2772,20 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui ProcessAction(e, unit, var0, var1); break; } + case SMART_EVENT_GO_EVENT_INFORM: + { + if (e.event.eventInform.eventId != var0) + return; + ProcessAction(e, NULL, var0); + break; + } + case SMART_EVENT_ACTION_DONE: + { + if (e.event.doAction.eventId != var0) + return; + ProcessAction(e, unit, var0); + break; + } default: sLog->outErrorDb("SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType()); break; @@ -2875,23 +2902,6 @@ void SmartScript::InstallEvents() } } -bool SmartScript::ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3) -{ - if (c == 0) - return true; - - if (!u || !u->ToPlayer()) - return false; - - Condition cond; - cond.ConditionType = ConditionTypes(uint32(c)); - cond.ConditionValue1 = uint32(v1); - cond.ConditionValue1 = uint32(v2); - cond.ConditionValue1 = uint32(v3); - ConditionSourceInfo srcInfo = ConditionSourceInfo(u->ToPlayer()); - return cond.Meets(srcInfo); -} - void SmartScript::OnUpdate(uint32 const diff) { if ((mScriptType == SMART_SCRIPT_TYPE_CREATURE || mScriptType == SMART_SCRIPT_TYPE_GAMEOBJECT) && !GetBaseObject()) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 5fb691c87f2..03d533e69e5 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -83,8 +83,6 @@ class SmartScript return obj && obj->GetTypeId() == TYPEID_GAMEOBJECT; } - bool ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3); - void OnUpdate(const uint32 diff); void OnMoveInLineOfSight(Unit* who); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index a7149f37480..de766d2a7e1 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -475,64 +475,78 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } case SMART_EVENT_TRANSPORT_ADDCREATURE: - { - if (e.event.transportAddCreature.creature && !IsCreatureValid(e, e.event.transportAddCreature.creature)) - return false; - break; - } + { + if (e.event.transportAddCreature.creature && !IsCreatureValid(e, e.event.transportAddCreature.creature)) + return false; + break; + } case SMART_EVENT_MOVEMENTINFORM: + { + if (e.event.movementInform.type > NULL_MOTION_TYPE) { - if (e.event.movementInform.type > NULL_MOTION_TYPE) - { - sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Motion type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.movementInform.type); - return false; - } - break; + sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Motion type %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.movementInform.type); + return false; } + break; + } case SMART_EVENT_DATA_SET: - { - if (!IsMinMaxValid(e, e.event.dataSet.cooldownMin, e.event.dataSet.cooldownMax)) - return false; - break; - } + { + if (!IsMinMaxValid(e, e.event.dataSet.cooldownMin, e.event.dataSet.cooldownMax)) + return false; + break; + } case SMART_EVENT_AREATRIGGER_ONTRIGGER: - { - if (e.event.areatrigger.id && !IsAreaTriggerValid(e, e.event.areatrigger.id)) - return false; - break; - } + { + if (e.event.areatrigger.id && !IsAreaTriggerValid(e, e.event.areatrigger.id)) + return false; + break; + } case SMART_EVENT_TEXT_OVER: //if (e.event.textOver.textGroupID && !IsTextValid(e, e.event.textOver.textGroupID)) return false;// 0 is a valid text group! break; case SMART_EVENT_LINK: + { + if (e.link && e.link == e.event_id) { - if (e.link && e.link == e.event_id) - { - sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u, Event %u, Link Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id); - return false; - } - break; + sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u, Event %u, Link Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id); + return false; } + break; + } case SMART_EVENT_DUMMY_EFFECT: + { if (!IsSpellValid(e, e.event.dummy.spell)) return false; if (e.event.dummy.effIndex > EFFECT_2) return false; break; + } case SMART_EVENT_IS_BEHIND_TARGET: + { if (!IsMinMaxValid(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax)) return false; break; + } case SMART_EVENT_GAME_EVENT_START: case SMART_EVENT_GAME_EVENT_END: + { + GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); + if (e.event.gameEvent.gameEventId >= events.size() || !events[e.event.gameEvent.gameEventId].isValid()) + return false; + break; + } + case SMART_EVENT_ACTION_DONE: + { + if (e.event.doAction.eventId > EVENT_CHARGE) { - GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); - if (e.event.gameEvent.gameEventId >= events.size() || !events[e.event.gameEvent.gameEventId].isValid()) - return false; - break; + sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid event id %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.doAction.eventId); + return false; } + break; + } case SMART_EVENT_GO_STATE_CHANGED: + case SMART_EVENT_GO_EVENT_INFORM: case SMART_EVENT_TIMED_EVENT_TRIGGERED: case SMART_EVENT_INSTANCE_PLAYER_ENTER: case SMART_EVENT_TRANSPORT_RELOCATE: @@ -563,6 +577,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_EVENT_GOSSIP_HELLO: case SMART_EVENT_JUST_CREATED: case SMART_EVENT_FOLLOW_COMPLETED: + case SMART_EVENT_ON_SPELLCLICK: break; default: sLog->outErrorDb("SmartAIMgr: Not handled event_type(%u), Entry %d SourceType %u Event %u Action %u, skipped.", e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); @@ -709,7 +724,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; break; case SMART_ACTION_REMOVEAURASFROMSPELL: - if (!IsSpellValid(e, e.action.removeAura.spell)) + if (e.action.removeAura.spell != 0 && !IsSpellValid(e, e.action.removeAura.spell)) return false; break; case SMART_ACTION_RANDOM_PHASE: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index e6c5eb727d7..155f27d0fe7 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -22,7 +22,6 @@ #include "Creature.h" #include "CreatureAI.h" #include "Unit.h" -#include "ConditionMgr.h" #include "Spell.h" #include "DB2Stores.h" @@ -83,80 +82,82 @@ const uint32 SmartPhaseMask[SMART_EVENT_PHASE_COUNT][2] = enum SMART_EVENT { - SMART_EVENT_UPDATE_IC = 0, //1 // InitialMin, InitialMax, RepeatMin, RepeatMax - SMART_EVENT_UPDATE_OOC = 1, //1 // InitialMin, InitialMax, RepeatMin, RepeatMax - SMART_EVENT_HEALT_PCT = 2, //1 // HPMin%, HPMax%, RepeatMin, RepeatMax - SMART_EVENT_MANA_PCT = 3, //1 // ManaMin%, ManaMax%, RepeatMin, RepeatMax - SMART_EVENT_AGGRO = 4, //1 // NONE - SMART_EVENT_KILL = 5, //1 // CooldownMin0, CooldownMax1, playerOnly2, else creature entry3 - SMART_EVENT_DEATH = 6, //1 // NONE - SMART_EVENT_EVADE = 7, //1 // NONE - SMART_EVENT_SPELLHIT = 8, //1 // SpellID, School, CooldownMin, CooldownMax - SMART_EVENT_RANGE = 9, //1 // MinDist, MaxDist, RepeatMin, RepeatMax - SMART_EVENT_OOC_LOS = 10, //1 // NoHostile, MaxRnage, CooldownMin, CooldownMax - SMART_EVENT_RESPAWN = 11, //1 // type, MapId, ZoneId - SMART_EVENT_TARGET_HEALTH_PCT = 12, //1 // HPMin%, HPMax%, RepeatMin, RepeatMax - SMART_EVENT_TARGET_CASTING = 13, //1 // RepeatMin, RepeatMax - SMART_EVENT_FRIENDLY_HEALTH = 14, //1 // HPDeficit, Radius, RepeatMin, RepeatMax - SMART_EVENT_FRIENDLY_IS_CC = 15, //1 // Radius, RepeatMin, RepeatMax - SMART_EVENT_FRIENDLY_MISSING_BUFF = 16, //1 // SpellId, Radius, RepeatMin, RepeatMax - SMART_EVENT_SUMMONED_UNIT = 17, //1 // CreatureId(0 all), CooldownMin, CooldownMax - SMART_EVENT_TARGET_MANA_PCT = 18, //1 // ManaMin%, ManaMax%, RepeatMin, RepeatMax - SMART_EVENT_ACCEPTED_QUEST = 19, //1 // QuestID(0any) - SMART_EVENT_REWARD_QUEST = 20, //1 // QuestID(0any) - SMART_EVENT_REACHED_HOME = 21, //1 // NONE - SMART_EVENT_RECEIVE_EMOTE = 22, //1 // EmoteId, CooldownMin, CooldownMax, condition, val1, val2, val3 - SMART_EVENT_HAS_AURA = 23, //1 // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 RepeatMin, RepeatMax - SMART_EVENT_TARGET_BUFFED = 24, //1 // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 RepeatMin, RepeatMax - SMART_EVENT_RESET = 25, //1 // Called after combat, when the creature respawn and spawn. - - SMART_EVENT_IC_LOS = 26, //1 // NoHostile, MaxRnage, CooldownMin, CooldownMax - SMART_EVENT_PASSENGER_BOARDED = 27, //1 // CooldownMin, CooldownMax - SMART_EVENT_PASSENGER_REMOVED = 28, //1 // CooldownMin, CooldownMax - SMART_EVENT_CHARMED = 29, //1 // NONE - SMART_EVENT_CHARMED_TARGET = 30, //1 // NONE - SMART_EVENT_SPELLHIT_TARGET = 31, //1 // SpellID, School, CooldownMin, CooldownMax - SMART_EVENT_DAMAGED = 32, //1 // MinDmg, MaxDmg, CooldownMin, CooldownMax - SMART_EVENT_DAMAGED_TARGET = 33, //1 // MinDmg, MaxDmg, CooldownMin, CooldownMax - SMART_EVENT_MOVEMENTINFORM = 34, //1 // MovementType(any), PointID - SMART_EVENT_SUMMON_DESPAWNED = 35, //1 // Entry, CooldownMin, CooldownMax - SMART_EVENT_CORPSE_REMOVED = 36, //1 // NONE - SMART_EVENT_AI_INIT = 37, //1 // NONE - SMART_EVENT_DATA_SET = 38, //1 // Id, Value, CooldownMin, CooldownMax - SMART_EVENT_WAYPOINT_START = 39, //1 // PointId(0any), pathID(0any) - SMART_EVENT_WAYPOINT_REACHED = 40, //1 // PointId(0any), pathID(0any) - SMART_EVENT_TRANSPORT_ADDPLAYER = 41, //1 // NONE - SMART_EVENT_TRANSPORT_ADDCREATURE = 42, //1 // Entry (0 any) - SMART_EVENT_TRANSPORT_REMOVE_PLAYER = 43, //1 // NONE - SMART_EVENT_TRANSPORT_RELOCATE = 44, //1 // PointId - SMART_EVENT_INSTANCE_PLAYER_ENTER = 45, //1 // Team (0 any), CooldownMin, CooldownMax - SMART_EVENT_AREATRIGGER_ONTRIGGER = 46, //1 // TriggerId(0 any) - SMART_EVENT_QUEST_ACCEPTED = 47, //1 // none - SMART_EVENT_QUEST_OBJ_COPLETETION = 48, //1 // none - SMART_EVENT_QUEST_COMPLETION = 49, //1 // none - SMART_EVENT_QUEST_REWARDED = 50, //1 // none - SMART_EVENT_QUEST_FAIL = 51, //1 // none - SMART_EVENT_TEXT_OVER = 52, //1 // GroupId from creature_text, creature entry who talks (0 any) - SMART_EVENT_RECEIVE_HEAL = 53, //1 // MinHeal, MaxHeal, CooldownMin, CooldownMax - SMART_EVENT_JUST_SUMMONED = 54, //1 // none - SMART_EVENT_WAYPOINT_PAUSED = 55, //1 // PointId(0any), pathID(0any) - SMART_EVENT_WAYPOINT_RESUMED = 56, //1 // PointId(0any), pathID(0any) - SMART_EVENT_WAYPOINT_STOPPED = 57, //1 // PointId(0any), pathID(0any) - SMART_EVENT_WAYPOINT_ENDED = 58, //1 // PointId(0any), pathID(0any) - SMART_EVENT_TIMED_EVENT_TRIGGERED = 59, //1 // id - SMART_EVENT_UPDATE = 60, //1 // InitialMin, InitialMax, RepeatMin, RepeatMax - SMART_EVENT_LINK = 61, //1 // INTERNAL USAGE, no params, used to link together multiple events, does not use any extra resources to iterate event lists needlessly - SMART_EVENT_GOSSIP_SELECT = 62, //1 // menuID, actionID - SMART_EVENT_JUST_CREATED = 63, //1 // none - SMART_EVENT_GOSSIP_HELLO = 64, //1 // none - SMART_EVENT_FOLLOW_COMPLETED = 65, //1 // none - SMART_EVENT_DUMMY_EFFECT = 66, //1 // spellId, effectIndex - SMART_EVENT_IS_BEHIND_TARGET = 67, //1 // cooldownMin, CooldownMax - SMART_EVENT_GAME_EVENT_START = 68, //1 // game_event.Entry - SMART_EVENT_GAME_EVENT_END = 69, //1 // game_event.Entry - SMART_EVENT_GO_STATE_CHANGED = 70, // go state - - SMART_EVENT_END = 71, + SMART_EVENT_UPDATE_IC = 0, // InitialMin, InitialMax, RepeatMin, RepeatMax + SMART_EVENT_UPDATE_OOC = 1, // InitialMin, InitialMax, RepeatMin, RepeatMax + SMART_EVENT_HEALT_PCT = 2, // HPMin%, HPMax%, RepeatMin, RepeatMax + SMART_EVENT_MANA_PCT = 3, // ManaMin%, ManaMax%, RepeatMin, RepeatMax + SMART_EVENT_AGGRO = 4, // NONE + SMART_EVENT_KILL = 5, // CooldownMin0, CooldownMax1, playerOnly2, else creature entry3 + SMART_EVENT_DEATH = 6, // NONE + SMART_EVENT_EVADE = 7, // NONE + SMART_EVENT_SPELLHIT = 8, // SpellID, School, CooldownMin, CooldownMax + SMART_EVENT_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax + SMART_EVENT_OOC_LOS = 10, // NoHostile, MaxRnage, CooldownMin, CooldownMax + SMART_EVENT_RESPAWN = 11, // type, MapId, ZoneId + SMART_EVENT_TARGET_HEALTH_PCT = 12, // HPMin%, HPMax%, RepeatMin, RepeatMax + SMART_EVENT_TARGET_CASTING = 13, // RepeatMin, RepeatMax + SMART_EVENT_FRIENDLY_HEALTH = 14, // HPDeficit, Radius, RepeatMin, RepeatMax + SMART_EVENT_FRIENDLY_IS_CC = 15, // Radius, RepeatMin, RepeatMax + SMART_EVENT_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax + SMART_EVENT_SUMMONED_UNIT = 17, // CreatureId(0 all), CooldownMin, CooldownMax + SMART_EVENT_TARGET_MANA_PCT = 18, // ManaMin%, ManaMax%, RepeatMin, RepeatMax + SMART_EVENT_ACCEPTED_QUEST = 19, // QuestID(0any) + SMART_EVENT_REWARD_QUEST = 20, // QuestID(0any) + SMART_EVENT_REACHED_HOME = 21, // NONE + SMART_EVENT_RECEIVE_EMOTE = 22, // EmoteId, CooldownMin, CooldownMax, condition, val1, val2, val3 + SMART_EVENT_HAS_AURA = 23, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 RepeatMin, RepeatMax + SMART_EVENT_TARGET_BUFFED = 24, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 RepeatMin, RepeatMax + SMART_EVENT_RESET = 25, // Called after combat, when the creature respawn and spawn. + SMART_EVENT_IC_LOS = 26, // NoHostile, MaxRnage, CooldownMin, CooldownMax + SMART_EVENT_PASSENGER_BOARDED = 27, // CooldownMin, CooldownMax + SMART_EVENT_PASSENGER_REMOVED = 28, // CooldownMin, CooldownMax + SMART_EVENT_CHARMED = 29, // NONE + SMART_EVENT_CHARMED_TARGET = 30, // NONE + SMART_EVENT_SPELLHIT_TARGET = 31, // SpellID, School, CooldownMin, CooldownMax + SMART_EVENT_DAMAGED = 32, // MinDmg, MaxDmg, CooldownMin, CooldownMax + SMART_EVENT_DAMAGED_TARGET = 33, // MinDmg, MaxDmg, CooldownMin, CooldownMax + SMART_EVENT_MOVEMENTINFORM = 34, // MovementType(any), PointID + SMART_EVENT_SUMMON_DESPAWNED = 35, // Entry, CooldownMin, CooldownMax + SMART_EVENT_CORPSE_REMOVED = 36, // NONE + SMART_EVENT_AI_INIT = 37, // NONE + SMART_EVENT_DATA_SET = 38, // Id, Value, CooldownMin, CooldownMax + SMART_EVENT_WAYPOINT_START = 39, // PointId(0any), pathID(0any) + SMART_EVENT_WAYPOINT_REACHED = 40, // PointId(0any), pathID(0any) + SMART_EVENT_TRANSPORT_ADDPLAYER = 41, // NONE + SMART_EVENT_TRANSPORT_ADDCREATURE = 42, // Entry (0 any) + SMART_EVENT_TRANSPORT_REMOVE_PLAYER = 43, // NONE + SMART_EVENT_TRANSPORT_RELOCATE = 44, // PointId + SMART_EVENT_INSTANCE_PLAYER_ENTER = 45, // Team (0 any), CooldownMin, CooldownMax + SMART_EVENT_AREATRIGGER_ONTRIGGER = 46, // TriggerId(0 any) + SMART_EVENT_QUEST_ACCEPTED = 47, // none + SMART_EVENT_QUEST_OBJ_COPLETETION = 48, // none + SMART_EVENT_QUEST_COMPLETION = 49, // none + SMART_EVENT_QUEST_REWARDED = 50, // none + SMART_EVENT_QUEST_FAIL = 51, // none + SMART_EVENT_TEXT_OVER = 52, // GroupId from creature_text, creature entry who talks (0 any) + SMART_EVENT_RECEIVE_HEAL = 53, // MinHeal, MaxHeal, CooldownMin, CooldownMax + SMART_EVENT_JUST_SUMMONED = 54, // none + SMART_EVENT_WAYPOINT_PAUSED = 55, // PointId(0any), pathID(0any) + SMART_EVENT_WAYPOINT_RESUMED = 56, // PointId(0any), pathID(0any) + SMART_EVENT_WAYPOINT_STOPPED = 57, // PointId(0any), pathID(0any) + SMART_EVENT_WAYPOINT_ENDED = 58, // PointId(0any), pathID(0any) + SMART_EVENT_TIMED_EVENT_TRIGGERED = 59, // id + SMART_EVENT_UPDATE = 60, // InitialMin, InitialMax, RepeatMin, RepeatMax + SMART_EVENT_LINK = 61, // INTERNAL USAGE, no params, used to link together multiple events, does not use any extra resources to iterate event lists needlessly + SMART_EVENT_GOSSIP_SELECT = 62, // menuID, actionID + SMART_EVENT_JUST_CREATED = 63, // none + SMART_EVENT_GOSSIP_HELLO = 64, // none + SMART_EVENT_FOLLOW_COMPLETED = 65, // none + SMART_EVENT_DUMMY_EFFECT = 66, // spellId, effectIndex + SMART_EVENT_IS_BEHIND_TARGET = 67, // cooldownMin, CooldownMax + SMART_EVENT_GAME_EVENT_START = 68, // game_event.Entry + SMART_EVENT_GAME_EVENT_END = 69, // game_event.Entry + SMART_EVENT_GO_STATE_CHANGED = 70, // go state + SMART_EVENT_GO_EVENT_INFORM = 71, // eventId + SMART_EVENT_ACTION_DONE = 72, // eventId (SharedDefines.EventId) + SMART_EVENT_ON_SPELLCLICK = 73, // clicker (unit) + + SMART_EVENT_END = 74, }; struct SmartEvent @@ -353,6 +354,16 @@ struct SmartEvent struct { + uint32 eventId; + } eventInform; + + struct + { + uint32 eventId; + } doAction; + + struct + { uint32 param1; uint32 param2; uint32 param3; @@ -399,7 +410,7 @@ enum SMART_ACTION SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID SMART_ACTION_CALL_CASTEDCREATUREORGO = 27, // CreatureId, SpellId - SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid + SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid, 0 removes all auras SMART_ACTION_FOLLOW = 29, // Distance (0 = default), Angle (0 = default), EndCreatureEntry, credit, creditType (0monsterkill, 1event) SMART_ACTION_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3... SMART_ACTION_RANDOM_PHASE_RANGE = 31, // PhaseMin, PhaseMax @@ -847,9 +858,9 @@ struct SmartAction struct { - bool withDelayed; + uint32 withDelayed; uint32 spell_id; - bool withInstant; + uint32 withInstant; } interruptSpellCasting; struct @@ -875,7 +886,7 @@ struct SmartAction struct { - uint8 pointId; + uint32 pointId; } MoveToPos; struct @@ -896,10 +907,13 @@ struct SmartAction struct { - float distance; - float angle; + uint32 distance; + uint32 angle; } setRangedMovement; + //! Note for any new future actions + //! All parameters must have type uint32 + struct { uint32 param1; @@ -1167,7 +1181,9 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] = {SMART_EVENT_GAME_EVENT_START, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_GAME_EVENT_END, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, {SMART_EVENT_GO_STATE_CHANGED, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, - + {SMART_EVENT_GO_EVENT_INFORM, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }, + {SMART_EVENT_ACTION_DONE, SMART_SCRIPT_TYPE_MASK_CREATURE }, + {SMART_EVENT_ON_SPELLCLICK, SMART_SCRIPT_TYPE_MASK_CREATURE }, }; enum SmartEventFlags @@ -1380,26 +1396,6 @@ class SmartAIMgr } return true; } - /*inline bool IsConditionValid(SmartScriptHolder e, int32 t, int32 v1, int32 v2, int32 v3) - { - bool error = false; - if (t > 0 && v1 >= 0 && v2 >= 0 && v3 >= 0) - { - Condition cond; - cond.mConditionType = ConditionType(t); - cond.mConditionValue1 = uint32(v1); - cond.mConditionValue2 = uint32(v2); - cond.mConditionValue3 = uint32(v3); - if (!sConditionMgr->isConditionTypeValid(&cond)) - error = true; - } - if (error) - { - sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Condition, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); - return false; - } - return true; - }*/ bool IsTextEmoteValid(SmartScriptHolder const& e, uint32 entry) { diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 21a2a75b470..252e120f0c9 100755 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -2207,7 +2207,6 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList() for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId) { - AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); if (!criteria) continue; @@ -2238,7 +2237,6 @@ void AchievementGlobalMgr::LoadAchievementReferenceList() for (uint32 entryId = 0; entryId < sAchievementStore.GetNumRows(); ++entryId) { - AchievementEntry const* achievement = sAchievementStore.LookupEntry(entryId); if (!achievement || !achievement->refAchievement) continue; @@ -2247,6 +2245,10 @@ void AchievementGlobalMgr::LoadAchievementReferenceList() ++count; } + // Once Bitten, Twice Shy (10 player) - Icecrown Citadel + if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(4539)) + const_cast<AchievementEntry*>(achievement)->mapID = 631; // Correct map requirement (currently has Ulduar) + sLog->outString(">> Loaded %u achievement references in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp index c964f47f495..1b666859749 100644 --- a/src/server/game/Battlegrounds/ArenaTeamMgr.cpp +++ b/src/server/game/Battlegrounds/ArenaTeamMgr.cpp @@ -151,11 +151,11 @@ void ArenaTeamMgr::DistributeArenaPoints() if (ArenaTeam* at = teamItr->second) at->UpdateArenaPointsHelper(PlayerPoints); + /* SQLTransaction trans = CharacterDatabase.BeginTransaction(); // Cycle that gives points to all players - /* - PreparedStatement* stmt; + PreparedStatement* stmt; for (std::map<uint32, uint32>::iterator playerItr = PlayerPoints.begin(); playerItr != PlayerPoints.end(); ++playerItr) { @@ -170,9 +170,9 @@ void ArenaTeamMgr::DistributeArenaPoints() trans->Append(stmt); } } - */ CharacterDatabase.CommitTransaction(trans); + */ PlayerPoints.clear(); diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 54c84f2e6d4..ebcf5495a55 100755 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -850,12 +850,8 @@ void Battleground::EndBattleground(uint32 winner) if (team == winner) { // update achievement BEFORE personal rating update - if (ArenaTeamMember* member = winner_arena_team->GetMember(player->GetGUID())) - { - uint32 rating = player->GetArenaPersonalRating(winner_arena_team->GetSlot()); - player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, - rating ? rating : 1); - } + uint32 rating = player->GetArenaPersonalRating(winner_arena_team->GetSlot()); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1); winner_arena_team->MemberWon(player, loser_matchmaker_rating, winner_matchmaker_change); } @@ -1776,15 +1772,19 @@ void Battleground::HandleTriggerBuff(uint64 go_guid) SpawnBGObject(index, BUFF_RESPAWN_TIME); } -void Battleground::HandleKillPlayer(Player* player, Player* killer) +void Battleground::HandleKillPlayer(Player* victim, Player* killer) { // Keep in mind that for arena this will have to be changed a bit // Add +1 deaths - UpdatePlayerScore(player, SCORE_DEATHS, 1); + UpdatePlayerScore(victim, SCORE_DEATHS, 1); // Add +1 kills to group and +1 killing_blows to killer if (killer) { + // Don't reward credit for killing ourselves, like fall damage of hellfire (warlock) + if (killer == victim) + return; + UpdatePlayerScore(killer, SCORE_HONORABLE_KILLS, 1); UpdatePlayerScore(killer, SCORE_KILLING_BLOWS, 1); @@ -1794,7 +1794,7 @@ void Battleground::HandleKillPlayer(Player* player, Player* killer) if (!creditedPlayer || creditedPlayer == killer) continue; - if (creditedPlayer->GetTeam() == killer->GetTeam() && creditedPlayer->IsAtGroupRewardDistance(player)) + if (creditedPlayer->GetTeam() == killer->GetTeam() && creditedPlayer->IsAtGroupRewardDistance(victim)) UpdatePlayerScore(creditedPlayer, SCORE_HONORABLE_KILLS, 1); } } @@ -1802,8 +1802,8 @@ void Battleground::HandleKillPlayer(Player* player, Player* killer) if (!isArena()) { // To be able to remove insignia -- ONLY IN Battlegrounds - player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); - RewardXPAtKill(killer, player); + victim->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); + RewardXPAtKill(killer, victim); } } diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index b7079fb00e0..0d4fc458faa 100755 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -55,7 +55,7 @@ BattlegroundMgr::BattlegroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTe { for (uint32 i = BATTLEGROUND_TYPE_NONE; i < MAX_BATTLEGROUND_TYPE_ID; i++) m_Battlegrounds[i].clear(); - m_NextRatingDiscardUpdate = sWorld->getIntConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); + m_NextRatedArenaUpdate = sWorld->getIntConfig(CONFIG_ARENA_RATED_UPDATE_TIMER); m_Testing=false; } @@ -143,10 +143,10 @@ void BattlegroundMgr::Update(uint32 diff) } // if rating difference counts, maybe force-update queues - if (sWorld->getIntConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld->getIntConfig(CONFIG_ARENA_RATING_DISCARD_TIMER)) + if (sWorld->getIntConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE) && sWorld->getIntConfig(CONFIG_ARENA_RATED_UPDATE_TIMER)) { // it's time to force update - if (m_NextRatingDiscardUpdate < diff) + if (m_NextRatedArenaUpdate < diff) { // forced update for rated arenas (scan all, but skipped non rated) sLog->outDebug(LOG_FILTER_BATTLEGROUND, "BattlegroundMgr: UPDATING ARENA QUEUES"); @@ -156,10 +156,10 @@ void BattlegroundMgr::Update(uint32 diff) BATTLEGROUND_AA, BattlegroundBracketId(bracket), BattlegroundMgr::BGArenaType(BattlegroundQueueTypeId(qtype)), true, 0); - m_NextRatingDiscardUpdate = sWorld->getIntConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); + m_NextRatedArenaUpdate = sWorld->getIntConfig(CONFIG_ARENA_RATED_UPDATE_TIMER); } else - m_NextRatingDiscardUpdate -= diff; + m_NextRatedArenaUpdate -= diff; } if (sWorld->getBoolConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS)) { @@ -771,8 +771,9 @@ void BattlegroundMgr::CreateInitialBattlegrounds() continue; } - selectionWeight = fields[10].GetUInt8(); data.StartMaxDist = fields[9].GetFloat(); + + selectionWeight = fields[10].GetUInt8(); data.scriptId = sObjectMgr->GetScriptId(fields[11].GetCString()); //data.BattlegroundName = bl->name[sWorld->GetDefaultDbcLocale()]; diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index dd502409178..4edad4da742 100755 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -141,7 +141,7 @@ class BattlegroundMgr BattlegroundSelectionWeightMap m_BGSelectionWeights; std::vector<uint64> m_QueueUpdateScheduler; std::set<uint32> m_ClientBattlegroundIds[MAX_BATTLEGROUND_TYPE_ID][MAX_BATTLEGROUND_BRACKETS]; //the instanceids just visible for the client - uint32 m_NextRatingDiscardUpdate; + uint32 m_NextRatedArenaUpdate; time_t m_NextAutoDistributionTime; uint32 m_AutoDistributionTimeChecker; bool m_ArenaTesting; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp index 39c6e00946a..bda1bdfa8d3 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp @@ -56,6 +56,8 @@ void BattlegroundSA::Reset() GateStatus[i] = BG_SA_GATE_OK; ShipsStarted = false; gateDestroyed = false; + _notEvenAScratch[BG_TEAM_ALLIANCE] = true; + _notEvenAScratch[BG_TEAM_HORDE] = true; Status = BG_SA_WARMUP; } @@ -553,13 +555,13 @@ void BattlegroundSA::EventPlayerDamagedGO(Player* /*player*/, GameObject* go, ui SendWarningToAll(LANG_BG_SA_IS_UNDER_ATTACK, go->GetGOInfo()->name.c_str()); } -void BattlegroundSA::HandleKillUnit(Creature* unit, Player* killer) +void BattlegroundSA::HandleKillUnit(Creature* creature, Player* killer) { - if (!unit) - return; - - if (unit->GetEntry() == NPC_DEMOLISHER_SA) + if (creature->GetEntry() == NPC_DEMOLISHER_SA) + { UpdatePlayerScore(killer, SCORE_DESTROYED_DEMOLISHER, 1); + _notEvenAScratch[Attackers] = false; + } } /* diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h index c18806490f2..fd11cb2c5ea 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.h @@ -456,7 +456,7 @@ class BattlegroundSA : public Battleground /// Called when a player deal damage to building (door) virtual void EventPlayerDamagedGO(Player* player, GameObject* go, uint32 eventType); /// Called when a player kill a unit in bg - virtual void HandleKillUnit(Creature* unit, Player* killer); + virtual void HandleKillUnit(Creature* creature, Player* killer); /// Return the nearest graveyard where player can respawn virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); /// Called when a player click on flag (graveyard flag) @@ -531,9 +531,12 @@ class BattlegroundSA : public Battleground /// Update score board void UpdatePlayerScore(Player* Source, uint32 type, uint32 value, bool doAddHonor = true); - // Achievement Defense of the Ancients + // Achievement: Defense of the Ancients bool gateDestroyed; + // Achievement: Not Even a Scratch + bool notEvenAScratch(uint32 team) const { return _notEvenAScratch[GetTeamIndexByTeamId(team)]; } + /// Id of attacker team TeamId Attackers; @@ -615,5 +618,7 @@ class BattlegroundSA : public Battleground bool InitSecondRound; std::map<uint32/*id*/, uint32/*timer*/> DemoliserRespawnList; + // Achievement: Not Even a Scratch + bool _notEvenAScratch[BG_TEAMS_COUNT]; }; #endif diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index cc64a8e22dd..7a146e89505 100755 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -92,40 +92,6 @@ ChatCommand* ChatHandler::getCommandTable() { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand castCommandTable[] = - { - { "back", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleCastBackCommand>, "", NULL }, - { "dist", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleCastDistCommand>, "", NULL }, - { "self", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleCastSelfCommand>, "", NULL }, - { "target", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleCastTargetCommand>, "", NULL }, - { "dest", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleCastDestCommand>, "", NULL }, - { "", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleCastCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand characterDeletedCommandTable[] = - { - { "delete", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleCharacterDeletedDeleteCommand>, "", NULL }, - { "list", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleCharacterDeletedListCommand>, "", NULL }, - { "restore", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleCharacterDeletedRestoreCommand>, "", NULL }, - { "old", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleCharacterDeletedOldCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand characterCommandTable[] = - { - { "customize", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleCharacterCustomizeCommand>, "", NULL }, - { "changefaction", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleCharacterChangeFactionCommand>, "", NULL }, - { "changerace", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleCharacterChangeRaceCommand>, "", NULL }, - { "deleted", SEC_GAMEMASTER, true, NULL, "", characterDeletedCommandTable}, - { "erase", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleCharacterEraseCommand>, "", NULL }, - { "level", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleCharacterLevelCommand>, "", NULL }, - { "rename", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleCharacterRenameCommand>, "", NULL }, - { "reputation", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleCharacterReputationCommand>, "", NULL }, - { "titles", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleCharacterTitlesCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - static ChatCommand channelSetCommandTable[] = { { "ownership", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleChannelSetOwnership>, "", NULL }, @@ -156,24 +122,6 @@ ChatCommand* ChatHandler::getCommandTable() { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand instanceCommandTable[] = - { - { "listbinds", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleInstanceListBindsCommand>, "", NULL }, - { "unbind", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleInstanceUnbindCommand>, "", NULL }, - { "stats", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleInstanceStatsCommand>, "", NULL }, - { "savedata", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleInstanceSaveDataCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand listCommandTable[] = - { - { "creature", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleListCreatureCommand>, "", NULL }, - { "item", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleListItemCommand>, "", NULL }, - { "object", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleListObjectCommand>, "", NULL }, - { "auras", SEC_ADMINISTRATOR, false, OldHandler<&ChatHandler::HandleListAurasCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - static ChatCommand lookupPlayerCommandTable[] = { { "ip", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleLookupPlayerIpCommand>, "", NULL }, @@ -217,18 +165,6 @@ ChatCommand* ChatHandler::getCommandTable() { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand resetCommandTable[] = - { - { "achievements", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleResetAchievementsCommand>, "", NULL }, - { "honor", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleResetHonorCommand>, "", NULL }, - { "level", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleResetLevelCommand>, "", NULL }, - { "spells", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleResetSpellsCommand>, "", NULL }, - { "stats", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleResetStatsCommand>, "", NULL }, - { "talents", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleResetTalentsCommand>, "", NULL }, - { "all", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleResetAllCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - static ChatCommand sendCommandTable[] = { { "items", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleSendItemsCommand>, "", NULL }, @@ -238,60 +174,6 @@ ChatCommand* ChatHandler::getCommandTable() { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand serverIdleRestartCommandTable[] = - { - { "cancel", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerShutDownCancelCommand>, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerIdleRestartCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand serverIdleShutdownCommandTable[] = - { - { "cancel", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerShutDownCancelCommand>, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerIdleShutDownCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand serverRestartCommandTable[] = - { - { "cancel", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerShutDownCancelCommand>, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerRestartCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand serverShutdownCommandTable[] = - { - { "cancel", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerShutDownCancelCommand>, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerShutDownCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand serverSetCommandTable[] = - { - { "difftime", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleServerSetDiffTimeCommand>, "", NULL }, - { "loglevel", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleServerSetLogLevelCommand>, "", NULL }, - { "logfilelevel", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleServerSetLogFileLevelCommand>, "", NULL }, - { "motd", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerSetMotdCommand>, "", NULL }, - { "closed", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerSetClosedCommand>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - - static ChatCommand serverCommandTable[] = - { - { "corpses", SEC_GAMEMASTER, true, OldHandler<&ChatHandler::HandleServerCorpsesCommand>, "", NULL }, - { "exit", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleServerExitCommand>, "", NULL }, - { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable }, - { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverIdleShutdownCommandTable }, - { "info", SEC_PLAYER, true, OldHandler<&ChatHandler::HandleServerInfoCommand>, "", NULL }, - { "motd", SEC_PLAYER, true, OldHandler<&ChatHandler::HandleServerMotdCommand>, "", NULL }, - { "plimit", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleServerPLimitCommand>, "", NULL }, - { "restart", SEC_ADMINISTRATOR, true, NULL, "", serverRestartCommandTable }, - { "shutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, - { "set", SEC_ADMINISTRATOR, true, NULL, "", serverSetCommandTable }, - { "togglequerylog", SEC_CONSOLE, true, OldHandler<&ChatHandler::HandleServerToggleQueryLogging>, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - static ChatCommand unbanCommandTable[] = { { "account", SEC_ADMINISTRATOR, true, OldHandler<&ChatHandler::HandleUnBanAccountCommand>, "", NULL }, @@ -331,16 +213,10 @@ ChatCommand* ChatHandler::getCommandTable() static ChatCommand commandTable[] = { - { "character", SEC_GAMEMASTER, true, NULL, "", characterCommandTable}, - { "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable }, { "lookup", SEC_ADMINISTRATOR, true, NULL, "", lookupCommandTable }, { "pdump", SEC_ADMINISTRATOR, true, NULL, "", pdumpCommandTable }, { "guild", SEC_ADMINISTRATOR, true, NULL, "", guildCommandTable }, { "group", SEC_ADMINISTRATOR, false, NULL, "", groupCommandTable }, - { "cast", SEC_ADMINISTRATOR, false, NULL, "", castCommandTable }, - { "reset", SEC_ADMINISTRATOR, true, NULL, "", resetCommandTable }, - { "instance", SEC_ADMINISTRATOR, true, NULL, "", instanceCommandTable }, - { "server", SEC_ADMINISTRATOR, true, NULL, "", serverCommandTable }, { "channel", SEC_ADMINISTRATOR, true, NULL, "", channelCommandTable }, diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index e88914a2daf..bbe138b923d 100755 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -119,10 +119,13 @@ class ChatHandler GameObject* GetNearbyGameObject(); GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid, uint32 entry); - bool HasSentErrorMessage() const { return sentErrorMessage;} - void SetSentErrorMessage(bool val){ sentErrorMessage = val;}; - static bool LoadCommandTable() { return load_command_table;} - static void SetLoadCommandTable(bool val){ load_command_table = val;}; + bool HasSentErrorMessage() const { return sentErrorMessage; } + void SetSentErrorMessage(bool val){ sentErrorMessage = val; } + static bool LoadCommandTable() { return load_command_table; } + static void SetLoadCommandTable(bool val) { load_command_table = val; } + + // cs_character + void HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel); protected: explicit ChatHandler() : m_session(NULL) {} // for CLI subclass @@ -147,26 +150,6 @@ class ChatHandler bool HandleBanListCharacterCommand(const char* args); bool HandleBanListIPCommand(const char* args); - bool HandleCastCommand(const char *args); - bool HandleCastBackCommand(const char *args); - bool HandleCastDistCommand(const char *args); - bool HandleCastSelfCommand(const char *args); - bool HandleCastTargetCommand(const char *args); - bool HandleCastDestCommand(const char *args); - - bool HandleCharacterCustomizeCommand(const char* args); - bool HandleCharacterChangeFactionCommand(const char* args); - bool HandleCharacterChangeRaceCommand(const char * args); - bool HandleCharacterDeletedDeleteCommand(const char* args); - bool HandleCharacterDeletedListCommand(const char* args); - bool HandleCharacterDeletedRestoreCommand(const char* args); - bool HandleCharacterDeletedOldCommand(const char* args); - bool HandleCharacterEraseCommand(const char* args); - bool HandleCharacterLevelCommand(const char* args); - bool HandleCharacterRenameCommand(const char* args); - bool HandleCharacterReputationCommand(const char* args); - bool HandleCharacterTitlesCommand(const char* args); - bool HandleChannelSetOwnership(const char *args); bool HandlePossessCommand(const char* args); @@ -180,16 +163,6 @@ class ChatHandler bool HandleGuildRankCommand(const char* args); bool HandleGuildDeleteCommand(const char* args); - bool HandleInstanceListBindsCommand(const char* args); - bool HandleInstanceUnbindCommand(const char* args); - bool HandleInstanceStatsCommand(const char* args); - bool HandleInstanceSaveDataCommand(const char * args); - - bool HandleListAurasCommand(const char * args); - bool HandleListCreatureCommand(const char* args); - bool HandleListItemCommand(const char* args); - bool HandleListObjectCommand(const char* args); - bool HandleLookupAreaCommand(const char* args); bool HandleLookupCreatureCommand(const char* args); bool HandleLookupEventCommand(const char* args); @@ -211,37 +184,11 @@ class ChatHandler bool HandlePDumpLoadCommand(const char *args); bool HandlePDumpWriteCommand(const char *args); - bool HandleResetAchievementsCommand(const char * args); - bool HandleResetAllCommand(const char * args); - bool HandleResetHonorCommand(const char * args); - bool HandleResetLevelCommand(const char * args); - bool HandleResetSpellsCommand(const char* args); - bool HandleResetStatsCommand(const char * args); - bool HandleResetTalentsCommand(const char* args); - bool HandleSendItemsCommand(const char* args); bool HandleSendMailCommand(const char* args); bool HandleSendMessageCommand(const char * args); bool HandleSendMoneyCommand(const char* args); - bool HandleServerCorpsesCommand(const char* args); - bool HandleServerExitCommand(const char* args); - bool HandleServerIdleRestartCommand(const char* args); - bool HandleServerIdleShutDownCommand(const char* args); - bool HandleServerInfoCommand(const char* args); - bool HandleServerMotdCommand(const char* args); - bool HandleServerPLimitCommand(const char* args); - bool HandleServerRestartCommand(const char* args); - bool HandleServerSetLogLevelCommand(const char* args); - bool HandleServerSetMotdCommand(const char* args); - bool HandleServerShutDownCommand(const char* args); - bool HandleServerShutDownCancelCommand(const char* args); - bool HandleServerSetClosedCommand(const char* args); - bool HandleServerToggleQueryLogging(const char* args); - - bool HandleServerSetLogFileLevelCommand(const char* args); - bool HandleServerSetDiffTimeCommand(const char* args); - bool HandleUnBanAccountCommand(const char* args); bool HandleUnBanAccountByCharCommand(const char* args); bool HandleUnBanCharacterCommand(const char* args); @@ -354,25 +301,8 @@ class ChatHandler bool HandleBanHelper(BanMode mode, char const* args); bool HandleBanInfoHelper(uint32 accountid, char const* accountname); bool HandleUnBanHelper(BanMode mode, char const* args); - void HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel); void HandleLearnSkillRecipesHelper(Player* player, uint32 skill_id); - // Stores informations about a deleted character - struct DeletedInfo - { - uint32 lowguid; ///< the low GUID from the character - std::string name; ///< the character name - uint32 accountId; ///< the account id - std::string accountName; ///< the account name - time_t deleteDate; ///< the date at which the character has been deleted - }; - - typedef std::list<DeletedInfo> DeletedInfoList; - bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString = ""); - std::string GenerateDeletedCharacterGUIDsWhereStr(DeletedInfoList::const_iterator& itr, DeletedInfoList::const_iterator const& itr_end); - void HandleCharacterDeletedListHelper(DeletedInfoList const& foundList); - void HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo); - private: bool _HandleGMTicketResponseAppendCommand(const char* args, bool newLine); diff --git a/src/server/game/Chat/Commands/Level0.cpp b/src/server/game/Chat/Commands/Level0.cpp index b2ac090c313..b05ba9b4194 100755 --- a/src/server/game/Chat/Commands/Level0.cpp +++ b/src/server/game/Chat/Commands/Level0.cpp @@ -80,29 +80,6 @@ bool ChatHandler::HandleStartCommand(const char* /*args*/) return true; } -bool ChatHandler::HandleServerInfoCommand(const char* /*args*/) -{ - uint32 playersNum = sWorld->GetPlayerCount(); - uint32 maxPlayersNum = sWorld->GetMaxPlayerCount(); - uint32 activeClientsNum = sWorld->GetActiveSessionCount(); - uint32 queuedClientsNum = sWorld->GetQueuedSessionCount(); - uint32 maxActiveClientsNum = sWorld->GetMaxActiveSessionCount(); - uint32 maxQueuedClientsNum = sWorld->GetMaxQueuedSessionCount(); - std::string uptime = secsToTimeString(sWorld->GetUptime()); - uint32 updateTime = sWorld->GetUpdateTime(); - - SendSysMessage(_FULLVERSION); - PSendSysMessage(LANG_CONNECTED_PLAYERS, playersNum, maxPlayersNum); - PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); - PSendSysMessage(LANG_UPTIME, uptime.c_str()); - PSendSysMessage(LANG_UPDATE_DIFF, updateTime); - //! Can't use sWorld->ShutdownMsg here in case of console command - if (sWorld->IsShuttingDown()) - PSendSysMessage(LANG_SHUTDOWN_TIMELEFT, secsToTimeString(sWorld->GetShutDownTimeLeft()).c_str()); - - return true; -} - bool ChatHandler::HandleDismountCommand(const char* /*args*/) { Player* player = m_session->GetPlayer(); @@ -150,10 +127,3 @@ bool ChatHandler::HandleSaveCommand(const char* /*args*/) return true; } -/// Display the 'Message of the day' for the realm -bool ChatHandler::HandleServerMotdCommand(const char* /*args*/) -{ - PSendSysMessage(LANG_MOTD_CURRENT, sWorld->GetMotd()); - return true; -} - diff --git a/src/server/game/Chat/Commands/Level2.cpp b/src/server/game/Chat/Commands/Level2.cpp index 4359c5ff20c..b1e13b7d92d 100755 --- a/src/server/game/Chat/Commands/Level2.cpp +++ b/src/server/game/Chat/Commands/Level2.cpp @@ -458,190 +458,6 @@ bool ChatHandler::HandlePInfoCommand(const char* args) return true; } -//rename characters -bool ChatHandler::HandleCharacterRenameCommand(const char* args) -{ - Player* target; - uint64 targetGuid; - std::string targetName; - if (!extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) - return false; - - if (target) - { - // check online security - if (HasLowerSecurity(target, 0)) - return false; - - PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_RENAME); - } - else - { - // check offline security - if (HasLowerSecurity(NULL, targetGuid)) - return false; - - std::string oldNameLink = playerLink(targetName); - - PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - - stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - - CharacterDatabase.Execute(stmt); - } - - return true; -} - -// customize characters -bool ChatHandler::HandleCharacterCustomizeCommand(const char* args) -{ - Player* target; - uint64 targetGuid; - std::string targetName; - if (!extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) - return false; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - - stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE)); - - if (target) - { - PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); - - stmt->setUInt32(1, target->GetGUIDLow()); - } - else - { - std::string oldNameLink = playerLink(targetName); - - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - - PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); - } - - CharacterDatabase.Execute(stmt); - - return true; -} - -bool ChatHandler::HandleCharacterChangeFactionCommand(const char* args) -{ - Player* target; - uint64 targetGuid; - std::string targetName; - - if (!extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) - return false; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - - stmt->setUInt16(0, uint16(AT_LOGIN_CHANGE_FACTION)); - - if (target) - { - PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION); - - stmt->setUInt32(1, target->GetGUIDLow()); - } - else - { - std::string oldNameLink = playerLink(targetName); - - PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); - - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - } - - CharacterDatabase.Execute(stmt); - - return true; -} - -bool ChatHandler::HandleCharacterChangeRaceCommand(const char * args) -{ - Player* target; - uint64 targetGuid; - std::string targetName; - if (!extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) - return false; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - - stmt->setUInt16(0, uint16(AT_LOGIN_CHANGE_RACE)); - - if (target) - { - // TODO : add text into database - PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str()); - target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE); - - stmt->setUInt32(1, target->GetGUIDLow()); - } - else - { - std::string oldNameLink = playerLink(targetName); - - // TODO : add text into database - PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); - - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - } - - CharacterDatabase.Execute(stmt); - - return true; -} - -bool ChatHandler::HandleCharacterReputationCommand(const char* args) -{ - Player* target; - if (!extractPlayerTarget((char*)args, &target)) - return false; - - LocaleConstant loc = GetSessionDbcLocale(); - - FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); - for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) - { - const FactionState& faction = itr->second; - FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID); - char const* factionName = factionEntry ? factionEntry->name : "#Not found#"; - ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); - std::string rankName = GetTrinityString(ReputationRankStrIndex[rank]); - std::ostringstream ss; - if (m_session) - ss << faction.ID << " - |cffffffff|Hfaction:" << faction.ID << "|h[" << factionName << ' ' << localeNames[loc] << "]|h|r"; - else - ss << faction.ID << " - " << factionName << ' ' << localeNames[loc]; - - ss << ' ' << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ')'; - - if (faction.Flags & FACTION_FLAG_VISIBLE) - ss << GetTrinityString(LANG_FACTION_VISIBLE); - if (faction.Flags & FACTION_FLAG_AT_WAR) - ss << GetTrinityString(LANG_FACTION_ATWAR); - if (faction.Flags & FACTION_FLAG_PEACE_FORCED) - ss << GetTrinityString(LANG_FACTION_PEACE_FORCED); - if (faction.Flags & FACTION_FLAG_HIDDEN) - ss << GetTrinityString(LANG_FACTION_HIDDEN); - if (faction.Flags & FACTION_FLAG_INVISIBLE_FORCED) - ss << GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); - if (faction.Flags & FACTION_FLAG_INACTIVE) - ss << GetTrinityString(LANG_FACTION_INACTIVE); - - SendSysMessage(ss.str().c_str()); - } - return true; -} - bool ChatHandler::HandleLookupEventCommand(const char* args) { if (!*args) @@ -848,13 +664,6 @@ bool ChatHandler::LookupPlayerSearchCommand(PreparedQueryResult result, int32 li return true; } -/// Triggering corpses expire check in world -bool ChatHandler::HandleServerCorpsesCommand(const char* /*args*/) -{ - sObjectAccessor->RemoveOldCorpses(); - return true; -} - bool ChatHandler::HandleRepairitemsCommand(const char* args) { Player* target; @@ -1130,43 +939,3 @@ bool ChatHandler::HandleLookupTitleCommand(const char* args) SendSysMessage(LANG_COMMAND_NOTITLEFOUND); return true; } - -bool ChatHandler::HandleCharacterTitlesCommand(const char* args) -{ - if (!*args) - return false; - - Player* target; - if (!extractPlayerTarget((char*)args, &target)) - return false; - - LocaleConstant loc = GetSessionDbcLocale(); - char const* targetName = target->GetName(); - char const* knownStr = GetTrinityString(LANG_KNOWN); - - // Search in CharTitles.dbc - for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) - { - CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); - if (titleInfo && target->HasTitle(titleInfo)) - { - std::string name = titleInfo->name; - if (name.empty()) - continue; - - char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index - ? GetTrinityString(LANG_ACTIVE) - : ""; - - char titleNameStr[80]; - snprintf(titleNameStr, 80, name.c_str(), targetName); - - // send title in "id (idx:idx) - [namedlink locale]" format - if (m_session) - PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->bit_index, id, titleNameStr, localeNames[loc], knownStr, activeStr); - else - PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->bit_index, name.c_str(), localeNames[loc], knownStr, activeStr); - } - } - return true; -} diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index 2ae7e73b828..0386b8786b6 100755 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -385,365 +385,6 @@ bool ChatHandler::HandleAddItemSetCommand(const char *args) return true; } -bool ChatHandler::HandleListItemCommand(const char *args) -{ - if (!*args) - return false; - - char* cId = extractKeyFromLink((char*)args, "Hitem"); - if (!cId) - return false; - - uint32 item_id = atol(cId); - if (!item_id) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id); - if (!itemProto) - { - PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, item_id); - SetSentErrorMessage(true); - return false; - } - - char* c_count = strtok(NULL, " "); - int _count = c_count ? atol(c_count) : 10; - - if (_count < 0) - return false; - uint32 count = uint32(_count); - - PreparedQueryResult result; - - // inventory case - uint32 inv_count = 0; - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM); - stmt->setUInt32(0, item_id); - result = CharacterDatabase.Query(stmt); - - if (result) - inv_count = (*result)[0].GetUInt64(); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY); - stmt->setUInt32(0, item_id); - stmt->setUInt32(1, count); - result = CharacterDatabase.Query(stmt); - - if (result) - { - do - { - Field* fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 item_bag = fields[1].GetUInt32(); - uint8 item_slot = fields[2].GetUInt8(); - uint32 owner_guid = fields[3].GetUInt32(); - uint32 owner_acc = fields[4].GetUInt32(); - std::string owner_name = fields[5].GetString(); - - char const* item_pos = 0; - if (Player::IsEquipmentPos(item_bag, item_slot)) - item_pos = "[equipped]"; - else if (Player::IsInventoryPos(item_bag, item_slot)) - item_pos = "[in inventory]"; - else if (Player::IsBankPos(item_bag, item_slot)) - item_pos = "[in bank]"; - else - item_pos = ""; - - PSendSysMessage(LANG_ITEMLIST_SLOT, item_guid, owner_name.c_str(), owner_guid, owner_acc, item_pos); - } - while (result->NextRow()); - - uint32 res_count = uint32(result->GetRowCount()); - - if (count > res_count) - count -= res_count; - else if (count) - count = 0; - } - - // mail case - uint32 mail_count = 0; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT_ITEM); - stmt->setUInt32(0, item_id); - result = CharacterDatabase.Query(stmt); - - if (result) - mail_count = (*result)[0].GetUInt64(); - - if (count > 0) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_ITEMS_BY_ENTRY); - stmt->setUInt32(0, item_id); - stmt->setUInt32(1, count); - result = CharacterDatabase.Query(stmt); - } - else - result = PreparedQueryResult(NULL); - - if (result) - { - do - { - Field* fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 item_s = fields[1].GetUInt32(); - uint32 item_r = fields[2].GetUInt32(); - uint32 item_s_acc = fields[3].GetUInt32(); - std::string item_s_name = fields[4].GetString(); - uint32 item_r_acc = fields[5].GetUInt32(); - std::string item_r_name = fields[6].GetString(); - - char const* item_pos = "[in mail]"; - - PSendSysMessage(LANG_ITEMLIST_MAIL, item_guid, item_s_name.c_str(), item_s, item_s_acc, item_r_name.c_str(), item_r, item_r_acc, item_pos); - } - while (result->NextRow()); - - uint32 res_count = uint32(result->GetRowCount()); - - if (count > res_count) - count -= res_count; - else if (count) - count = 0; - } - - // auction case - uint32 auc_count = 0; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM); - stmt->setUInt32(0, item_id); - result = CharacterDatabase.Query(stmt); - - if (result) - auc_count = (*result)[0].GetUInt64(); - - if (count > 0) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONHOUSE_ITEM_BY_ENTRY); - stmt->setUInt32(0, item_id); - stmt->setUInt32(1, count); - result = CharacterDatabase.Query(stmt); - } - else - result = PreparedQueryResult(NULL); - - if (result) - { - do - { - Field* fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 owner = fields[1].GetUInt32(); - uint32 owner_acc = fields[2].GetUInt32(); - std::string owner_name = fields[3].GetString(); - - char const* item_pos = "[in auction]"; - - PSendSysMessage(LANG_ITEMLIST_AUCTION, item_guid, owner_name.c_str(), owner, owner_acc, item_pos); - } - while (result->NextRow()); - } - - // guild bank case - uint32 guild_count = 0; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM); - stmt->setUInt32(0, item_id); - result = CharacterDatabase.Query(stmt); - - if (result) - guild_count = (*result)[0].GetUInt64(); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_ITEM_BY_ENTRY); - stmt->setUInt32(0, item_id); - stmt->setUInt32(1, count); - result = CharacterDatabase.Query(stmt); - - if (result) - { - do - { - Field* fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 guild_guid = fields[1].GetUInt32(); - std::string guild_name = fields[2].GetString(); - - char const* item_pos = "[in guild bank]"; - - PSendSysMessage(LANG_ITEMLIST_GUILD, item_guid, guild_name.c_str(), guild_guid, item_pos); - } - while (result->NextRow()); - - uint32 res_count = uint32(result->GetRowCount()); - - if (count > res_count) - count -= res_count; - else if (count) - count = 0; - } - - if (inv_count + mail_count + auc_count + guild_count == 0) - { - SendSysMessage(LANG_COMMAND_NOITEMFOUND); - SetSentErrorMessage(true); - return false; - } - - PSendSysMessage(LANG_COMMAND_LISTITEMMESSAGE, item_id, inv_count + mail_count + auc_count + guild_count, inv_count, mail_count, auc_count, guild_count); - return true; -} - -bool ChatHandler::HandleListObjectCommand(const char *args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args, "Hgameobject_entry"); - if (!cId) - return false; - - uint32 go_id = atol(cId); - if (!go_id) - { - PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); - SetSentErrorMessage(true); - return false; - } - - GameObjectTemplate const* gInfo = sObjectMgr->GetGameObjectTemplate(go_id); - if (!gInfo) - { - PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, go_id); - SetSentErrorMessage(true); - return false; - } - - char* c_count = strtok(NULL, " "); - int count = c_count ? atol(c_count) : 10; - - if (count < 0) - return false; - - QueryResult result; - - uint32 obj_count = 0; - result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'", go_id); - if (result) - obj_count = (*result)[0].GetUInt64(); - - if (m_session) - { - Player* player = m_session->GetPlayer(); - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, id, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", - player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), go_id, uint32(count)); - } - else - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, id FROM gameobject WHERE id = '%u' LIMIT %u", - go_id, uint32(count)); - - if (result) - { - do - { - Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - float x = fields[1].GetFloat(); - float y = fields[2].GetFloat(); - float z = fields[3].GetFloat(); - int mapid = fields[4].GetUInt16(); - uint32 entry = fields[5].GetUInt32(); - - if (m_session) - PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapid); - else - PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapid); - } while (result->NextRow()); - } - - PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE, go_id, obj_count); - return true; -} - -bool ChatHandler::HandleListCreatureCommand(const char *args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r - char* cId = extractKeyFromLink((char*)args, "Hcreature_entry"); - if (!cId) - return false; - - uint32 cr_id = atol(cId); - if (!cr_id) - { - PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); - SetSentErrorMessage(true); - return false; - } - - CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(cr_id); - if (!cInfo) - { - PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, cr_id); - SetSentErrorMessage(true); - return false; - } - - char* c_count = strtok(NULL, " "); - int count = c_count ? atol(c_count) : 10; - - if (count < 0) - return false; - - QueryResult result; - - uint32 cr_count = 0; - result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'", cr_id); - if (result) - cr_count = (*result)[0].GetUInt64(); - - if (m_session) - { - Player* player = m_session->GetPlayer(); - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM creature WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", - player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), cr_id, uint32(count)); - } - else - result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM creature WHERE id = '%u' LIMIT %u", - cr_id, uint32(count)); - - if (result) - { - do - { - Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - float x = fields[1].GetFloat(); - float y = fields[2].GetFloat(); - float z = fields[3].GetFloat(); - int mapid = fields[4].GetUInt16(); - - if (m_session) - PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapid); - else - PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapid); - } while (result->NextRow()); - } - - PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE, cr_id, cr_count); - return true; -} - bool ChatHandler::HandleLookupItemCommand(const char *args) { if (!*args) @@ -1144,15 +785,20 @@ bool ChatHandler::HandleLookupQuestCommand(const char *args) { QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - if (status == QUEST_STATUS_COMPLETE) + switch (status) { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else + case QUEST_STATUS_COMPLETE: statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + break; + case QUEST_STATUS_INCOMPLETE: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + break; + case QUEST_STATUS_REWARDED: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + break; + default: + break; } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); } if (m_session) @@ -1187,15 +833,20 @@ bool ChatHandler::HandleLookupQuestCommand(const char *args) { QuestStatus status = target->GetQuestStatus(qinfo->GetQuestId()); - if (status == QUEST_STATUS_COMPLETE) + switch (status) { - if (target->GetQuestRewardStatus(qinfo->GetQuestId())) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); - else + case QUEST_STATUS_COMPLETE: statusStr = GetTrinityString(LANG_COMMAND_QUEST_COMPLETE); + break; + case QUEST_STATUS_INCOMPLETE: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); + break; + case QUEST_STATUS_REWARDED: + statusStr = GetTrinityString(LANG_COMMAND_QUEST_REWARDED); + break; + default: + break; } - else if (status == QUEST_STATUS_INCOMPLETE) - statusStr = GetTrinityString(LANG_COMMAND_QUEST_ACTIVE); } if (m_session) @@ -1730,7 +1381,7 @@ bool ChatHandler::HandleGuildUninviteCommand(const char *args) if (!extractPlayerTarget((char*)args, &target, &target_guid)) return false; - uint32 glId = target ? target->GetGuildId() : Player::GetGuildIdFromGuid(target_guid); + uint32 glId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(target_guid); if (!glId) return false; @@ -1756,7 +1407,7 @@ bool ChatHandler::HandleGuildRankCommand(const char *args) if (!extractPlayerTarget(nameStr, &target, &target_guid, &target_name)) return false; - uint32 glId = target ? target->GetGuildId() : Player::GetGuildIdFromGuid(target_guid); + uint32 glId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(target_guid); if (!glId) return false; @@ -2188,47 +1839,6 @@ void ChatHandler::HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 } } -bool ChatHandler::HandleCharacterLevelCommand(const char *args) -{ - char* nameStr; - char* levelStr; - extractOptFirstArg((char*)args, &nameStr, &levelStr); - if (!levelStr) - return false; - - // exception opt second arg: .character level $name - if (isalpha(levelStr[0])) - { - nameStr = levelStr; - levelStr = NULL; // current level will used - } - - Player* target; - uint64 target_guid; - std::string target_name; - if (!extractPlayerTarget(nameStr, &target, &target_guid, &target_name)) - return false; - - int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(target_guid); - int32 newlevel = levelStr ? atoi(levelStr) : oldlevel; - - if (newlevel < 1) - return false; // invalid level - - if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level - newlevel = STRONG_MAX_LEVEL; - - HandleCharacterLevel(target, target_guid, oldlevel, newlevel); - - if (!m_session || m_session->GetPlayer() != target) // including player == NULL - { - std::string nameLink = playerLink(target_name); - PSendSysMessage(LANG_YOU_CHANGE_LVL, nameLink.c_str(), newlevel); - } - - return true; -} - bool ChatHandler::HandleLevelUpCommand(const char *args) { char* nameStr; @@ -2380,457 +1990,6 @@ bool ChatHandler::HandleChangeWeather(const char *args) return true; } -bool ChatHandler::HandleListAurasCommand (const char * /*args*/) -{ - Unit* unit = getSelectedUnit(); - if (!unit) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - char const* talentStr = GetTrinityString(LANG_TALENT); - char const* passiveStr = GetTrinityString(LANG_PASSIVE); - - Unit::AuraApplicationMap const& uAuras = unit->GetAppliedAuras(); - PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); - for (Unit::AuraApplicationMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) - { - bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; - - AuraApplication const* aurApp = itr->second; - Aura const* aura = aurApp->GetBase(); - char const* name = aura->GetSpellInfo()->SpellName; - - std::ostringstream ss_name; - ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r"; - - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), (m_session ? ss_name.str().c_str() : name), - aurApp->GetEffectMask(), aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), - aura->GetDuration(), aura->GetMaxDuration(), (aura->IsPassive() ? passiveStr : ""), - (talent ? talentStr : ""), IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature", - GUID_LOPART(aura->GetCasterGUID())); - } - for (uint16 i = 0; i < TOTAL_AURAS; ++i) - { - Unit::AuraEffectList const& uAuraList = unit->GetAuraEffectsByType(AuraType(i)); - if (uAuraList.empty()) - continue; - - PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); - for (Unit::AuraEffectList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) - { - PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), - (*itr)->GetAmount()); - } - } - return true; -} - -bool ChatHandler::HandleResetAchievementsCommand (const char * args) -{ - Player* target; - uint64 target_guid; - if (!extractPlayerTarget((char*)args, &target, &target_guid)) - return false; - - if (target) - target->GetAchievementMgr().Reset(); - else - AchievementMgr::DeleteFromDB(GUID_LOPART(target_guid)); - - return true; -} - -bool ChatHandler::HandleResetHonorCommand (const char * args) -{ - Player* target; - if (!extractPlayerTarget((char*)args, &target)) - return false; - - target->SetCurrency(CURRENCY_TYPE_HONOR_POINTS, 0); - target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); - target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); - target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); - - return true; -} - -static bool HandleResetStatsOrLevelHelper(Player* player) -{ - ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(player->getClass()); - if (!cEntry) - { - sLog->outError("Class %u not found in DBC (Wrong DBC files?)", player->getClass()); - return false; - } - - uint8 powertype = cEntry->powerType; - - // reset m_form if no aura - if (!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) - player->SetShapeshiftForm(FORM_NONE); - - player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); - player->SetFloatValue(UNIT_FIELD_COMBATREACH, DEFAULT_COMBAT_REACH); - - player->setFactionForRace(player->getRace()); - - player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powertype << 24))); - - // reset only if player not in some form; - if (player->GetShapeshiftForm() == FORM_NONE) - player->InitDisplayIds(); - - player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); - - player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); - - //-1 is default value - player->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); - - //player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000); - return true; -} - -bool ChatHandler::HandleResetLevelCommand(const char * args) -{ - Player* target; - if (!extractPlayerTarget((char*)args, &target)) - return false; - - if (!HandleResetStatsOrLevelHelper(target)) - return false; - - uint8 oldLevel = target->getLevel(); - - // set starting level - uint32 start_level = target->getClass() != CLASS_DEATH_KNIGHT - ? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL) - : sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); - - target->_ApplyAllLevelScaleItemMods(false); - target->SetLevel(start_level); - target->InitRunes(); - target->InitStatsForLevel(true); - target->InitTaxiNodesForLevel(); - target->InitGlyphsForLevel(); - target->InitTalentForLevel(); - target->SetUInt32Value(PLAYER_XP, 0); - - target->_ApplyAllLevelScaleItemMods(true); - - // reset level for pet - if (Pet* pet = target->GetPet()) - pet->SynchronizeLevelWithOwner(); - - sScriptMgr->OnPlayerLevelChanged(target, oldLevel); - - return true; -} - -bool ChatHandler::HandleResetStatsCommand(const char * args) -{ - Player* target; - if (!extractPlayerTarget((char*)args, &target)) - return false; - - if (!HandleResetStatsOrLevelHelper(target)) - return false; - - target->InitRunes(); - target->InitStatsForLevel(true); - target->InitTaxiNodesForLevel(); - target->InitGlyphsForLevel(); - target->InitTalentForLevel(); - - return true; -} - -bool ChatHandler::HandleResetSpellsCommand(const char* args) -{ - Player* target; - uint64 targetGuid; - std::string targetName; - if (!extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) - return false; - - if (target) - { - target->resetSpells(/* bool myClassOnly */); - - ChatHandler(target).SendSysMessage(LANG_RESET_SPELLS); - if (!m_session || m_session->GetPlayer() != target) - PSendSysMessage(LANG_RESET_SPELLS_ONLINE, GetNameLink(target).c_str()); - } - else - { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - - stmt->setUInt16(0, uint16(AT_LOGIN_RESET_SPELLS)); - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - - CharacterDatabase.Execute(stmt); - - PSendSysMessage(LANG_RESET_SPELLS_OFFLINE, targetName.c_str()); - } - - return true; -} - -bool ChatHandler::HandleResetTalentsCommand(const char* args) -{ - Player* target; - uint64 targetGuid; - std::string targetName; - if (!extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) - { - // Try reset talents as Hunter Pet - Creature* creature = getSelectedCreature(); - if (!*args && creature && creature->isPet()) - { - Unit* owner = creature->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER && creature->ToPet()->IsPermanentPetFor(owner->ToPlayer())) - { - creature->ToPet()->resetTalents(); - owner->ToPlayer()->SendTalentsInfoData(true); - - ChatHandler(owner->ToPlayer()).SendSysMessage(LANG_RESET_PET_TALENTS); - if (!m_session || m_session->GetPlayer() != owner->ToPlayer()) - PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE, GetNameLink(owner->ToPlayer()).c_str()); - } - return true; - } - - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (target) - { - target->ResetTalents(true); - target->SendTalentsInfoData(false); - ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); - if (!m_session || m_session->GetPlayer() != target) - PSendSysMessage(LANG_RESET_TALENTS_ONLINE, GetNameLink(target).c_str()); - - Pet* pet = target->GetPet(); - Pet::resetTalentsForAllPetsOf(target, pet); - if (pet) - target->SendTalentsInfoData(true); - return true; - } - else if (targetGuid) - { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - - stmt->setUInt16(0, uint16(AT_LOGIN_NONE | AT_LOGIN_RESET_PET_TALENTS)); - stmt->setUInt32(1, GUID_LOPART(targetGuid)); - - CharacterDatabase.Execute(stmt); - - std::string nameLink = playerLink(targetName); - PSendSysMessage(LANG_RESET_TALENTS_OFFLINE, nameLink.c_str()); - return true; - } - - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; -} - -bool ChatHandler::HandleResetAllCommand(const char * args) -{ - if (!*args) - return false; - - std::string casename = args; - - AtLoginFlags atLogin; - - // Command specially created as single command to prevent using short case names - if (casename == "spells") - { - atLogin = AT_LOGIN_RESET_SPELLS; - sWorld->SendWorldText(LANG_RESETALL_SPELLS); - if (!m_session) - SendSysMessage(LANG_RESETALL_SPELLS); - } - else if (casename == "talents") - { - atLogin = AtLoginFlags(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS); - sWorld->SendWorldText(LANG_RESETALL_TALENTS); - if (!m_session) - SendSysMessage(LANG_RESETALL_TALENTS); - } - else - { - PSendSysMessage(LANG_RESETALL_UNKNOWN_CASE, args); - SetSentErrorMessage(true); - return false; - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ALL_AT_LOGIN_FLAGS); - - stmt->setUInt16(0, uint16(atLogin)); - - CharacterDatabase.Execute(stmt); - - TRINITY_READ_GUARD(HashMapHolder<Player>::LockType, *HashMapHolder<Player>::GetLock()); - HashMapHolder<Player>::MapType const& plist = sObjectAccessor->GetPlayers(); - for (HashMapHolder<Player>::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) - itr->second->SetAtLoginFlag(atLogin); - - return true; -} - -bool ChatHandler::HandleServerShutDownCancelCommand(const char* /*args*/) -{ - sWorld->ShutdownCancel(); - return true; -} - -bool ChatHandler::HandleServerShutDownCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0')) || time < 0) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld->ShutdownServ(time, 0, exitcode); - } - else - sWorld->ShutdownServ(time, 0, SHUTDOWN_EXIT_CODE); - return true; -} - -bool ChatHandler::HandleServerRestartCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0')) || time < 0) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART, exitcode); - } - else - sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); - return true; -} - -bool ChatHandler::HandleServerIdleRestartCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0')) || time < 0) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE, exitcode); - } - else - sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART|SHUTDOWN_MASK_IDLE, RESTART_EXIT_CODE); - return true; -} - -bool ChatHandler::HandleServerIdleShutDownCommand(const char *args) -{ - if (!*args) - return false; - - char* time_str = strtok ((char*) args, " "); - char* exitcode_str = strtok (NULL, ""); - - int32 time = atoi (time_str); - - ///- Prevent interpret wrong arg value as 0 secs shutdown time - if ((time == 0 && (time_str[0] != '0' || time_str[1] != '\0')) || time < 0) - return false; - - if (exitcode_str) - { - int32 exitcode = atoi (exitcode_str); - - // Handle atoi() errors - if (exitcode == 0 && (exitcode_str[0] != '0' || exitcode_str[1] != '\0')) - return false; - - // Exit code should be in range of 0-125, 126-255 is used - // in many shells for their own return codes and code > 255 - // is not supported in many others - if (exitcode < 0 || exitcode > 125) - return false; - - sWorld->ShutdownServ(time, SHUTDOWN_MASK_IDLE, exitcode); - } - else - sWorld->ShutdownServ(time, SHUTDOWN_MASK_IDLE, SHUTDOWN_EXIT_CODE); - return true; -} bool ChatHandler::HandleBanAccountCommand(const char *args) { @@ -3752,277 +2911,6 @@ bool ChatHandler::HandleMovegensCommand(const char* /*args*/) return true; } -bool ChatHandler::HandleServerPLimitCommand(const char *args) -{ - if (*args) - { - char* param = strtok((char*)args, " "); - if (!param) - return false; - - int l = strlen(param); - - if (strncmp(param, "player", l) == 0) - sWorld->SetPlayerSecurityLimit(SEC_PLAYER); - else if (strncmp(param, "moderator", l) == 0) - sWorld->SetPlayerSecurityLimit(SEC_MODERATOR); - else if (strncmp(param, "gamemaster", l) == 0) - sWorld->SetPlayerSecurityLimit(SEC_GAMEMASTER); - else if (strncmp(param, "administrator", l) == 0) - sWorld->SetPlayerSecurityLimit(SEC_ADMINISTRATOR); - else if (strncmp(param, "reset", l) == 0) - { - sWorld->SetPlayerAmountLimit(ConfigMgr::GetIntDefault("PlayerLimit", 100)); - sWorld->LoadDBAllowedSecurityLevel(); - } - else - { - int val = atoi(param); - if (val < 0) - sWorld->SetPlayerSecurityLimit(AccountTypes(uint32(-val))); - else - sWorld->SetPlayerAmountLimit(uint32(val)); - } - } - - uint32 pLimit = sWorld->GetPlayerAmountLimit(); - AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit(); - char const* secName = ""; - switch (allowedAccountType) - { - case SEC_PLAYER: secName = "Player"; break; - case SEC_MODERATOR: secName = "Moderator"; break; - case SEC_GAMEMASTER: secName = "Gamemaster"; break; - case SEC_ADMINISTRATOR: secName = "Administrator"; break; - default: secName = "<unknown>"; break; - } - - PSendSysMessage("Player limits: amount %u, min. security level %s.", pLimit, secName); - - return true; -} - -bool ChatHandler::HandleCastCommand(const char *args) -{ - if (!*args) - return false; - - Unit* target = getSelectedUnit(); - - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell) - return false; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); - if (!spellInfo) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - if (!SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell); - SetSentErrorMessage(true); - return false; - } - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str, "triggered", l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - m_session->GetPlayer()->CastSpell(target, spell, triggered); - - return true; -} - -bool ChatHandler::HandleCastBackCommand(const char *args) -{ - Creature* caster = getSelectedCreature(); - - if (!caster) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell || !sSpellMgr->GetSpellInfo(spell)) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str, "triggered", l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - caster->CastSpell(m_session->GetPlayer(), spell, triggered); - - return true; -} - -bool ChatHandler::HandleCastDistCommand(const char *args) -{ - if (!*args) - return false; - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell) - return false; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); - if (!spellInfo) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - if (!SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell); - SetSentErrorMessage(true); - return false; - } - - char *distStr = strtok(NULL, " "); - - float dist = 0; - - if (distStr) - sscanf(distStr, "%f", &dist); - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str, "triggered", l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - float x, y, z; - m_session->GetPlayer()->GetClosePoint(x, y, z, dist); - - m_session->GetPlayer()->CastSpell(x, y, z, spell, triggered); - return true; -} - -bool ChatHandler::HandleCastTargetCommand(const char *args) -{ - Creature* caster = getSelectedCreature(); - - if (!caster) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - if (!caster->getVictim()) - { - SendSysMessage(LANG_SELECTED_TARGET_NOT_HAVE_VICTIM); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell || !sSpellMgr->GetSpellInfo(spell)) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str, "triggered", l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - caster->CastSpell(caster->getVictim(), spell, triggered); - - return true; -} - -bool ChatHandler::HandleCastDestCommand(const char *args) -{ - Unit* caster = getSelectedUnit(); - if (!caster) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell || !sSpellMgr->GetSpellInfo(spell)) - { - PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - SetSentErrorMessage(true); - return false; - } - - char* px = strtok(NULL, " "); - char* py = strtok(NULL, " "); - char* pz = strtok(NULL, " "); - - if (!px || !py || !pz) - return false; - - float x = (float)atof(px); - float y = (float)atof(py); - float z = (float)atof(pz); - - char* trig_str = strtok(NULL, " "); - if (trig_str) - { - int l = strlen(trig_str); - if (strncmp(trig_str, "triggered", l) != 0) - return false; - } - - bool triggered = (trig_str != NULL); - - caster->CastSpell(x, y, z, spell, triggered); - - return true; -} - /* ComeToMe command REQUIRED for 3rd party scripting library to have access to PointMovementGenerator Without this function 3rd party scripting library will get linking errors (unresolved external) @@ -4049,196 +2937,6 @@ bool ChatHandler::HandleComeToMeCommand(const char *args) return true; } -bool ChatHandler::HandleCastSelfCommand(const char *args) -{ - if (!*args) - return false; - - Unit* target = getSelectedUnit(); - - if (!target) - { - SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - SetSentErrorMessage(true); - return false; - } - - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form - uint32 spell = extractSpellIdFromLink((char*)args); - if (!spell) - return false; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell); - if (!spellInfo) - return false; - - if (!SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer())) - { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell); - SetSentErrorMessage(true); - return false; - } - - target->CastSpell(target, spell, false); - - return true; -} - -std::string GetTimeString(uint64 time) -{ - uint64 days = time / DAY, hours = (time % DAY) / HOUR, minute = (time % HOUR) / MINUTE; - std::ostringstream ss; - if (days) ss << days << "d "; - if (hours) ss << hours << "h "; - ss << minute << 'm'; - return ss.str(); -} - -bool ChatHandler::HandleInstanceListBindsCommand(const char* /*args*/) -{ - Player* player = getSelectedPlayer(); - if (!player) player = m_session->GetPlayer(); - uint32 counter = 0; - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); - for (Player::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) - { - InstanceSave* save = itr->second.save; - std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - counter++; - } - } - PSendSysMessage("player binds: %d", counter); - counter = 0; - Group* group = player->GetGroup(); - if (group) - { - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - Group::BoundInstancesMap &binds = group->GetBoundInstances(Difficulty(i)); - for (Group::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) - { - InstanceSave* save = itr->second.save; - std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - counter++; - } - } - } - PSendSysMessage("group binds: %d", counter); - - return true; -} - -bool ChatHandler::HandleInstanceUnbindCommand(const char *args) -{ - if (!*args) - return false; - - Player* player = getSelectedPlayer(); - if (!player) - player = m_session->GetPlayer(); - - char* map = strtok((char*)args, " "); - char* pDiff = strtok(NULL, " "); - int8 diff = -1; - if (pDiff) - diff = atoi(pDiff); - uint16 counter = 0; - uint16 MapId = 0; - - if (strcmp(map, "all")) - { - MapId = uint16(atoi(map)); - if (!MapId) - return false; - } - - for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) - { - Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); - for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) - { - InstanceSave* save = itr->second.save; - if (itr->first != player->GetMapId() && (!MapId || MapId == itr->first) && (diff == -1 || diff == save->GetDifficulty())) - { - std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); - PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); - player->UnbindInstance(itr, Difficulty(i)); - counter++; - } - else - ++itr; - } - } - PSendSysMessage("instances unbound: %d", counter); - return true; -} - -bool ChatHandler::HandleInstanceStatsCommand(const char* /*args*/) -{ - PSendSysMessage("instances loaded: %d", sMapMgr->GetNumInstances()); - PSendSysMessage("players in instances: %d", sMapMgr->GetNumPlayersInInstances()); - PSendSysMessage("instance saves: %d", sInstanceSaveMgr->GetNumInstanceSaves()); - PSendSysMessage("players bound: %d", sInstanceSaveMgr->GetNumBoundPlayersTotal()); - PSendSysMessage("groups bound: %d", sInstanceSaveMgr->GetNumBoundGroupsTotal()); - return true; -} - -bool ChatHandler::HandleInstanceSaveDataCommand(const char * /*args*/) -{ - Player* player = m_session->GetPlayer(); - - Map* map = player->GetMap(); - if (!map->IsDungeon()) - { - PSendSysMessage("Map is not a dungeon."); - SetSentErrorMessage(true); - return false; - } - - if (!((InstanceMap*)map)->GetInstanceScript()) - { - PSendSysMessage("Map has no instance data."); - SetSentErrorMessage(true); - return false; - } - - ((InstanceMap*)map)->GetInstanceScript()->SaveToDB(); - return true; -} - -/// Define the 'Message of the day' for the realm -bool ChatHandler::HandleServerSetMotdCommand(const char *args) -{ - sWorld->SetMotd(args); - PSendSysMessage(LANG_MOTD_NEW, args); - return true; -} - -/// Set whether we accept new clients -bool ChatHandler::HandleServerSetClosedCommand(const char *args) -{ - if (strncmp(args, "on", 3) == 0) - { - SendSysMessage(LANG_WORLD_CLOSED); - sWorld->SetClosed(true); - return true; - } - else if (strncmp(args, "off", 4) == 0) - { - SendSysMessage(LANG_WORLD_OPENED); - sWorld->SetClosed(false); - return true; - } - - SendSysMessage(LANG_USE_BOL); - SetSentErrorMessage(true); - return false; -} - //Send items by mail bool ChatHandler::HandleSendItemsCommand(const char *args) { diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index 9737d4584ea..0c43c9ece0e 100755 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -354,7 +354,9 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* attacker, HostileR // list sorted and and we check current target, then this is best case if (currentVictim == currentRef || currentRef->getThreat() <= 1.1f * currentVictim->getThreat()) { - currentRef = currentVictim; // for second case + if (currentVictim != currentRef && attacker->canCreatureAttack(currentVictim->getTarget())) + currentRef = currentVictim; // for second case, if currentvictim is attackable + found = true; break; } diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 4176d9f605b..9f534ab697d 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -441,7 +441,7 @@ uint32 Condition::GetSearcherTypeMaskForCondition() uint32 Condition::GetMaxAvailableConditionTargets() { // returns number of targets which are available for given source type - switch(SourceType) + switch (SourceType) { case CONDITION_SOURCE_TYPE_SPELL: case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET: diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index dcd189a05cb..e032335c3bc 100755 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -527,16 +527,27 @@ enum SummonPropFlags enum VehicleSeatFlags { + VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER = 0x00000001, + VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_RIDE = 0x00000002, + VEHICLE_SEAT_FLAG_SHOULD_USE_VEH_SEAT_EXIT_ANIM_ON_VOLUNTARY_EXIT = 0x00000008, VEHICLE_SEAT_FLAG_HIDE_PASSENGER = 0x00000200, // Passenger is hidden - VEHICLE_SEAT_FLAG_UNK1 = 0x00000400, // needed for CGCamera__SyncFreeLookFacing + VEHICLE_SEAT_FLAG_ALLOW_TURNING = 0x00000400, // needed for CGCamera__SyncFreeLookFacing VEHICLE_SEAT_FLAG_CAN_CONTROL = 0x00000800, // Lua_UnitInVehicleControlSeat VEHICLE_SEAT_FLAG_CAN_CAST_MOUNT_SPELL = 0x00001000, // Can cast spells with SPELL_AURA_MOUNTED from seat (possibly 4.x only, 0 seats on 3.3.5a) VEHICLE_SEAT_FLAG_UNCONTROLLED = 0x00002000, // can override !& VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT VEHICLE_SEAT_FLAG_CAN_ATTACK = 0x00004000, // Can attack, cast spells and use items from vehicle + VEHICLE_SEAT_FLAG_SHOULD_USE_VEH_SEAT_EXIT_ANIMN_ON_FORCED_EXIT = 0x00008000, + VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_VOLUNTARY_EXIT = 0x00040000, + VEHICLE_SEAT_FLAG_HAS_VEH_EXIT_ANIM_FORCED_EXIT = 0x00080000, + VEHICLE_SEAT_FLAG_REC_HAS_VEHICLE_ENTER_ANIM = 0x00400000, + VEHICLE_SEAT_FLAG_ENABLE_VEHICLE_ZOOM = 0x01000000, VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT = 0x02000000, // Lua_CanExitVehicle - can enter and exit at free will VEHICLE_SEAT_FLAG_CAN_SWITCH = 0x04000000, // Lua_CanSwitchVehicleSeats + VEHICLE_SEAT_FLAG_HAS_START_WARITING_FOR_VEH_TRANSITION_ANIM_ENTER = 0x08000000, + VEHICLE_SEAT_FLAG_HAS_START_WARITING_FOR_VEH_TRANSITION_ANIM_EXIT = 0x10000000, VEHICLE_SEAT_FLAG_CAN_CAST = 0x20000000, // Lua_UnitHasVehicleUI VEHICLE_SEAT_FLAG_UNK2 = 0x40000000, // checked in conjunction with 0x800 in CastSpell2 + VEHICLE_SEAT_FLAG_ALLOWS_INTERACTION = 0x80000000, }; enum VehicleSeatFlagsB @@ -548,6 +559,7 @@ enum VehicleSeatFlagsB VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 = 0x00000040, VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 = 0x00000100, VEHICLE_SEAT_FLAG_B_USABLE_FORCED_4 = 0x02000000, + VEHICLE_SEAT_FLAG_B_CAN_SWITCH = 0x04000000, VEHICLE_SEAT_FLAG_B_VEHICLE_PLAYERFRAME_UI = 0x80000000, // Lua_UnitHasVehiclePlayerFrameUI - actually checked for flagsb &~ 0x80000000 }; diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 973421bc2e3..80f62d9cedb 100755 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -635,7 +635,7 @@ void LoadDBCStores(const std::string& dataPath) // include existed nodes that have at least single not spell base (scripted) path { std::set<uint32> spellPaths; - for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) + for (uint32 i = 1; i < sSpellEffectStore.GetNumRows(); ++i) if (SpellEffectEntry const* sInfo = sSpellEffectStore.LookupEntry (i)) if (sInfo->Effect == SPELL_EFFECT_SEND_TAXI) spellPaths.insert(sInfo->EffectMiscValue); @@ -1166,11 +1166,3 @@ uint32 ScalingStatValuesEntry::GetDPSAndDamageMultiplier(uint32 subClass, bool i return 0; } -// script support functions -DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore() { return &sSoundEntriesStore; } -DBCStorage <SpellRangeEntry> const* GetSpellRangeStore() { return &sSpellRangeStore; } -DBCStorage <FactionEntry> const* GetFactionStore() { return &sFactionStore; } -DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore() { return &sCreatureDisplayInfoStore; } -DBCStorage <EmotesEntry> const* GetEmotesStore() { return &sEmotesStore; } -DBCStorage <EmotesTextEntry> const* GetEmotesTextStore() { return &sEmotesTextStore; } -DBCStorage <AchievementEntry> const* GetAchievementStore() { return &sAchievementStore; } diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index c22f2ccd625..d94b60c1384 100755 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -214,13 +214,4 @@ extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore; void LoadDBCStores(const std::string& dataPath); -// script support functions - DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore(); - DBCStorage <SpellRangeEntry> const* GetSpellRangeStore(); - DBCStorage <FactionEntry> const* GetFactionStore(); -// DBCStorage <ItemEntry> const* GetItemDisplayStore(); - DBCStorage <CreatureDisplayInfoEntry> const* GetCreatureDisplayStore(); - DBCStorage <EmotesEntry> const* GetEmotesStore(); - DBCStorage <EmotesTextEntry> const* GetEmotesTextStore(); - DBCStorage <AchievementEntry> const* GetAchievementStore(); #endif diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 47c298d7467..91f9104b0b1 100755 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -433,8 +433,8 @@ void LFGMgr::InitializeLockedDungeons(Player* player) locktype = LFG_LOCKSTATUS_RAID_LOCKED; else if (dungeon->difficulty > DUNGEON_DIFFICULTY_NORMAL && player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { - if (!player->GetGroup() || !player->GetGroup()->isLFGGroup() || GetDungeon(player->GetGroup()->GetGUID(), true) != dungeon->ID || GetState(player->GetGroup()->GetGUID()) != LFG_STATE_DUNGEON) - locktype = LFG_LOCKSTATUS_RAID_LOCKED; + //if (!player->GetGroup() || !player->GetGroup()->isLFGGroup() || GetDungeon(player->GetGroup()->GetGUID(), true) != dungeon->ID || GetState(player->GetGroup()->GetGUID()) != LFG_STATE_DUNGEON) + locktype = LFG_LOCKSTATUS_RAID_LOCKED; } else if (dungeon->minlevel > level) locktype = LFG_LOCKSTATUS_TOO_LOW_LEVEL; @@ -791,7 +791,7 @@ LfgProposal* LFGMgr::FindNewGroups(LfgGuidList& check, LfgGuidList& all) sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::FindNewGroup: (%s) - all(%s)", ConcatenateGuids(check).c_str(), ConcatenateGuids(all).c_str()); LfgProposal* pProposal = NULL; - if (!check.size() || check.size() > MAXGROUPSIZE || !CheckCompatibility(check, pProposal)) + if (check.empty() || check.size() > MAXGROUPSIZE || !CheckCompatibility(check, pProposal)) return NULL; // Try to match with queued groups @@ -1417,6 +1417,10 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) waitTimesMap[(*it)->GetGUID()] = int32(joinTime - itQueue->second->joinTime); } + // Set the dungeon difficulty + LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(pProposal->dungeonId); + ASSERT(dungeon); + // Create a new group (if needed) LfgUpdateData updateData = LfgUpdateData(LFG_UPDATETYPE_GROUP_FOUND); Group* grp = pProposal->groupLowGuid ? sGroupMgr->GetGroupByGUID(pProposal->groupLowGuid) : NULL; @@ -1427,6 +1431,7 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) Group* group = player->GetGroup(); if (sendUpdate) player->GetSession()->SendLfgUpdateProposal(proposalId, pProposal); + if (group) { player->GetSession()->SendLfgUpdateParty(updateData); @@ -1478,14 +1483,16 @@ void LFGMgr::UpdateProposal(uint32 proposalId, uint64 guid, bool accept) break; } } + m_teleport.push_back(pguid); grp->SetLfgRoles(pguid, pProposal->players[pguid]->role); SetState(pguid, LFG_STATE_DUNGEON); + + // Add the cooldown spell if queued for a random dungeon + if (dungeon->type == LFG_TYPE_RANDOM) + player->CastSpell(player, LFG_SPELL_DUNGEON_COOLDOWN, false); } - // Set the dungeon difficulty - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(pProposal->dungeonId); - ASSERT(dungeon); grp->SetDungeonDifficulty(Difficulty(dungeon->difficulty)); uint64 gguid = grp->GetGUID(); SetDungeon(gguid, dungeon->Entry()); @@ -1626,6 +1633,7 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string reas { if (!grp) return; + uint64 gguid = grp->GetGUID(); SetState(gguid, LFG_STATE_BOOT); @@ -1635,7 +1643,6 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string reas pBoot->reason = reason; pBoot->victim = victim; pBoot->votedNeeded = GetVotesNeeded(gguid); - PlayerSet players; // Set votes for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) @@ -1651,15 +1658,11 @@ void LFGMgr::InitBoot(Group* grp, uint64 kicker, uint64 victim, std::string reas else { pBoot->votes[guid] = LFG_ANSWER_PENDING; // Other members need to vote - players.insert(plrg); + plrg->GetSession()->SendLfgBootPlayer(pBoot); } } } - // Notify players - for (PlayerSet::const_iterator it = players.begin(); it != players.end(); ++it) - (*it)->GetSession()->SendLfgBootPlayer(pBoot); - m_Boots[grp->GetLowGUID()] = pBoot; } @@ -1748,14 +1751,7 @@ void LFGMgr::UpdateBoot(Player* player, bool accept) void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*/) { sLog->outDebug(LOG_FILTER_LFG, "LFGMgr::TeleportPlayer: [" UI64FMTD "] is being teleported %s", player->GetGUID(), out ? "out" : "in"); - if (out) - { - player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW); - player->TeleportToBGEntryPoint(); - return; - } - // TODO Add support for LFG_TELEPORTERROR_FATIGUE LfgTeleportError error = LFG_TELEPORTERROR_OK; Group* grp = player->GetGroup(); @@ -1765,10 +1761,25 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* error = LFG_TELEPORTERROR_PLAYER_DEAD; else if (player->IsFalling() || player->HasUnitState(UNIT_STATE_JUMPING)) error = LFG_TELEPORTERROR_FALLING; + else if (player->IsMirrorTimerActive(FATIGUE_TIMER)) + error = LFG_TELEPORTERROR_FATIGUE; else { - uint64 gguid = grp->GetGUID(); - LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(GetDungeon(gguid)); + LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(GetDungeon(grp->GetGUID())); + + if (out) + { + // Player needs to be inside the LFG dungeon to be able to teleport out + if (dungeon && player->GetMapId() == uint32(dungeon->map)) + { + player->RemoveAurasDueToSpell(LFG_SPELL_LUCK_OF_THE_DRAW); + player->TeleportToBGEntryPoint(); + } + else + player->GetSession()->SendLfgTeleportError(LFG_TELEPORTERROR_DONT_REPORT); // Not sure which error message to send + + return; + } if (!dungeon) error = LFG_TELEPORTERROR_INVALID_LOCATION; @@ -1817,7 +1828,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* if (error == LFG_TELEPORTERROR_OK) { - if (!player->GetMap()->IsDungeon() && !player->GetMap()->IsRaid()) + if (!player->GetMap()->IsDungeon()) player->SetBattlegroundEntryPoint(); if (player->isInFlight()) diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index d10902b9553..f21818deb64 100755 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -68,6 +68,7 @@ enum LfgTeleportError LFG_TELEPORTERROR_OK = 0, // Internal use LFG_TELEPORTERROR_PLAYER_DEAD = 1, LFG_TELEPORTERROR_FALLING = 2, + LFG_TELEPORTERROR_DONT_REPORT = 3, LFG_TELEPORTERROR_FATIGUE = 4, LFG_TELEPORTERROR_INVALID_LOCATION = 6 }; diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 6175addfae2..1fa7fe0ca9f 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -117,13 +117,14 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth return; } + uint32 state = sLFGMgr->GetState(gguid); sLFGMgr->ClearState(guid); sLFGMgr->SetState(guid, LFG_STATE_NONE); if (Player* player = ObjectAccessor::FindPlayer(guid)) { + if (method == GROUP_REMOVEMETHOD_LEAVE && state != LFG_STATE_FINISHED_DUNGEON && player->HasAura(LFG_SPELL_DUNGEON_COOLDOWN)) + player->CastSpell(player, LFG_SPELL_DUNGEON_DESERTER, false); /* - if (method == GROUP_REMOVEMETHOD_LEAVE) - // Add deserter flag else if (group->isLfgKickActive()) // Update internal kick cooldown of kicked */ @@ -134,7 +135,7 @@ void LFGGroupScript::OnRemoveMember(Group* group, uint64 guid, RemoveMethod meth sLFGMgr->TeleportPlayer(player, true); } - if (sLFGMgr->GetState(gguid) != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon + if (state != LFG_STATE_FINISHED_DUNGEON)// Need more players to finish the dungeon sLFGMgr->OfferContinue(group); } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index bbce6cf56c1..c7758bf5e55 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -486,7 +486,7 @@ void Creature::Update(uint32 diff) break; uint64 dbtableHighGuid = MAKE_NEW_GUID(m_DBTableGuid, GetEntry(), HIGHGUID_UNIT); - time_t linkedRespawntime = sObjectMgr->GetLinkedRespawnTime(dbtableHighGuid, GetMap()->GetInstanceId()); + time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); if (!linkedRespawntime) // Can respawn Respawn(); else // the master is dead @@ -1303,7 +1303,7 @@ bool Creature::LoadCreatureFromDB(uint32 guid, Map* map, bool addToMap) m_respawnDelay = data->spawntimesecs; m_deathState = ALIVE; - m_respawnTime = sObjectMgr->GetCreatureRespawnTime(m_DBTableGuid, GetInstanceId()); + m_respawnTime = GetMap()->GetCreatureRespawnTime(m_DBTableGuid); if (m_respawnTime) // respawn on Update { m_deathState = DEAD; @@ -1398,7 +1398,7 @@ void Creature::DeleteFromDB() return; } - sObjectMgr->RemoveCreatureRespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid); sObjectMgr->DeleteCreatureData(m_DBTableGuid); SQLTransaction trans = WorldDatabase.BeginTransaction(); @@ -1598,7 +1598,7 @@ void Creature::Respawn(bool force) if (getDeathState() == DEAD) { if (m_DBTableGuid) - sObjectMgr->RemoveCreatureRespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveCreatureRespawnTime(m_DBTableGuid); sLog->outStaticDebug("Respawning creature %s (GuidLow: %u, Full GUID: " UI64FMTD " Entry: %u)", GetName(), GetGUIDLow(), GetGUID(), GetEntry()); m_respawnTime = 0; @@ -1676,11 +1676,15 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo) // the check of mechanic immunity on DB (tested) because GetCreatureTemplate()->MechanicImmuneMask and m_spellImmune[IMMUNITY_MECHANIC] don't have same data. bool immunedToAllEffects = true; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (!spellInfo->Effects[i].IsEffect()) + continue; if (!IsImmunedToSpellEffect(spellInfo, i)) { immunedToAllEffects = false; break; } + } if (immunedToAllEffects) return true; @@ -1727,6 +1731,8 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) break; } } + if (bcontinue) + continue; if (bcontinue) continue; @@ -2014,7 +2020,7 @@ void Creature::SaveRespawnTime() if (isSummon() || !m_DBTableGuid || (m_creatureData && !m_creatureData->dbData)) return; - sObjectMgr->SaveCreatureRespawnTime(m_DBTableGuid, GetInstanceId(), m_respawnTime); + GetMap()->SaveCreatureRespawnTime(m_DBTableGuid, m_respawnTime); } // this should not be called by petAI or @@ -2458,7 +2464,7 @@ bool Creature::SetWalk(bool enable) if (!Unit::SetWalk(enable)) return false; - WorldPacket data(enable ? SMSG_MOVE_SPLINE_SET_WALK_MODE : SMSG_MOVE_SPLINE_SET_RUN_MODE, 9); + WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_WALK_MODE : SMSG_SPLINE_MOVE_SET_RUN_MODE, 9); data.append(GetPackGUID()); SendMessageToSet(&data, false); return true; @@ -2474,7 +2480,7 @@ bool Creature::SetDisableGravity(bool disable, bool packetOnly/*=false*/) if (!movespline->Initialized()) return true; - WorldPacket data(disable ? SMSG_MOVE_SPLINE_DISABLE_GRAVITY : SMSG_MOVE_SPLINE_ENABLE_GRAVITY, 9); + WorldPacket data(disable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9); data.append(GetPackGUID()); SendMessageToSet(&data, false); return true; @@ -2495,7 +2501,7 @@ bool Creature::SetHover(bool enable) return true; //! Not always a packet is sent - WorldPacket data(enable ? SMSG_MOVE_SPLINE_SET_HOVER : SMSG_MOVE_SPLINE_UNSET_HOVER, 9); + WorldPacket data(enable ? SMSG_SPLINE_MOVE_SET_HOVER : SMSG_SPLINE_MOVE_UNSET_HOVER, 9); data.append(GetPackGUID()); SendMessageToSet(&data, false); return true; diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 906dc827d3f..1824e2c1b44 100755 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -679,6 +679,11 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature void GetHomePosition(float &x, float &y, float &z, float &ori) { m_homePosition.GetPosition(x, y, z, ori); } Position GetHomePosition() { return m_homePosition; } + void SetTransportHomePosition(float x, float y, float z, float o) { m_transportHomePosition.Relocate(x, y, z, o); } + void SetTransportHomePosition(const Position &pos) { m_transportHomePosition.Relocate(pos); } + void GetTransportHomePosition(float &x, float &y, float &z, float &ori) { m_transportHomePosition.GetPosition(x, y, z, ori); } + Position GetTransportHomePosition() { return m_transportHomePosition; } + uint32 GetWaypointPath(){return m_path_id;} void LoadPath(uint32 pathid) { m_path_id = pathid; } @@ -752,6 +757,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature uint32 m_originalEntry; Position m_homePosition; + Position m_transportHomePosition; bool DisableReputationGain; diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h index 829eb73bf80..537bbd9c099 100755 --- a/src/server/game/Entities/Creature/TemporarySummon.h +++ b/src/server/game/Entities/Creature/TemporarySummon.h @@ -36,6 +36,7 @@ class TempSummon : public Creature Unit* GetSummoner() const; uint64 GetSummonerGUID() { return m_summonerGUID; } TempSummonType const& GetSummonType() { return m_type; } + uint32 GetTimer() { return m_timer; } const SummonPropertiesEntry* const m_Properties; private: diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 7591359230a..2a74d262daf 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -338,7 +338,7 @@ void GameObject::Update(uint32 diff) if (m_respawnTime <= now) // timer expired { uint64 dbtableHighGuid = MAKE_NEW_GUID(m_DBTableGuid, GetEntry(), HIGHGUID_GAMEOBJECT); - time_t linkedRespawntime = sObjectMgr->GetLinkedRespawnTime(dbtableHighGuid, GetMap()->GetInstanceId()); + time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid); if (linkedRespawntime) // Can't respawn, the master is dead { uint64 targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid); @@ -761,13 +761,13 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap) else { m_respawnDelayTime = data->spawntimesecs; - m_respawnTime = sObjectMgr->GetGORespawnTime(m_DBTableGuid, map->GetInstanceId()); + m_respawnTime = GetMap()->GetGORespawnTime(m_DBTableGuid); // ready to respawn if (m_respawnTime && m_respawnTime <= time(NULL)) { m_respawnTime = 0; - sObjectMgr->RemoveGORespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveGORespawnTime(m_DBTableGuid); } } } @@ -788,7 +788,7 @@ bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap) void GameObject::DeleteFromDB() { - sObjectMgr->RemoveGORespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveGORespawnTime(m_DBTableGuid); sObjectMgr->DeleteGOData(m_DBTableGuid); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT); @@ -863,7 +863,7 @@ Unit* GameObject::GetOwner() const void GameObject::SaveRespawnTime() { if (m_goData && m_goData->dbData && m_respawnTime > time(NULL) && m_spawnedByDefault) - sObjectMgr->SaveGORespawnTime(m_DBTableGuid, GetInstanceId(), m_respawnTime); + GetMap()->SaveGORespawnTime(m_DBTableGuid, m_respawnTime); } bool GameObject::IsAlwaysVisibleFor(WorldObject const* seer) const @@ -908,7 +908,7 @@ void GameObject::Respawn() if (m_spawnedByDefault && m_respawnTime > 0) { m_respawnTime = time(NULL); - sObjectMgr->RemoveGORespawnTime(m_DBTableGuid, GetInstanceId()); + GetMap()->RemoveGORespawnTime(m_DBTableGuid); } } @@ -1711,7 +1711,13 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const void GameObject::EventInform(uint32 eventId) { - if (eventId && m_zoneScript) + if (!eventId) + return; + + if (AI()) + AI()->EventInform(eventId); + + if (m_zoneScript) m_zoneScript->ProcessEvent(this, eventId); } diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index d973c3ba4f8..248b080bfdd 100755 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -274,7 +274,7 @@ bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner) for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) SetSpellCharges(i, itemProto->Spells[i].SpellCharges); - SetUInt32Value(ITEM_FIELD_DURATION, abs(itemProto->Duration)); + SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Duration); SetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME, 0); return true; } @@ -420,7 +420,7 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, Field* fields, uint32 entr // update duration if need, and remove if not need if ((proto->Duration == 0) != (duration == 0)) { - SetUInt32Value(ITEM_FIELD_DURATION, abs(proto->Duration)); + SetUInt32Value(ITEM_FIELD_DURATION, proto->Duration); need_save = true; } diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index 54570e9b708..d38e8c32e30 100755 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -242,6 +242,7 @@ class Item : public Object bool IsLocked() const { return !HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_UNLOCKED); } bool IsBag() const { return GetTemplate()->InventoryType == INVTYPE_BAG; } + bool IsCurrencyToken() const { return GetTemplate()->IsCurrencyToken(); } bool IsNotEmptyBag() const; bool IsBroken() const { return GetUInt32Value(ITEM_FIELD_MAXDURABILITY) > 0 && GetUInt32Value(ITEM_FIELD_DURABILITY) == 0; } bool CanBeTraded(bool mail = false, bool trade = false) const; diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h index 048da0b231c..2da0e721a20 100755 --- a/src/server/game/Entities/Item/ItemPrototype.h +++ b/src/server/game/Entities/Item/ItemPrototype.h @@ -202,6 +202,12 @@ enum ItemFlagsExtra ITEM_FLAGS_EXTRA_BNET_ACCOUNT_BOUND = 0x00020000, }; +enum ItemFlagsCustom +{ + ITEM_FLAGS_CU_DURATION_REAL_TIME = 0x0001, // Item duration will tick even if player is offline + ITEM_FLAGS_CU_IGNORE_QUEST_STATUS = 0x0002, // No quest status will be checked when this item drops +}; + enum BAG_FAMILY_MASK { BAG_FAMILY_MASK_NONE = 0x00000000, @@ -641,7 +647,7 @@ struct ItemTemplate uint32 socketBonus; // id from SpellItemEnchantment.dbc uint32 GemProperties; // id from GemProperties.dbc float ArmorDamageModifier; - int32 Duration; // negative = realtime, positive = ingame time + uint32 Duration; uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc uint32 HolidayId; // id from Holidays.dbc float StatScalingFactor; @@ -661,6 +667,7 @@ struct ItemTemplate uint32 FoodType; uint32 MinMoneyLoot; uint32 MaxMoneyLoot; + uint32 FlagsCu; // helpers bool CanChangeEquipStateInCombat() const @@ -683,6 +690,8 @@ struct ItemTemplate return false; } + bool IsCurrencyToken() const { return BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS; } + uint32 GetMaxStackSize() const { return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF-1) : uint32(Stackable); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 0d18a47885f..1a04f7b3053 100755 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -34,11 +34,11 @@ #define CONTACT_DISTANCE 0.5f #define INTERACTION_DISTANCE 5.0f #define ATTACK_DISTANCE 5.0f -#define MAX_VISIBILITY_DISTANCE 500.0f // max distance for visible objects +#define MAX_VISIBILITY_DISTANCE SIZE_OF_GRIDS // max distance for visible objects #define SIGHT_RANGE_UNIT 50.0f -#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents -#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards -#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards +#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents +#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards +#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards #define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects #define DEFAULT_COMBAT_REACH 1.5f @@ -500,13 +500,13 @@ struct MovementInfo t_seat = -1; } - uint32 GetMovementFlags() { return flags; } + uint32 GetMovementFlags() const { return flags; } void SetMovementFlags(uint32 flag) { flags = flag; } void AddMovementFlag(uint32 flag) { flags |= flag; } void RemoveMovementFlag(uint32 flag) { flags &= ~flag; } bool HasMovementFlag(uint32 flag) const { return flags & flag; } - uint16 GetExtraMovementFlags() { return flags2; } + uint16 GetExtraMovementFlags() const { return flags2; } void AddExtraMovementFlag(uint16 flag) { flags2 |= flag; } bool HasExtraMovementFlag(uint16 flag) const { return flags2 & flag; } diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 6e988a79c29..5759a58a575 100755 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -153,6 +153,7 @@ class Pet : public Guardian bool HaveInDiet(ItemTemplate const* item) const; uint32 GetCurrentFoodBenefitLevel(uint32 itemlevel); void SetDuration(int32 dur) { m_duration = dur; } + int32 GetDuration() { return m_duration; } /* bool UpdateStats(Stats stat); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e8d89110f82..ba7ca524521 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -3403,7 +3403,7 @@ void Player::SendInitialSpells() uint16 spellCooldowns = m_spellCooldowns.size(); data << uint16(spellCooldowns); - for (SpellCooldowns::const_iterator itr=m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr) + for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr) { SpellInfo const* sEntry = sSpellMgr->GetSpellInfo(itr->first); if (!sEntry) @@ -4828,7 +4828,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC // bones will be deleted by corpse/bones deleting thread shortly sObjectAccessor->ConvertCorpseForPlayer(playerguid); - if (uint32 guildId = GetGuildIdFromGuid(playerguid)) + if (uint32 guildId = GetGuildIdFromDB(playerguid)) if (Guild* guild = sGuildMgr->GetGuildById(guildId)) guild->DeleteMember(guid); @@ -5176,8 +5176,8 @@ void Player::SetMovement(PlayerMovementType pType) { case MOVE_ROOT: data.Initialize(SMSG_MOVE_ROOT, GetPackGUID().size()+4); break; case MOVE_UNROOT: data.Initialize(SMSG_MOVE_UNROOT, GetPackGUID().size()+4); break; - case MOVE_WATER_WALK: data.Initialize(SMSG_MOVE_SPLINE_SET_WATER_WALK, GetPackGUID().size()+4); break; - case MOVE_LAND_WALK: data.Initialize(SMSG_MOVE_SPLINE_SET_LAND_WALK, GetPackGUID().size()+4); break; + case MOVE_WATER_WALK: data.Initialize(SMSG_SPLINE_MOVE_SET_WATER_WALK, GetPackGUID().size()+4); break; + case MOVE_LAND_WALK: data.Initialize(SMSG_SPLINE_MOVE_SET_LAND_WALK, GetPackGUID().size()+4); break; default: sLog->outError("Player::SetMovement: Unsupported move type (%d), data not sent to client.", pType); return; @@ -7270,7 +7270,7 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto uint8 k_level = getLevel(); uint8 k_grey = Trinity::XP::GetGrayLevel(k_level); - uint8 v_level = plrVictim->getLevel(); + uint8 v_level = victim->getLevel(); if (v_level <= k_grey) return false; @@ -7281,7 +7281,7 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto // [15..28] Horde honor titles and player name // [29..38] Other title and player name // [39+] Nothing - uint32 victim_title = plrVictim->GetUInt32Value(PLAYER_CHOSEN_TITLE); + uint32 victim_title = victim->GetUInt32Value(PLAYER_CHOSEN_TITLE); // Get Killer titles, CharTitlesEntry::bit_index // Ranks: // title[1..14] -> rank[5..18] @@ -7303,10 +7303,10 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto // and those in a lifetime ApplyModUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 1, true); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS, plrVictim->getClass()); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_RACE, plrVictim->getRace()); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS, victim->getClass()); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_RACE, victim->getRace()); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, GetAreaId()); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, plrVictim); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, victim); } else { @@ -7548,7 +7548,7 @@ uint32 Player::_GetCurrencyWeekCap(const CurrencyTypesEntry* currency) const return cap; } -uint32 Player::GetGuildIdFromGuid(uint64 guid) +uint32 Player::GetGuildIdFromDB(uint64 guid) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_GET_GUILD_ID); stmt->setUInt64(0, guid); @@ -8227,7 +8227,6 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply if (CanUseAttackType(attType)) _ApplyWeaponDamage(slot, proto, ssv, apply); - } void Player::_ApplyWeaponDamage(uint8 slot, ItemTemplate const* proto, ScalingStatValuesEntry const* ssv, bool apply) @@ -9157,7 +9156,6 @@ void Player::SendLoot(uint64 guid, LootType loot_type) loot->loot_type = loot_type; WorldPacket data(SMSG_LOOT_RESPONSE, 8 + 1 + 50 + 1 + 1); // we guess size - data << uint64(guid); data << uint8(loot_type); data << LootView(*loot, this, permission); @@ -10734,7 +10732,7 @@ InventoryResult Player::CanStoreItem_InSpecificSlot(uint8 bag, uint8 slot, ItemP return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; // currencytoken case - if (slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END && !(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS)) + if (slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END && !(pProto->IsCurrencyToken())) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; // prevent cheating @@ -11087,7 +11085,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; } } - else if (pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + else if (pProto->IsCurrencyToken()) { res = CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, false, pItem, bag, slot); if (res != EQUIP_ERR_OK) @@ -11254,7 +11252,7 @@ InventoryResult Player::CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &des return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; } } - else if (pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + else if (pProto->IsCurrencyToken()) { res = CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START, CURRENCYTOKEN_SLOT_END, dest, pProto, count, false, pItem, bag, slot); if (res != EQUIP_ERR_OK) @@ -11503,7 +11501,7 @@ InventoryResult Player::CanStoreItems(Item** pItems, int count) const if (b_found) continue; - if (pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + if (pProto->IsCurrencyToken()) { for (uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t) { @@ -12755,7 +12753,7 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ { ItemRemovedQuestCheck(pItem->GetEntry(), count - remcount); pItem->SetCount(pItem->GetCount() - count + remcount); - if (IsInWorld() & update) + if (IsInWorld() && update) pItem->SendUpdateToPlayer(this); pItem->SetState(ITEM_CHANGED, this); return; @@ -12783,7 +12781,7 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ { ItemRemovedQuestCheck(pItem->GetEntry(), count - remcount); pItem->SetCount(pItem->GetCount() - count + remcount); - if (IsInWorld() & update) + if (IsInWorld() && update) pItem->SendUpdateToPlayer(this); pItem->SetState(ITEM_CHANGED, this); return; @@ -12849,7 +12847,7 @@ void Player::DestroyItemCount(uint32 item, uint32 count, bool update, bool unequ { ItemRemovedQuestCheck(pItem->GetEntry(), count - remcount); pItem->SetCount(pItem->GetCount() - count + remcount); - if (IsInWorld() & update) + if (IsInWorld() && update) pItem->SendUpdateToPlayer(this); pItem->SetState(ITEM_CHANGED, this); return; @@ -12924,6 +12922,11 @@ Item* Player::GetItemByEntry(uint32 entry) const if (pItem->GetEntry() == entry) return pItem; + for (uint8 i = KEYRING_SLOT_START; i < CURRENCYTOKEN_SLOT_END; ++i) + if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + if (pItem->GetEntry() == entry) + return pItem; + for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) if (Bag* pBag = GetBagByPos(i)) for (uint32 j = 0; j < pBag->GetBagSize(); ++j) @@ -12957,7 +12960,7 @@ void Player::DestroyItemCount(Item* pItem, uint32 &count, bool update) ItemRemovedQuestCheck(pItem->GetEntry(), count); pItem->SetCount(pItem->GetCount() - count); count = 0; - if (IsInWorld() & update) + if (IsInWorld() && update) pItem->SendUpdateToPlayer(this); pItem->SetState(ITEM_CHANGED, this); } @@ -13545,9 +13548,9 @@ void Player::SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2, uint } case EQUIP_ERR_EVENT_AUTOEQUIP_BIND_CONFIRM: // no idea about this one... { - data << uint64(0); - data << uint32(0); - data << uint64(0); + data << uint64(0); // item guid + data << uint32(0); // slot + data << uint64(0); // container break; } case EQUIP_ERR_ITEM_MAX_LIMIT_CATEGORY_COUNT_EXCEEDED: @@ -13653,7 +13656,7 @@ void Player::UpdateItemDuration(uint32 time, bool realtimeonly) Item* item = *itr; ++itr; // current element can be erased in UpdateDuration - if ((realtimeonly && item->GetTemplate()->Duration < 0) || !realtimeonly) + if (!realtimeonly || item->GetTemplate()->FlagsCu & ITEM_FLAGS_CU_DURATION_REAL_TIME) item->UpdateDuration(this, time); } } @@ -14226,7 +14229,7 @@ void Player::SendNewItem(Item* item, uint32 count, bool received, bool created, data << uint64(GetGUID()); // player GUID data << uint32(received); // 0=looted, 1=from npc data << uint32(created); // 0=received, 1=created - data << uint32(1); // always 0x01 (probably meant to be count of listed items) + data << uint32(1); // bool print error to chat data << uint8(item->GetBagSlot()); // bagslot // item slot, but when added to stack: 0xFFFFFFFF data << uint32((item->GetCount() == count) ? item->GetSlot() : -1); @@ -20160,8 +20163,10 @@ void Player::PetSpellInitialize() WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1); data << uint64(pet->GetGUID()); data << uint16(pet->GetCreatureTemplate()->family); // creature family (required for pet talents) - data << uint32(0); - data << uint8(pet->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); + data << uint32(pet->GetDuration()); + data << uint8(pet->GetReactState()); + data << uint8(charmInfo->GetCommandState()); + data << uint16(0); // Flags, mostly unknown // action bar loop charmInfo->BuildActionBar(&data); @@ -20194,22 +20199,33 @@ void Player::PetSpellInitialize() for (CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) { - time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0; - - data << uint32(itr->first); // spellid - data << uint16(0); // spell category? - data << uint32(cooldown); // cooldown - data << uint32(0); // category cooldown - } + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); + if (!spellInfo) + { + data << uint32(0); + data << uint16(0); + data << uint32(0); + data << uint32(0); + continue; + } - for (CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr) - { time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0; + data << uint32(itr->first); // spell ID - data << uint32(itr->first); // spellid - data << uint16(0); // spell category? - data << uint32(0); // cooldown - data << uint32(cooldown); // category cooldown + CreatureSpellCooldowns::const_iterator categoryitr = pet->m_CreatureCategoryCooldowns.find(spellInfo->Category); + if (categoryitr != pet->m_CreatureCategoryCooldowns.end()) + { + time_t categoryCooldown = (categoryitr->second > curTime) ? (categoryitr->second - curTime) * IN_MILLISECONDS : 0; + data << uint16(spellInfo->Category); // spell category + data << uint32(cooldown); // spell cooldown + data << uint32(categoryCooldown); // category cooldown + } + else + { + data << uint16(0); + data << uint32(cooldown); + data << uint32(0); + } } GetSession()->SendPacket(&data); @@ -20245,24 +20261,24 @@ void Player::PossessSpellInitialize() void Player::VehicleSpellInitialize() { - Creature* veh = GetVehicleCreatureBase(); - if (!veh) + Creature* vehicle = GetVehicleCreatureBase(); + if (!vehicle) return; - uint8 cooldownCount = veh->m_CreatureSpellCooldowns.size() + veh->m_CreatureCategoryCooldowns.size(); + uint8 cooldownCount = vehicle->m_CreatureSpellCooldowns.size(); WorldPacket data(SMSG_PET_SPELLS, 8 + 2 + 4 + 4 + 4 * 10 + 1 + 1 + cooldownCount * (4 + 2 + 4 + 4)); - data << uint64(veh->GetGUID()); - data << uint16(veh->GetCreatureTemplate()->family); - data << uint32(0); - // The following three segments are read as one uint32 - data << uint8(veh->GetReactState()); - data << uint8(0); // CommandState? - data << uint16(0); // unk + data << uint64(vehicle->GetGUID()); // Guid + data << uint16(0); // Pet Family (0 for all vehicles) + data << uint32(vehicle->isSummon() ? vehicle->ToTempSummon()->GetTimer() : 0); // Duration + // The following three segments are read by the client as one uint32 + data << uint8(vehicle->GetReactState()); // React State + data << uint8(0); // Command State + data << uint16(0x800); // DisableActions (set for all vehicles) for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) { - uint32 spellId = veh->m_spells[i]; + uint32 spellId = vehicle->m_spells[i]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { @@ -20270,54 +20286,59 @@ void Player::VehicleSpellInitialize() continue; } - ConditionList conditions = sConditionMgr->GetConditionsForVehicleSpell(veh->GetEntry(), spellId); - if (!sConditionMgr->IsObjectMeetToConditions(this, veh, conditions)) + ConditionList conditions = sConditionMgr->GetConditionsForVehicleSpell(vehicle->GetEntry(), spellId); + if (!sConditionMgr->IsObjectMeetToConditions(this, vehicle, conditions)) { - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "VehicleSpellInitialize: conditions not met for Vehicle entry %u spell %u", veh->ToCreature()->GetEntry(), spellId); + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "VehicleSpellInitialize: conditions not met for Vehicle entry %u spell %u", vehicle->ToCreature()->GetEntry(), spellId); data << uint16(0) << uint8(0) << uint8(i+8); continue; } if (spellInfo->IsPassive()) - { - veh->CastSpell(veh, spellId, true); - data << uint16(0) << uint8(0) << uint8(i+8); - } - else - data << uint32(MAKE_UNIT_ACTION_BUTTON(spellId, i+8)); + vehicle->CastSpell(vehicle, spellId, true); + + data << uint32(MAKE_UNIT_ACTION_BUTTON(spellId, i+8)); } for (uint32 i = CREATURE_MAX_SPELLS; i < MAX_SPELL_CONTROL_BAR; ++i) - data << uint16(0) << uint8(0) << uint8(i+8); + data << uint32(0); - data << uint8(0); - /*if (v23 > 0) - { - for (uint32 i = 0; i < v23; ++i) - data << uint32(v16); // Some spellid? - }*/ + data << uint8(0); // Auras? // Cooldowns - data << cooldownCount; + data << uint8(cooldownCount); time_t now = sWorld->GetGameTime(); - CreatureSpellCooldowns::const_iterator itr; - for (itr = veh->m_CreatureSpellCooldowns.begin(); itr != veh->m_CreatureSpellCooldowns.end(); ++itr) - { - time_t cooldown = (itr->second > now) ? (itr->second - now) * IN_MILLISECONDS : 0; - data << uint32(itr->first); // SpellId - data << uint16(0); // unk - data << uint32(cooldown); // spell cooldown - data << uint32(0); // category cooldown - } - for (itr = veh->m_CreatureCategoryCooldowns.begin(); itr != veh->m_CreatureCategoryCooldowns.end(); ++itr) + for (CreatureSpellCooldowns::const_iterator itr = vehicle->m_CreatureSpellCooldowns.begin(); itr != vehicle->m_CreatureSpellCooldowns.end(); ++itr) { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); + if (!spellInfo) + { + data << uint32(0); + data << uint16(0); + data << uint32(0); + data << uint32(0); + continue; + } + time_t cooldown = (itr->second > now) ? (itr->second - now) * IN_MILLISECONDS : 0; - data << uint32(itr->first); // SpellId - data << uint16(0); // unk - data << uint32(0); // spell cooldown - data << uint32(cooldown); // category cooldown + data << uint32(itr->first); // spell ID + + CreatureSpellCooldowns::const_iterator categoryitr = vehicle->m_CreatureCategoryCooldowns.find(spellInfo->Category); + if (categoryitr != vehicle->m_CreatureCategoryCooldowns.end()) + { + time_t categoryCooldown = (categoryitr->second > now) ? (categoryitr->second - now) * IN_MILLISECONDS : 0; + data << uint16(spellInfo->Category); // spell category + data << uint32(cooldown); // spell cooldown + data << uint32(categoryCooldown); // category cooldown + } + else + { + data << uint16(0); + data << uint32(cooldown); + data << uint32(0); + } } GetSession()->SendPacket(&data); @@ -20356,7 +20377,7 @@ void Player::CharmSpellInitialize() if (charm->GetTypeId() != TYPEID_PLAYER) data << uint8(charm->ToCreature()->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); else - data << uint8(0) << uint8(0) << uint16(0); + data << uint32(0); charmInfo->BuildActionBar(&data); @@ -20581,7 +20602,7 @@ void Player::RemovePetitionsAndSigns(uint64 guid, uint32 type) else { stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIG_BY_GUID_TYPE); - stmt->setUInt8(0, uint8(type)); + stmt->setUInt8(1, uint8(type)); } stmt->setUInt32(0, GUID_LOPART(guid)); @@ -22319,8 +22340,8 @@ void Player::SendInstanceResetWarning(uint32 mapid, Difficulty difficulty, uint3 data << uint32(time); if (type == RAID_INSTANCE_WELCOME) { - data << uint8(0); // is your (1) - data << uint8(0); // is extended (1), ignored if prev field is 0 + data << uint8(0); // is locked + data << uint8(0); // is extended, ignored if prev field is 0 } GetSession()->SendPacket(&data); } @@ -23366,7 +23387,7 @@ Player* Player::GetNextRandomRaidMember(float radius) PartyResult Player::CanUninviteFromGroup() const { - const Group* grp = GetGroup(); + Group const* grp = GetGroup(); if (!grp) return ERR_NOT_IN_GROUP; @@ -23389,8 +23410,12 @@ PartyResult Player::CanUninviteFromGroup() const if (grp->isRollLootActive()) return ERR_PARTY_LFG_BOOT_LOOT_ROLLS; + // TODO: Should also be sent when anyone has recently left combat, with an aprox ~5 seconds timer. + for (GroupReference const* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + if (itr->getSource() && itr->getSource()->isInCombat()) + return ERR_PARTY_LFG_BOOT_IN_COMBAT; + /* Missing support for these types - return ERR_PARTY_LFG_BOOT_IN_COMBAT; // also have a cooldown (some secs after combat finish return ERR_PARTY_LFG_BOOT_COOLDOWN_S; return ERR_PARTY_LFG_BOOT_NOT_ELIGIBLE_S; */ @@ -25639,8 +25664,8 @@ void Player::SendMovementSetCanFly(bool apply) void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply) { WorldPacket data(apply ? - SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY : - SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY, 12); + SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY : + SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, 12); data.append(GetPackGUID()); data << uint32(0); //! movement counter SendDirectMessage(&data); @@ -25648,7 +25673,7 @@ void Player::SendMovementSetCanTransitionBetweenSwimAndFly(bool apply) void Player::SendMovementSetHover(bool apply) { - WorldPacket data(apply ? SMSG_MOVE_SET_HOVERING : SMSG_MOVE_SPLINE_UNSET_HOVER, 12); + WorldPacket data(apply ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, 12); data.append(GetPackGUID()); data << uint32(0); //! movement counter SendDirectMessage(&data); @@ -25656,7 +25681,7 @@ void Player::SendMovementSetHover(bool apply) void Player::SendMovementSetWaterWalking(bool apply) { - WorldPacket data(apply ? SMSG_MOVE_SET_WATER_WALK : SMSG_MOVE_SET_LAND_WALK, 12); + WorldPacket data(apply ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, 12); data.append(GetPackGUID()); data << uint32(0); //! movement counter SendDirectMessage(&data); @@ -25664,7 +25689,7 @@ void Player::SendMovementSetWaterWalking(bool apply) void Player::SendMovementSetFeatherFall(bool apply) { - WorldPacket data(apply ? SMSG_MOVE_SET_FEATHER_FALL : SMSG_MOVE_SET_NORMAL_FALL, 12); + WorldPacket data(apply ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, 12); data.append(GetPackGUID()); data << uint32(0); //! movement counter SendDirectMessage(&data); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 24a1c35b8e2..dbe9cd94a21 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1888,7 +1888,7 @@ class Player : public Unit, public GridObject<Player> m_guildId = GuildId; } uint32 GetGuildId() { return m_guildId; } - static uint32 GetGuildIdFromGuid(uint64 guid); + static uint32 GetGuildIdFromDB(uint64 guid); void SetRank(uint8 rankId) { SetUInt32Value(PLAYER_GUILDRANK, rankId); } uint8 GetRank() { return uint8(GetUInt32Value(PLAYER_GUILDRANK)); } @@ -2049,6 +2049,7 @@ class Player : public Unit, public GridObject<Player> StopMirrorTimer(BREATH_TIMER); StopMirrorTimer(FIRE_TIMER); } + bool IsMirrorTimerActive(MirrorTimerType type) { return m_MirrorTimer[type] == getMaxTimer(type); } void SetMovement(PlayerMovementType pType); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index a00fcae1e09..ef3e1331a4c 100755 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -656,6 +656,7 @@ uint32 Transport::AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, o + GetOrientation()); creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); + creature->SetTransportHomePosition(creature->m_movementInfo.t_pos); if (!creature->IsPositionValid()) { @@ -698,11 +699,33 @@ void Transport::UpdateNPCPositions() Creature* npc = *itr; float x, y, z, o; - o = GetOrientation() + npc->m_movementInfo.t_pos.m_orientation; - x = GetPositionX() + (npc->m_movementInfo.t_pos.m_positionX * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionY * sin(GetOrientation() + M_PI)); - y = GetPositionY() + (npc->m_movementInfo.t_pos.m_positionY * cos(GetOrientation()) + npc->m_movementInfo.t_pos.m_positionX * sin(GetOrientation())); - z = GetPositionZ() + npc->m_movementInfo.t_pos.m_positionZ; - npc->SetHomePosition(x, y, z, o); + npc->m_movementInfo.t_pos.GetPosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, o); GetMap()->CreatureRelocation(npc, x, y, z, o, false); + npc->GetTransportHomePosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, o); + npc->SetHomePosition(x, y, z, o); } } + +//! This method transforms supplied transport offsets into global coordinates +void Transport::CalculatePassengerPosition(float& x, float& y, float& z, float& o) +{ + float inx = x, iny = y, inz = z, ino = o; + o = GetOrientation() + ino; + x = GetPositionX() + (inx * cos(GetOrientation()) + iny * sin(GetOrientation() + M_PI)); + y = GetPositionY() + (iny * cos(GetOrientation()) + inx * sin(GetOrientation())); + z = GetPositionZ() + inz; +} + +//! This method transforms supplied global coordinates into local offsets +void Transport::CalculatePassengerOffset(float& x, float& y, float& z, float& o) +{ + o -= GetOrientation(); + z -= GetPositionZ(); + y -= GetPositionY(); // y = searchedY * cos(o) + searchedX * sin(o) + x -= GetPositionX(); // x = searchedX * cos(o) + searchedY * sin(o + pi) + float inx = x, iny = y; + y = (iny - inx * tan(GetOrientation())) / (cos(GetOrientation()) - sin(GetOrientation() + M_PI) * tan(GetOrientation())); + x = (inx - iny * sin(GetOrientation() + M_PI) / cos(GetOrientation())) / (cos(GetOrientation()) - tan(GetOrientation()) * sin(GetOrientation() + M_PI)); +} diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 518dcf6359d..4b0c42c9071 100755 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -47,6 +47,8 @@ class Transport : public GameObject uint32 AddNPCPassenger(uint32 tguid, uint32 entry, float x, float y, float z, float o, uint32 anim=0); void UpdatePosition(MovementInfo* mi); void UpdateNPCPositions(); + void CalculatePassengerPosition(float& x, float& y, float& z, float& o); + void CalculatePassengerOffset(float& x, float& y, float& z, float& o); void BuildStartMovePacket(Map const* targetMap); void BuildStopMovePacket(Map const* targetMap); uint32 GetScriptId() const { return ScriptId; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 347a51a67d9..5fe8f0bf657 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -396,10 +396,25 @@ void Unit::UpdateSplineMovement(uint32 t_diff) m_movesplineTimer.Reset(POSITION_UPDATE_DELAY); Movement::Location loc = movespline->ComputePosition(); - if (GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->UpdatePosition(loc.x,loc.y,loc.z,loc.orientation); - else - GetMap()->CreatureRelocation((Creature*)this,loc.x,loc.y,loc.z,loc.orientation); + if (HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + { + Position& pos = m_movementInfo.t_pos; + pos.m_positionX = loc.x; + pos.m_positionY = loc.y; + pos.m_positionZ = loc.z; + pos.m_orientation = loc.orientation; + if (Unit* vehicle = GetVehicleBase()) + { + loc.x += vehicle->GetPositionX(); + loc.y += vehicle->GetPositionY(); + loc.z += vehicle->GetPositionZMinusOffset(); + loc.orientation = vehicle->GetOrientation(); + } + else if (Transport* trans = GetTransport()) + trans->CalculatePassengerPosition(loc.x, loc.y, loc.z, loc.orientation); + } + + UpdatePosition(loc.x, loc.y, loc.z, loc.orientation); } } @@ -409,50 +424,6 @@ void Unit::DisableSpline() movespline->_Interrupt(); } -void Unit::SendMonsterMoveExitVehicle(Position const* newPos) -{ - WorldPacket data(SMSG_MONSTER_MOVE, 1+12+4+1+4+4+4+12+GetPackGUID().size()); - data.append(GetPackGUID()); - - data << uint8(GetTypeId() == TYPEID_PLAYER ? 1 : 0); // new in 3.1, bool - data << GetPositionX() << GetPositionY() << GetPositionZ(); - data << getMSTime(); - - data << uint8(SPLINETYPE_FACING_ANGLE); - data << float(GetOrientation()); // guess - data << uint32(SPLINEFLAG_EXIT_VEHICLE); - data << uint32(0); // Time in between points - data << uint32(1); // 1 single waypoint - data << newPos->GetPositionX(); - data << newPos->GetPositionY(); - data << newPos->GetPositionZ(); - - SendMessageToSet(&data, true); -} - -void Unit::SendMonsterMoveTransport(Unit* vehicleOwner) -{ - // TODO: Turn into BuildMonsterMoveTransport packet and allow certain variables (for npc movement aboard vehicles) - WorldPacket data(SMSG_MONSTER_MOVE_TRANSPORT, GetPackGUID().size()+vehicleOwner->GetPackGUID().size() + 47); - data.append(GetPackGUID()); - data.append(vehicleOwner->GetPackGUID()); - data << int8(GetTransSeat()); - data << uint8(0); - data << GetPositionX() - vehicleOwner->GetPositionX(); - data << GetPositionY() - vehicleOwner->GetPositionY(); - data << GetPositionZ() - vehicleOwner->GetPositionZ(); - data << uint32(getMSTime()); // should be an increasing constant that indicates movement packet count - data << uint8(SPLINETYPE_FACING_ANGLE); - data << GetTransOffsetO(); // facing angle? - data << uint32(SPLINEFLAG_TRANSPORT); - data << uint32(GetTransTime()); // move time - data << uint32(1); // amount of waypoints - data << uint32(0); // waypoint X - data << uint32(0); // waypoint Y - data << uint32(0); // waypoint Z - SendMessageToSet(&data, true); -} - void Unit::resetAttackTimer(WeaponAttackType type) { m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]); @@ -556,13 +527,7 @@ void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb) if (absorb) *absorb += damage; damage = 0; - return; } - - uint32 originalDamage = damage; - - if (absorb && originalDamage > damage) - *absorb += (originalDamage - damage); } uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss) @@ -839,11 +804,6 @@ void Unit::CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo return; } - // TODO: this is a workaround and needs removal - if (!originalCaster && GetTypeId() == TYPEID_UNIT && ToCreature()->isTotem() && IsControlledByPlayer()) - if (Unit* owner = GetOwner()) - originalCaster=owner->GetGUID(); - // TODO: this is a workaround - not needed anymore, but required for some scripts :( if (!originalCaster && triggeredByAura) originalCaster = triggeredByAura->GetCasterGUID(); @@ -2503,12 +2463,12 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) // Chance resist debuff if (!spell->IsPositive()) { - bool bNegativeAura = false; + bool bNegativeAura = true; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (spell->Effects[i].ApplyAuraName != 0) + if (spell->Effects[i].ApplyAuraName == 0) { - bNegativeAura = true; + bNegativeAura = false; break; } } @@ -2931,9 +2891,11 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); m_AutoRepeatFirstCast = true; } - AddUnitState(UNIT_STATE_CASTING); - } break; + if (pSpell->m_spellInfo->CalcCastTime(this) > 0) + AddUnitState(UNIT_STATE_CASTING); + break; + } case CURRENT_CHANNELED_SPELL: { // channel spells always break generic non-delayed and any channeled spells @@ -2945,8 +2907,9 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != 75) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); AddUnitState(UNIT_STATE_CASTING); - } break; + break; + } case CURRENT_AUTOREPEAT_SPELL: { // only Auto Shoot does not break anything @@ -2958,12 +2921,11 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) } // special action: set first cast flag m_AutoRepeatFirstCast = true; - } break; + break; + } default: - { - // other spell types don't break anything now - } break; + break; // other spell types don't break anything now } // current spell (if it is still here) may be safely deleted now @@ -3638,87 +3600,6 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId // Call AfterDispel hook on AuraScript aura->CallScriptAfterDispel(&dispelInfo); - switch (aura->GetSpellInfo()->SpellFamilyName) - { - case SPELLFAMILY_WARLOCK: - { - // Unstable Affliction (crash if before removeaura?) - if (aura->GetSpellInfo()->SpellFamilyFlags[1] & 0x0100) - { - Unit* caster = aura->GetCaster(); - if (!caster) - break; - if (AuraEffect const* aurEff = aura->GetEffect(EFFECT_0)) - { - int32 damage = aurEff->GetAmount() * 9; - // backfire damage and silence - caster->CastCustomSpell(dispeller, 31117, &damage, NULL, NULL, true, NULL, aurEff); - } - } - break; - } - case SPELLFAMILY_DRUID: - { - // Lifebloom - if (aura->GetSpellInfo()->SpellFamilyFlags[1] & 0x10) - { - if (AuraEffect const* aurEff = aura->GetEffect(EFFECT_1)) - { - // final heal - int32 healAmount = aurEff->GetAmount(); - if (Unit* caster = aura->GetCaster()) - { - healAmount = caster->SpellHealingBonusDone(this, aura->GetSpellInfo(), healAmount, HEAL, dispelInfo.GetRemovedCharges()); - healAmount = this->SpellHealingBonusTaken(caster, aura->GetSpellInfo(), healAmount, HEAL, dispelInfo.GetRemovedCharges()); - } - CastCustomSpell(this, 33778, &healAmount, NULL, NULL, true, NULL, NULL, aura->GetCasterGUID()); - - // mana - if (Unit* caster = aura->GetCaster()) - { - int32 mana = CalculatePctU(caster->GetCreateMana(), aura->GetSpellInfo()->ManaCostPercentage) * chargesRemoved / 2; - caster->CastCustomSpell(caster, 64372, &mana, NULL, NULL, true, NULL, NULL, aura->GetCasterGUID()); - } - } - } - break; - } - case SPELLFAMILY_SHAMAN: - { - // Flame Shock - if (aura->GetSpellInfo()->SpellFamilyFlags[0] & 0x10000000) - { - if (Unit* caster = aura->GetCaster()) - { - uint32 triggeredSpellId = 0; - // Lava Flows - if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, 3087, 0)) - { - switch (aurEff->GetId()) - { - case 51482: // Rank 3 - triggeredSpellId = 65264; - break; - case 51481: // Rank 2 - triggeredSpellId = 65263; - break; - case 51480: // Rank 1 - triggeredSpellId = 64694; - break; - default: - sLog->outError("Unit::RemoveAurasDueToSpellByDispel: Unknown rank of Lava Flows (%d) found", aurEff->GetId()); - } - } - - if (triggeredSpellId) - caster->CastSpell(caster, triggeredSpellId, true); - } - } - break; - } - default: - break; - } return; } else @@ -8328,6 +8209,14 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg CastSpell(victim, 27526, true, castItem, triggeredByAura); return true; } + // Evasive Maneuvers + case 50240: + { + // Remove a Evasive Charge + Aura* charge = GetAura(50241); + if (charge->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL)) + RemoveAurasDueToSpell(50240); + } } break; case SPELLFAMILY_MAGE: @@ -8982,12 +8871,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg CastSpell(this, 70721, true); break; } - // Bloodthirst (($m/100)% of max health) - case 23880: - { - basepoints0 = int32(CountPctFromMaxHealth(triggerAmount)); - break; - } // Shamanistic Rage triggered spell case 30824: { @@ -10159,7 +10042,7 @@ Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo) Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET); for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) { - if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner()) + if (Unit* magnet = (*itr)->GetBase()->GetCaster()) if (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK && spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK && _IsValidAttackTarget(magnet, spellInfo) @@ -10801,6 +10684,15 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui int32 TakenTotal = 0; float TakenTotalMod = 1.0f; + float TakenTotalCasterMod = 0.0f; + + // get all auras from caster that allow the spell to ignore resistance (sanctified wrath) + AuraEffectList const& IgnoreResistAuras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i) + { + if ((*i)->GetMiscValue() & spellProto->GetSchoolMask()) + TakenTotalCasterMod += (float((*i)->GetAmount())/100); + } // from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN // multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085) @@ -10865,7 +10757,22 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui TakenTotal+= int32(TakenAdvertisedBenefit * coeff * factorMod); } - float tmpDamage = (float(pdamage) + TakenTotal) * TakenTotalMod; + float tmpDamage = 0.0f; + + if (TakenTotalCasterMod) + { + if (TakenTotal < 0) + { + if (TakenTotalMod < 1) + tmpDamage = ((float(CalculatePctF(pdamage, TakenTotalCasterMod) + TakenTotal) * TakenTotalMod) + CalculatePctF(pdamage, TakenTotalCasterMod)); + else + tmpDamage = ((float(CalculatePctF(pdamage, TakenTotalCasterMod) + TakenTotal) + CalculatePctF(pdamage, TakenTotalCasterMod)) * TakenTotalMod); + } + else if (TakenTotalMod < 1) + tmpDamage = ((CalculatePctF(float(pdamage) + TakenTotal, TakenTotalCasterMod) * TakenTotalMod) + CalculatePctF(float(pdamage) + TakenTotal, TakenTotalCasterMod)); + } + if (!tmpDamage) + tmpDamage = (float(pdamage) + TakenTotal) * TakenTotalMod; return uint32(std::max(tmpDamage, 0.0f)); } @@ -11575,6 +11482,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) { // State/effect immunities applied by aura expect full spell immunity // Ignore effects with mechanic, they are supposed to be checked separately + if (!spellInfo->Effects[i].IsEffect()) + continue; if (!IsImmunedToSpellEffect(spellInfo, i)) { immuneToAllEffects = false; @@ -11820,6 +11729,16 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT return 0; int32 TakenFlatBenefit = 0; + float TakenTotalCasterMod = 0.0f; + + // get all auras from caster that allow the spell to ignore resistance (sanctified wrath) + SpellSchoolMask attackSchoolMask = spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL; + AuraEffectList const& IgnoreResistAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffectList::const_iterator i = IgnoreResistAuras.begin(); i != IgnoreResistAuras.end(); ++i) + { + if ((*i)->GetMiscValue() & attackSchoolMask) + TakenTotalCasterMod += (float((*i)->GetAmount())/100); + } // ..taken AuraEffectList const& mDamageTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN); @@ -11904,7 +11823,22 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT AddPctN(TakenTotalMod, (*i)->GetAmount()); } - float tmpDamage = (float(pdamage) + TakenFlatBenefit) * TakenTotalMod; + float tmpDamage = 0.0f; + + if (TakenTotalCasterMod) + { + if (TakenFlatBenefit < 0) + { + if (TakenTotalMod < 1) + tmpDamage = ((float(CalculatePctF(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) * TakenTotalMod) + CalculatePctF(pdamage, TakenTotalCasterMod)); + else + tmpDamage = ((float(CalculatePctF(pdamage, TakenTotalCasterMod) + TakenFlatBenefit) + CalculatePctF(pdamage, TakenTotalCasterMod)) * TakenTotalMod); + } + else if (TakenTotalMod < 1) + tmpDamage = ((CalculatePctF(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod) * TakenTotalMod) + CalculatePctF(float(pdamage) + TakenFlatBenefit, TakenTotalCasterMod)); + } + if (!tmpDamage) + tmpDamage = (float(pdamage) + TakenFlatBenefit) * TakenTotalMod; // bonus result can be negative return uint32(std::max(tmpDamage, 0.0f)); @@ -12730,7 +12664,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) { // Set creature speed rate from CreatureInfo if (GetTypeId() == TYPEID_UNIT) - speed *= ToCreature()->GetCreatureTemplate()->speed_walk; + speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached // Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need // TODO: possible affect only on MOVE_RUN @@ -12795,10 +12729,10 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) switch (mtype) { case MOVE_WALK: - data.Initialize(SMSG_MOVE_SPLINE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4); + data.Initialize(SMSG_SPLINE_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_RUN: - data.Initialize(SMSG_MOVE_SPLINE_SET_RUN_SPEED, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_RUN_SPEED, 1 + 8 + 4); data.WriteByteMask(bytes[7]); data.WriteByteMask(bytes[2]); data.WriteByteMask(bytes[1]); @@ -12820,7 +12754,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) data << float(GetSpeed(mtype)); break; case MOVE_RUN_BACK: - data.Initialize(SMSG_MOVE_SPLINE_SET_RUN_BACK_SPEED, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, 1 + 8 + 4); data.WriteByteMask(bytes[4]); data.WriteByteMask(bytes[0]); data.WriteByteMask(bytes[6]); @@ -12842,7 +12776,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) data << float(GetSpeed(mtype)); break; case MOVE_SWIM: - data.Initialize(SMSG_MOVE_SPLINE_SET_SWIM_SPEED, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_SWIM_SPEED, 1 + 8 + 4); data.WriteByteMask(bytes[3]); data.WriteByteMask(bytes[5]); data.WriteByteMask(bytes[7]); @@ -12863,7 +12797,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) data.WriteByteSeq(bytes[5]); break; case MOVE_SWIM_BACK: - data.Initialize(SMSG_MOVE_SPLINE_SET_SWIM_BACK_SPEED, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, 1 + 8 + 4); data.WriteByteMask(bytes[3]); data.WriteByteMask(bytes[5]); data.WriteByteMask(bytes[4]); @@ -12884,7 +12818,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) data.WriteByteSeq(bytes[5]); break; case MOVE_TURN_RATE: - data.Initialize(SMSG_MOVE_SPLINE_SET_TURN_RATE, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_TURN_RATE, 1 + 8 + 4); data.WriteByteMask(bytes[0]); data.WriteByteMask(bytes[4]); data.WriteByteMask(bytes[5]); @@ -12905,7 +12839,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) data.WriteByteSeq(bytes[3]); break; case MOVE_FLIGHT: - data.Initialize(SMSG_MOVE_SPLINE_SET_FLIGHT_SPEED, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, 1 + 8 + 4); data.WriteByteMask(bytes[2]); data.WriteByteMask(bytes[3]); data.WriteByteMask(bytes[5]); @@ -12927,7 +12861,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) data.WriteByteSeq(bytes[4]); break; case MOVE_FLIGHT_BACK: - data.Initialize(SMSG_MOVE_SPLINE_SET_FLIGHT_BACK_SPEED, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, 1 + 8 + 4); data.WriteByteMask(bytes[1]); data.WriteByteMask(bytes[6]); data.WriteByteMask(bytes[0]); @@ -12948,7 +12882,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) data.WriteByteSeq(bytes[3]); break; case MOVE_PITCH_RATE: - data.Initialize(SMSG_MOVE_SPLINE_SET_PITCH_RATE, 1 + 8 + 4); + data.Initialize(SMSG_SPLINE_MOVE_SET_PITCH_RATE, 1 + 8 + 4); data.WriteByteMask(bytes[7]); data.WriteByteMask(bytes[2]); data.WriteByteMask(bytes[3]); @@ -13379,8 +13313,7 @@ void Unit::TauntFadeOut(Unit* taunter) return; } - //m_ThreatManager.tauntFadeOut(taunter); - target = m_ThreatManager.getHostilTarget(); + target = creature->SelectVictim(); // might have more taunt auras remaining if (target && target != taunter) { @@ -13464,7 +13397,7 @@ Unit* Creature::SelectVictim() else return NULL; - if (target && _IsTargetAcceptable(target)) + if (target && _IsTargetAcceptable(target) && canCreatureAttack(target)) { SetInFront(target); return target; @@ -13490,7 +13423,7 @@ Unit* Creature::SelectVictim() { target = SelectNearestTargetInAttackDistance(m_CombatDistance ? m_CombatDistance : ATTACK_DISTANCE); - if (target && _IsTargetAcceptable(target)) + if (target && _IsTargetAcceptable(target) && canCreatureAttack(target)) return target; } @@ -13672,7 +13605,7 @@ void Unit::ModSpellCastTime(SpellInfo const* spellProto, int32 & castTime, Spell if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CASTING_TIME, castTime, spell); - if (!(spellProto->Attributes & (SPELL_ATTR0_ABILITY|SPELL_ATTR0_TRADESPELL)) && spellProto->SpellFamilyName) + if (!(spellProto->Attributes & (SPELL_ATTR0_ABILITY|SPELL_ATTR0_TRADESPELL)) && ((GetTypeId() == TYPEID_PLAYER && spellProto->SpellFamilyName) || GetTypeId() == TYPEID_UNIT)) castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); else if (spellProto->Attributes & SPELL_ATTR0_REQ_AMMO && !(spellProto->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)) castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]); @@ -15007,6 +14940,11 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u if (procSpell && (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check takeCharges = true; break; + case SPELL_AURA_SPELL_MAGNET: + // Skip Melee hits and targets with magnet aura + if (procSpell && (triggeredByAura->GetBase()->GetUnitOwner()->ToUnit() == ToUnit())) // Magnet + takeCharges = true; + break; case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT: case SPELL_AURA_MOD_POWER_COST_SCHOOL: // Skip melee hits and spells ws wrong school or zero cost @@ -15235,6 +15173,7 @@ void Unit::StopMoving() return; Movement::MoveSplineInit init(*this); + init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); init.SetFacing(GetOrientation()); init.Launch(); } @@ -16347,7 +16286,7 @@ void Unit::SetRooted(bool apply) } else { - WorldPacket data(SMSG_MOVE_SPLINE_ROOT, 8); + WorldPacket data(SMSG_SPLINE_MOVE_ROOT, 8); data.append(GetPackGUID()); SendMessageToSet(&data, true); ToCreature()->StopMoving(); @@ -16366,7 +16305,7 @@ void Unit::SetRooted(bool apply) } else { - WorldPacket data(SMSG_MOVE_SPLINE_UNROOT, 8); + WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8); data.append(GetPackGUID()); SendMessageToSet(&data, true); } @@ -16747,7 +16686,7 @@ Creature* Unit::GetVehicleCreatureBase() const uint64 Unit::GetTransGUID() const { if (GetVehicle()) - return GetVehicle()->GetBase()->GetGUID(); + return GetVehicleBase()->GetGUID(); if (GetTransport()) return GetTransport()->GetGUID(); @@ -17529,7 +17468,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId) Creature* creature = ToCreature(); if (creature && creature->IsAIEnabled) - creature->AI()->DoAction(EVENT_SPELLCLICK); + creature->AI()->OnSpellClick(clicker); return true; } @@ -17649,11 +17588,12 @@ void Unit::_ExitVehicle(Position const* exitPosition) Vehicle* vehicle = m_vehicle; m_vehicle = NULL; - SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT + SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT Position pos; - if (!exitPosition) // Exit position not specified - vehicle->GetBase()->GetPosition(&pos); + if (!exitPosition) // Exit position not specified + vehicle->GetBase()->GetPosition(&pos); // This should use passenger's current position, leaving it as it is now + // because we calculate positions incorrect (sometimes under map) else pos = *exitPosition; @@ -17663,19 +17603,22 @@ void Unit::_ExitVehicle(Position const* exitPosition) ToPlayer()->SetFallInformation(0, GetPositionZ()); else if (HasUnitMovementFlag(MOVEMENTFLAG_ROOT)) { - WorldPacket data(SMSG_MOVE_SPLINE_UNROOT, 8); + WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8); data.append(GetPackGUID()); SendMessageToSet(&data, false); } - SendMonsterMoveExitVehicle(&pos); - Relocate(&pos); + Movement::MoveSplineInit init(*this); + init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); + init.SetFacing(GetOrientation()); + init.SetTransportExit(); + init.Launch(); + + //GetMotionMaster()->MoveFall(); // Enable this once passenger positions are calculater properly (see above) if (Player* player = ToPlayer()) player->ResummonPetTemporaryUnSummonedIfAny(); - SendMovementFlagUpdate(); - if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION)) if (((Minion*)vehicle->GetBase())->GetOwner() == this) vehicle->Dismiss(); @@ -17693,24 +17636,13 @@ void Unit::_ExitVehicle(Position const* exitPosition) void Unit::BuildMovementPacket(ByteBuffer *data) const { - switch (GetTypeId()) - { - case TYPEID_UNIT: - if (CanFly()) - const_cast<Unit*>(this)->AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); - break; - case TYPEID_PLAYER: - // remove unknown, unused etc flags for now - const_cast<Unit*>(this)->RemoveUnitMovementFlag(MOVEMENTFLAG_SPLINE_ENABLED); - if (isInFlight()) - { - WPAssert(const_cast<Unit*>(this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE); - const_cast<Unit*>(this)->AddUnitMovementFlag(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_SPLINE_ENABLED); - } - break; - default: - break; - } + *data << uint32(GetUnitMovementFlags()); // movement flags + *data << uint16(GetExtraUnitMovementFlags()); // 2.3.0 + *data << uint32(getMSTime()); // time / counter + *data << GetPositionX(); + *data << GetPositionY(); + *data << GetPositionZMinusOffset(); + *data << GetOrientation(); bool onTransport = GetUnitMovementFlags() & MOVEMENTFLAG_ONTRANSPORT; bool hasInterpolatedMovement = m_movementInfo.flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT; @@ -18116,6 +18048,7 @@ void Unit::SetInFront(Unit const* target) void Unit::SetFacingTo(float ori) { Movement::MoveSplineInit init(*this); + init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); init.SetFacing(ori); init.Launch(); } @@ -18187,7 +18120,7 @@ void Unit::SendMovementHover() if (GetTypeId() == TYPEID_PLAYER) ToPlayer()->SendMovementSetHover(HasUnitMovementFlag(MOVEMENTFLAG_HOVER)); - WorldPacket data(MSG_MOVE_HOVER, 64); // SMSG_MOVE_SET_HOVERING? + WorldPacket data(MSG_MOVE_HOVER, 64); data.append(GetPackGUID()); BuildMovementPacket(&data); SendMessageToSet(&data, false); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 9d6c22ab8b5..6d188fe3593 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -735,19 +735,6 @@ enum MovementFlags2 MOVEMENTFLAG2_UNK16 = 0x00008000, }; -enum SplineFlags -{ - SPLINEFLAG_WALKMODE = 0x00001000, - SPLINEFLAG_FLYING = 0x00002000, - SPLINEFLAG_TRANSPORT = 0x00800000, - SPLINEFLAG_EXIT_VEHICLE = 0x01000000, -}; - -enum SplineType -{ - SPLINETYPE_FACING_ANGLE = 4, -}; - enum UnitTypeMask { UNIT_MASK_NONE = 0x00000000, @@ -806,8 +793,8 @@ public: m_dispeller(_dispeller), m_dispellerSpellId(_dispellerSpellId), m_chargesRemoved(_chargesRemoved) {} Unit* GetDispeller() { return m_dispeller; } - uint32 GetDispellerSpellId() { return m_dispellerSpellId; } - uint8 GetRemovedCharges() { return m_chargesRemoved; } + uint32 GetDispellerSpellId() const { return m_dispellerSpellId; } + uint8 GetRemovedCharges() const { return m_chargesRemoved; } void SetRemovedCharges(uint8 amount) { m_chargesRemoved = amount; @@ -1350,10 +1337,10 @@ class Unit : public WorldObject uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); } bool IsFullHealth() const { return GetHealth() == GetMaxHealth(); } - bool HealthBelowPct(int32 pct) const { return GetHealth() * uint64(100) < GetMaxHealth() * uint64(pct); } - bool HealthBelowPctDamaged(int32 pct, uint32 damage) const { return (int32(GetHealth()) - damage) * int64(100) < GetMaxHealth() * int64(pct); } - bool HealthAbovePct(int32 pct) const { return GetHealth() * uint64(100) > GetMaxHealth() * uint64(pct); } - bool HealthAbovePctHealed(int32 pct, uint32 heal) const { return (GetHealth() + heal) * uint64(100) > GetMaxHealth() * uint64(pct); } + bool HealthBelowPct(int32 pct) const { return GetHealth() < CountPctFromMaxHealth(pct); } + bool HealthBelowPctDamaged(int32 pct, uint32 damage) const { return int64(GetHealth()) - int64(damage) < int64(CountPctFromMaxHealth(pct)); } + bool HealthAbovePct(int32 pct) const { return GetHealth() > CountPctFromMaxHealth(pct); } + bool HealthAbovePctHealed(int32 pct, uint32 heal) const { return uint64(GetHealth()) + uint64(heal) > CountPctFromMaxHealth(pct); } float GetHealthPct() const { return GetMaxHealth() ? 100.f * GetHealth() / GetMaxHealth() : 0.0f; } uint32 CountPctFromMaxHealth(int32 pct) const { return CalculatePctN(GetMaxHealth(), pct); } uint32 CountPctFromCurHealth(int32 pct) const { return CalculatePctN(GetHealth(), pct); } @@ -1632,9 +1619,7 @@ class Unit : public WorldObject void MonsterMoveWithSpeed(float x, float y, float z, float speed); //void SetFacing(float ori, WorldObject* obj = NULL); - void SendMonsterMoveExitVehicle(Position const* newPos); //void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); - void SendMonsterMoveTransport(Unit* vehicleOwner); void SendMovementFlagUpdate(); /*! These methods send the same packet to the client in apply and unapply case. diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 090a1db382a..eb50f3fe229 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -28,6 +28,7 @@ #include "ZoneScript.h" #include "SpellMgr.h" #include "SpellInfo.h" +#include "MoveSplineInit.h" Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) : _me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntry) { @@ -338,7 +339,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) } } - if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_UNK1)) + if (seat->second.SeatInfo->m_flags && !(seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_ALLOW_TURNING)) unit->AddUnitState(UNIT_STATE_ONVEHICLE); unit->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); @@ -364,7 +365,12 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) unit->SendClearTarget(); // SMSG_BREAK_TARGET unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures) // also adds MOVEMENTFLAG_ROOT - unit->SendMonsterMoveTransport(_me); // SMSG_MONSTER_MOVE_TRANSPORT + Movement::MoveSplineInit init(*unit); + init.DisableTransportPathTransformations(); + init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ); + init.SetFacing(0.0f); + init.SetTransportEnter(); + init.Launch(); if (_me->GetTypeId() == TYPEID_UNIT) { @@ -372,7 +378,8 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) _me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, true); // update all passenger's positions - RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); + //Passenger's spline OR vehicle movement will update positions + //RelocatePassengers(_me->GetPositionX(), _me->GetPositionY(), _me->GetPositionZ(), _me->GetOrientation()); } } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 43381267545..71ce341185e 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -461,7 +461,7 @@ void ObjectMgr::LoadCreatureTemplates() creatureTemplate.SkinLootId = fields[48].GetUInt32(); for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) - creatureTemplate.resistance[i] = fields[50 + i -1].GetInt16(); + creatureTemplate.resistance[i] = fields[49 + i - 1].GetInt16(); for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) creatureTemplate.spells[i] = fields[55 + i].GetUInt32(); @@ -1884,71 +1884,6 @@ void ObjectMgr::RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data } } -void ObjectMgr::LoadCreatureRespawnTimes() -{ - uint32 oldMSTime = getMSTime(); - - uint32 count = 0; - - PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CREATURE_RESPAWNS)); - if (!result) - { - sLog->outString(">> Loaded 0 creature respawn time."); - sLog->outString(); - return; - } - - do - { - Field* fields = result->Fetch(); - - uint32 loguid = fields[0].GetUInt32(); - uint32 respawn_time = fields[1].GetUInt32(); - uint32 instance = fields[2].GetUInt32(); - - _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); - - ++count; - } while (result->NextRow()); - - sLog->outString(">> Loaded %lu creature respawn times in %u ms", (unsigned long)_creatureRespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); - sLog->outString(); -} - -void ObjectMgr::LoadGameobjectRespawnTimes() -{ - uint32 oldMSTime = getMSTime(); - - // Remove outdated data - CharacterDatabase.DirectExecute("DELETE FROM gameobject_respawn WHERE respawnTime <= UNIX_TIMESTAMP(NOW())"); - - uint32 count = 0; - - PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_GO_RESPAWNS)); - if (!result) - { - sLog->outString(">> Loaded 0 gameobject respawn times. DB table `gameobject_respawn` is empty!"); - sLog->outString(); - return; - } - - do - { - Field* fields = result->Fetch(); - - uint32 loguid = fields[0].GetUInt32(); - uint32 respawn_time = fields[1].GetUInt32(); - uint32 instance = fields[2].GetUInt32(); - - _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = time_t(respawn_time); - - ++count; - } while (result->NextRow()); - - sLog->outString(); - sLog->outString(">> Loaded %lu gameobject respawn times in %u ms", (unsigned long)_goRespawnTimes.size(), GetMSTimeDiffToNow(oldMSTime)); -} - Player* ObjectMgr::GetPlayerByLowGUID(uint32 lowguid) const { uint64 guid = MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER); @@ -2613,7 +2548,7 @@ void ObjectMgr::LoadItemTemplateAddon() uint32 oldMSTime = getMSTime(); uint32 count = 0; - QueryResult result = WorldDatabase.Query("SELECT Id, FoodType, MinMoneyLoot, MaxMoneyLoot, SpellPPMChance FROM item_template_addon"); + QueryResult result = WorldDatabase.Query("SELECT Id, FlagsCu, FoodType, MinMoneyLoot, MaxMoneyLoot, SpellPPMChance FROM item_template_addon"); if (result) { do @@ -2626,16 +2561,8 @@ void ObjectMgr::LoadItemTemplateAddon() continue; } - uint8 buyCount = fields[1].GetUInt8(); - if (!buyCount) - { - sLog->outErrorDb("Item %u has BuyCount set to 0, corrected to 1.", itemId); - buyCount = 1; - } - - uint8 foodType = fields[1].GetUInt8(); - uint32 minMoneyLoot = fields[2].GetUInt32(); - uint32 maxMoneyLoot = fields[3].GetUInt32(); + uint32 minMoneyLoot = fields[3].GetUInt32(); + uint32 maxMoneyLoot = fields[4].GetUInt32(); if (minMoneyLoot > maxMoneyLoot) { sLog->outErrorDb("Minimum money loot specified in `item_template_addon` for item %u was greater than maximum amount, swapping.", itemId); @@ -2643,10 +2570,11 @@ void ObjectMgr::LoadItemTemplateAddon() } ItemTemplate& itemTemplate = _itemTemplateStore[itemId]; - itemTemplate.FoodType = foodType; + itemTemplate.FlagsCu = fields[1].GetUInt32(); + itemTemplate.FoodType = fields[2].GetUInt8(); itemTemplate.MinMoneyLoot = minMoneyLoot; itemTemplate.MaxMoneyLoot = maxMoneyLoot; - itemTemplate.SpellPPMRate = fields[4].GetFloat(); + itemTemplate.SpellPPMRate = fields[5].GetFloat(); ++count; } while (result->NextRow()); } @@ -2739,6 +2667,7 @@ void ObjectMgr::LoadItemSetNames() } // 0 1 2 + // 0 1 2 QueryResult result = WorldDatabase.Query("SELECT `entry`, `name`, `InventoryType` FROM `item_set_names`"); if (!result) @@ -5043,11 +4972,11 @@ void ObjectMgr::LoadSpellScriptNames() Field* fields = result->Fetch(); - int32 spellId = fields[0].GetInt32(); + int32 spellId = fields[0].GetInt32(); const char *scriptName = fields[1].GetCString(); bool allRanks = false; - if (spellId <=0) + if (spellId <= 0) { allRanks = true; spellId = -spellId; @@ -6783,7 +6712,7 @@ uint32 ObjectMgr::GetBaseXP(uint8 level) return _baseXPTable[level] ? _baseXPTable[level] : 0; } -uint32 ObjectMgr::GetXPForLevel(uint8 level) +uint32 ObjectMgr::GetXPForLevel(uint8 level) const { if (level < _playerXPperLevel.size()) return _playerXPperLevel[level]; @@ -7340,44 +7269,6 @@ void ObjectMgr::LoadNPCSpellClickSpells() sLog->outString(); } -void ObjectMgr::SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t) -{ - if (!t) - { - // Delete only - RemoveCreatureRespawnTime(loguid, instance); - return; - } - - // This function can be called from various map threads concurrently - { - _creatureRespawnTimesMutex.acquire(); - _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = t; - _creatureRespawnTimesMutex.release(); - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CREATURE_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt32(1, uint32(t)); - stmt->setUInt32(2, instance); - CharacterDatabase.Execute(stmt); -} - -void ObjectMgr::RemoveCreatureRespawnTime(uint32 loguid, uint32 instance) -{ - // This function can be called from various map threads concurrently - { - _creatureRespawnTimesMutex.acquire(); - _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; - _creatureRespawnTimesMutex.release(); - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt32(1, instance); - CharacterDatabase.Execute(stmt); -} - void ObjectMgr::DeleteCreatureData(uint32 guid) { // remove mapid*cellid -> guid_set map @@ -7388,81 +7279,6 @@ void ObjectMgr::DeleteCreatureData(uint32 guid) _creatureDataStore.erase(guid); } -void ObjectMgr::SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t) -{ - if (!t) - { - // Delete only - RemoveGORespawnTime(loguid, instance); - return; - } - - // This function can be called from different map threads concurrently - { - _goRespawnTimesMutex.acquire(); - _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = t; - _goRespawnTimesMutex.release(); - } - - PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt64(1, uint64(t)); - stmt->setUInt32(2, instance); - CharacterDatabase.Execute(stmt); -} - -void ObjectMgr::RemoveGORespawnTime(uint32 loguid, uint32 instance) -{ - // This function can be called from different map threads concurrently - { - _goRespawnTimesMutex.acquire(); - _goRespawnTimes[MAKE_PAIR64(loguid, instance)] = 0; - _goRespawnTimesMutex.release(); - } - - PreparedStatement *stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN); - stmt->setUInt32(0, loguid); - stmt->setUInt32(1, instance); - CharacterDatabase.Execute(stmt); -} - -void ObjectMgr::DeleteRespawnTimeForInstance(uint32 instance) -{ - // This function can be called from different map threads concurrently - RespawnTimes::iterator next; - - { - _goRespawnTimesMutex.acquire(); - for (RespawnTimes::iterator itr = _goRespawnTimes.begin(); itr != _goRespawnTimes.end(); itr = next) - { - next = itr; - ++next; - - if (GUID_HIPART(itr->first) == instance) - _goRespawnTimes.erase(itr); - } - _goRespawnTimesMutex.release(); - } - { - _creatureRespawnTimesMutex.acquire(); - for (RespawnTimes::iterator itr = _creatureRespawnTimes.begin(); itr != _creatureRespawnTimes.end(); itr = next) - { - next = itr; - ++next; - - if (GUID_HIPART(itr->first) == instance) - _creatureRespawnTimes.erase(itr); - } - _creatureRespawnTimesMutex.release(); - } - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE); - stmt->setUInt32(0, instance); - CharacterDatabase.Execute(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE); - stmt->setUInt32(0, instance); - CharacterDatabase.Execute(stmt); -} - void ObjectMgr::DeleteGOData(uint32 guid) { // remove mapid*cellid -> guid_set map diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 9ab7898573f..742259aa536 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -367,8 +367,6 @@ struct CellObjectGuids typedef UNORDERED_MAP<uint32/*cell_id*/, CellObjectGuids> CellObjectGuidsMap; typedef UNORDERED_MAP<uint32/*(mapid, spawnMode) pair*/, CellObjectGuidsMap> MapObjectGuids; -typedef UNORDERED_MAP<uint64/*(instance, guid) pair*/, time_t> RespawnTimes; - // Trinity string ranges #define MIN_TRINITY_STRING_ID 1 // 'trinity_string' #define MAX_TRINITY_STRING_ID 2000000000 @@ -624,14 +622,14 @@ class ObjectMgr Player* GetPlayerByLowGUID(uint32 lowguid) const; GameObjectTemplate const* GetGameObjectTemplate(uint32 entry); - GameObjectTemplateContainer const* GetGameObjectTemplates() { return &_gameObjectTemplateStore; } + GameObjectTemplateContainer const* GetGameObjectTemplates() const { return &_gameObjectTemplateStore; } int LoadReferenceVendor(int32 vendor, int32 item_id, std::set<uint32> *skip_vendors); void LoadGameObjectTemplate(); void AddGameobjectInfo(GameObjectTemplate* goinfo); CreatureTemplate const* GetCreatureTemplate(uint32 entry); - CreatureTemplateContainer const* GetCreatureTemplates() { return &_creatureTemplateStore; } + CreatureTemplateContainer const* GetCreatureTemplates() const { return &_creatureTemplateStore; } CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId); CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID); static uint32 ChooseDisplayId(uint32 team, const CreatureTemplate* cinfo, const CreatureData* data = NULL); @@ -640,7 +638,7 @@ class ObjectMgr CreatureAddon const* GetCreatureAddon(uint32 lowguid); CreatureAddon const* GetCreatureTemplateAddon(uint32 entry); ItemTemplate const* GetItemTemplate(uint32 entry); - ItemTemplateContainer const* GetItemTemplateStore() { return &_itemTemplateStore; } + ItemTemplateContainer const* GetItemTemplateStore() const { return &_itemTemplateStore; } ItemSetNameEntry const* GetItemSetNameEntry(uint32 itemId) { @@ -863,13 +861,11 @@ class ObjectMgr void LoadCreatures(); void LoadLinkedRespawn(); bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid); - void LoadCreatureRespawnTimes(); void LoadCreatureAddons(); void LoadCreatureModelInfo(); void LoadEquipmentTemplates(); void LoadGameObjectLocales(); void LoadGameobjects(); - void LoadGameobjectRespawnTimes(); void LoadItemTemplates(); void LoadItemTemplateAddon(); void LoadItemScriptNames(); @@ -927,7 +923,7 @@ class ObjectMgr std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint8 level); - uint32 GetXPForLevel(uint8 level); + uint32 GetXPForLevel(uint8 level) const; int32 GetFishingBaseSkillLevel(uint32 entry) const { @@ -1059,36 +1055,6 @@ class ObjectMgr void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance); void DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid); - time_t GetLinkedRespawnTime(uint64 guid, uint32 instance) - { - uint64 linkedGuid = GetLinkedRespawnGuid(guid); - switch (GUID_HIPART(linkedGuid)) - { - case HIGHGUID_UNIT: - return GetCreatureRespawnTime(GUID_LOPART(linkedGuid), instance); - case HIGHGUID_GAMEOBJECT: - return GetGORespawnTime(GUID_LOPART(linkedGuid), instance); - default: - return 0; - } - } - - time_t GetCreatureRespawnTime(uint32 loguid, uint32 instance) - { - TRINITY_GUARD(ACE_Thread_Mutex, _creatureRespawnTimesMutex); - return _creatureRespawnTimes[MAKE_PAIR64(loguid, instance)]; - } - void SaveCreatureRespawnTime(uint32 loguid, uint32 instance, time_t t); - void RemoveCreatureRespawnTime(uint32 loguid, uint32 instance); - time_t GetGORespawnTime(uint32 loguid, uint32 instance) - { - TRINITY_GUARD(ACE_Thread_Mutex, _goRespawnTimesMutex); - return _goRespawnTimes[MAKE_PAIR64(loguid, instance)]; - } - void SaveGORespawnTime(uint32 loguid, uint32 instance, time_t t); - void RemoveGORespawnTime(uint32 loguid, uint32 instance); - void DeleteRespawnTimeForInstance(uint32 instance); - // grid objects void AddCreatureToGrid(uint32 guid, CreatureData const* data); void RemoveCreatureFromGrid(uint32 guid, CreatureData const* data); @@ -1143,7 +1109,7 @@ class ObjectMgr void LoadScriptNames(); ScriptNameContainer &GetScriptNames() { return _scriptNamesStore; } - const char * GetScriptName(uint32 id) { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } + const char * GetScriptName(uint32 id) const { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } uint32 GetScriptId(const char *name); SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const @@ -1321,10 +1287,6 @@ class ObjectMgr TrinityStringLocaleContainer _trinityStringLocaleStore; GossipMenuItemsLocaleContainer _gossipMenuItemsLocaleStore; PointOfInterestLocaleContainer _pointOfInterestLocaleStore; - RespawnTimes _creatureRespawnTimes; - ACE_Thread_Mutex _creatureRespawnTimesMutex; - RespawnTimes _goRespawnTimes; - ACE_Thread_Mutex _goRespawnTimesMutex; CacheVendorItemContainer _cacheVendorItemStore; CacheTrainerSpellContainer _cacheTrainerSpellStore; @@ -1339,7 +1301,6 @@ class ObjectMgr GO_TO_GO, GO_TO_CREATURE, // GO is dependant on creature }; - HotfixData _hotfixData; }; diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 54bc1206e18..75df3e67c5a 100755 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -1325,11 +1325,16 @@ namespace Trinity { public: UnitAuraCheck(bool present, uint32 spellId, uint64 casterGUID = 0) : _present(present), _spellId(spellId), _casterGUID(casterGUID) {} - bool operator()(Unit* unit) + bool operator()(Unit* unit) const { return unit->HasAura(_spellId, _casterGUID) == _present; } + bool operator()(WorldObject* object) const + { + return object->ToUnit() && object->ToUnit()->HasAura(_spellId, _casterGUID) == _present; + } + private: bool _present; uint32 _spellId; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 4c6b6249887..743d56886f0 100755 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -556,7 +556,7 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod &method /*= GROUP_REMOV roll->playerVote.erase(itr2); - CountRollVote(guid, roll->itemGUID, GetMembersCount()-1, MAX_ROLL_TYPE); + CountRollVote(guid, roll->itemGUID, MAX_ROLL_TYPE); } // Update subgroups @@ -763,7 +763,7 @@ void Group::SendLootStartRoll(uint32 countDown, uint32 mapid, const Roll &r) WorldPacket data(SMSG_LOOT_START_ROLL, (8+4+4+4+4+4+4+1)); data << uint64(r.itemGUID); // guid of rolled item data << uint32(mapid); // 3.3.3 mapid - data << uint32(r.itemSlot); // slot + data << uint32(r.itemSlot); // itemslot data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for data << uint32(r.itemRandomSuffix); // randomSuffix data << uint32(r.itemRandomPropId); // item random property ID @@ -791,7 +791,7 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, WorldPacket data(SMSG_LOOT_START_ROLL, (8 + 4 + 4 + 4 + 4 + 4 + 4 + 1)); data << uint64(r.itemGUID); // guid of rolled item data << uint32(mapId); // 3.3.3 mapid - data << uint32(r.totalPlayersRolling); // maybe the number of players rolling for it??? + data << uint32(r.itemSlot); // itemslot data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for data << uint32(r.itemRandomSuffix); // randomSuffix data << uint32(r.itemRandomPropId); // item random property ID @@ -805,20 +805,20 @@ void Group::SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, p->GetSession()->SendPacket(&data); } -void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRoll(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll) { WorldPacket data(SMSG_LOOT_ROLL, (8+4+8+4+4+4+1+1+1)); - data << uint64(SourceGuid); // guid of the item rolled - data << uint32(0); // unknown, maybe amount of players - data << uint64(TargetGuid); - data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for - data << uint32(r.itemRandomSuffix); // randomSuffix - data << uint32(r.itemRandomPropId); // Item random property ID - data << uint8(RollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number - data << uint8(RollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll - data << uint8(0); // auto pass on NeedBeforeGreed loot because player cannot use the object + data << uint64(sourceGuid); // guid of the item rolled + data << uint32(roll.itemSlot); // slot + data << uint64(targetGuid); + data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for + data << uint32(roll.itemRandomSuffix); // randomSuffix + data << uint32(roll.itemRandomPropId); // Item random property ID + data << uint8(rollNumber); // 0: "Need for: [item name]" > 127: "you passed on: [item name]" Roll number + data << uint8(rollType); // 0: "Need for: [item name]" 0: "You have selected need for [item name] 1: need roll 2: greed roll + data << uint8(0); // 1: "You automatically passed on: %s because you cannot loot that item." - Possibly used in need befor greed - for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr) + for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { Player* p = ObjectAccessor::FindPlayer(itr->first); if (!p || !p->GetSession()) @@ -829,19 +829,19 @@ void Group::SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, } } -void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r) +void Group::SendLootRollWon(uint64 sourceGuid, uint64 targetGuid, uint8 rollNumber, uint8 rollType, Roll const& roll) { WorldPacket data(SMSG_LOOT_ROLL_WON, (8+4+4+4+4+8+1+1)); - data << uint64(SourceGuid); // guid of the item rolled - data << uint32(0); // unknown, maybe amount of players - data << uint32(r.itemid); // the itemEntryId for the item that shall be rolled for - data << uint32(r.itemRandomSuffix); // randomSuffix - data << uint32(r.itemRandomPropId); // Item random property - data << uint64(TargetGuid); // guid of the player who won. - data << uint8(RollNumber); // rollnumber realted to SMSG_LOOT_ROLL - data << uint8(RollType); // Rolltype related to SMSG_LOOT_ROLL + data << uint64(sourceGuid); // guid of the item rolled + data << uint32(roll.itemSlot); // slot + data << uint32(roll.itemid); // the itemEntryId for the item that shall be rolled for + data << uint32(roll.itemRandomSuffix); // randomSuffix + data << uint32(roll.itemRandomPropId); // Item random property + data << uint64(targetGuid); // guid of the player who won. + data << uint8(rollNumber); // rollnumber realted to SMSG_LOOT_ROLL + data << uint8(rollType); // rollType related to SMSG_LOOT_ROLL - for (Roll::PlayerVote::const_iterator itr=r.playerVote.begin(); itr != r.playerVote.end(); ++itr) + for (Roll::PlayerVote::const_iterator itr = roll.playerVote.begin(); itr != roll.playerVote.end(); ++itr) { Player* p = ObjectAccessor::FindPlayer(itr->first); if (!p || !p->GetSession()) @@ -852,11 +852,11 @@ void Group::SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumb } } -void Group::SendLootAllPassed(uint32 numberOfPlayers, Roll const& roll) +void Group::SendLootAllPassed(Roll const& roll) { WorldPacket data(SMSG_LOOT_ALL_PASSED, (8+4+4+4+4)); data << uint64(roll.itemGUID); // Guid of the item rolled - data << uint32(numberOfPlayers); // The number of players rolling for it + data << uint32(roll.itemSlot); // Item loot slot data << uint32(roll.itemid); // The itemEntryId for the item that shall be rolled for data << uint32(roll.itemRandomPropId); // Item random property ID data << uint32(roll.itemRandomSuffix); // Item random suffix ID @@ -1099,7 +1099,7 @@ void Group::MasterLoot(Loot* /*loot*/, WorldObject* pLootedObject) } } -void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choice) +void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint8 Choice) { Rolls::iterator rollI = GetRoll(Guid); if (rollI == RollId.end()) @@ -1140,7 +1140,7 @@ void Group::CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers } if (roll->totalPass + roll->totalNeed + roll->totalGreed >= roll->totalPlayersRolling) - CountTheRoll(rollI, NumberOfPlayers); + CountTheRoll(rollI); } //called when roll timer expires @@ -1149,7 +1149,7 @@ void Group::EndRoll(Loot* pLoot) for (Rolls::iterator itr = RollId.begin(); itr != RollId.end();) { if ((*itr)->getLoot() == pLoot) { - CountTheRoll(itr, GetMembersCount()); //i don't have to edit player votes, who didn't vote ... he will pass + CountTheRoll(itr); //i don't have to edit player votes, who didn't vote ... he will pass itr = RollId.begin(); } else @@ -1157,7 +1157,7 @@ void Group::EndRoll(Loot* pLoot) } } -void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) +void Group::CountTheRoll(Rolls::iterator rollI) { Roll* roll = *rollI; if (!roll->isValid()) // is loot already deleted ? @@ -1280,7 +1280,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) } else { - SendLootAllPassed(NumberOfPlayers, *roll); + SendLootAllPassed(*roll); // remove is_blocked so that the item is lootable by all players LootItem* item = &(roll->getLoot()->items[roll->itemSlot]); @@ -2107,20 +2107,6 @@ bool Group::HasFreeSlotSubGroup(uint8 subgroup) const return (m_subGroupsCounts && m_subGroupsCounts[subgroup] < MAXGROUPSIZE); } -Group::MemberSlotList const& Group::GetMemberSlots() const -{ - return m_memberSlots; -} - -GroupReference* Group::GetFirstMember() -{ - return m_memberMgr.getFirst(); -} - -uint32 Group::GetMembersCount() const -{ - return m_memberSlots.size(); -} uint8 Group::GetMemberGroup(uint64 guid) const { diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 08246614627..f909b755829 100755 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -232,9 +232,11 @@ class Group bool SameSubGroup(Player const* member1, Player const* member2) const; bool HasFreeSlotSubGroup(uint8 subgroup) const; - MemberSlotList const& GetMemberSlots() const; - GroupReference* GetFirstMember(); - uint32 GetMembersCount() const; + MemberSlotList const& GetMemberSlots() const { return m_memberSlots; } + GroupReference* GetFirstMember() { return m_memberMgr.getFirst(); } + GroupReference const* GetFirstMember() const { return m_memberMgr.getFirst(); } + uint32 GetMembersCount() const { return m_memberSlots.size(); } + uint8 GetMemberGroup(uint64 guid) const; void ConvertToLFG(); @@ -279,14 +281,14 @@ class Group void SendLootStartRollToPlayer(uint32 countDown, uint32 mapId, Player* p, bool canNeed, Roll const& r); void SendLootRoll(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); void SendLootRollWon(uint64 SourceGuid, uint64 TargetGuid, uint8 RollNumber, uint8 RollType, const Roll &r); - void SendLootAllPassed(uint32 NumberOfPlayers, const Roll &r); + void SendLootAllPassed(Roll const& roll); void SendLooter(Creature* creature, Player* pLooter); void GroupLoot(Loot* loot, WorldObject* pLootedObject); void NeedBeforeGreed(Loot* loot, WorldObject* pLootedObject); void MasterLoot(Loot* loot, WorldObject* pLootedObject); Rolls::iterator GetRoll(uint64 Guid); - void CountTheRoll(Rolls::iterator roll, uint32 NumberOfPlayers); - void CountRollVote(uint64 playerGUID, uint64 Guid, uint32 NumberOfPlayers, uint8 Choise); + void CountTheRoll(Rolls::iterator roll); + void CountRollVote(uint64 playerGUID, uint64 Guid, uint8 Choise); void EndRoll(Loot* loot); // related to disenchant rolls diff --git a/src/server/game/Groups/GroupRefManager.h b/src/server/game/Groups/GroupRefManager.h index 9bcc05f8724..d9fef8611de 100755 --- a/src/server/game/Groups/GroupRefManager.h +++ b/src/server/game/Groups/GroupRefManager.h @@ -28,7 +28,8 @@ class GroupReference; class GroupRefManager : public RefManager<Group, Player> { public: - GroupReference* getFirst() { return ((GroupReference*) RefManager<Group, Player>::getFirst()); } + GroupReference* getFirst() { return ((GroupReference*)RefManager<Group, Player>::getFirst()); } + GroupReference const* getFirst() const { return ((GroupReference const*)RefManager<Group, Player>::getFirst()); } }; #endif diff --git a/src/server/game/Groups/GroupReference.h b/src/server/game/Groups/GroupReference.h index 2048fd9cb0d..7960dd21035 100755 --- a/src/server/game/Groups/GroupReference.h +++ b/src/server/game/Groups/GroupReference.h @@ -35,6 +35,7 @@ class GroupReference : public Reference<Group, Player> GroupReference() : Reference<Group, Player>(), iSubGroup(0) {} ~GroupReference() { unlink(); } GroupReference* next() { return (GroupReference*)Reference<Group, Player>::next(); } + GroupReference const* next() const { return (GroupReference const*)Reference<Group, Player>::next(); } uint8 getSubGroup() const { return iSubGroup; } void setSubGroup(uint8 pSubGroup) { iSubGroup = pSubGroup; } }; diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index dfeb3f7cad9..b57e9970dab 100755 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -2093,7 +2093,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) if (player->GetGuildId() != 0) return false; } - else if (Player::GetGuildIdFromGuid(guid) != 0) + else if (Player::GetGuildIdFromDB(guid) != 0) return false; // Remove all player signs from another petitions diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 27eb559fb68..95204dfa353 100755 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -161,7 +161,7 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) etime *= MINUTE; - switch(etime) + switch (etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 887bebe5656..1c79b20ce81 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1868,9 +1868,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) case RACE_NIGHTELF: stmt->setUInt16(1, 113); break; - case RACE_WORGEN: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 791, 300, 300)", lowGuid); - break; + case RACE_WORGEN: + stmt->setUInt16(1, 791); + break; case RACE_UNDEAD_PLAYER: stmt->setUInt16(1, 673); break; @@ -1883,9 +1883,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data) case RACE_BLOODELF: stmt->setUInt16(1, 137); break; - case RACE_GOBLIN: - trans->PAppend("INSERT INTO `character_skills` (guid, skill, value, max) VALUES (%u, 792, 300, 300)", lowGuid); - break; + case RACE_GOBLIN: + stmt->setUInt16(1, 792); + break; } trans->Append(stmt); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index d725419ac84..eadc0958518 100755 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -458,24 +458,20 @@ void WorldSession::HandleLootMethodOpcode(WorldPacket & recv_data) group->SendUpdate(); } -void WorldSession::HandleLootRoll(WorldPacket &recv_data) +void WorldSession::HandleLootRoll(WorldPacket& recvData) { + uint64 guid; + uint32 itemSlot; + uint8 rollType; + recvData >> guid; // guid of the item rolled + recvData >> itemSlot; + recvData >> rollType; // 0: pass, 1: need, 2: greed + Group* group = GetPlayer()->GetGroup(); if (!group) - { - recv_data.rfinish(); return; - } - uint64 Guid; - uint32 NumberOfPlayers; - uint8 rollType; - recv_data >> Guid; //guid of the item rolled - recv_data >> NumberOfPlayers; - recv_data >> rollType; //0: pass, 1: need, 2: greed - - // everything's fine, do it - group->CountRollVote(GetPlayer()->GetGUID(), Guid, NumberOfPlayers, rollType); + group->CountRollVote(GetPlayer()->GetGUID(), guid, rollType); switch (rollType) { diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index 2d85a4cb689..5baa54a2779 100755 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -1369,6 +1369,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) _player->ToggleMetaGemsActive(slot, true); //turn on all metagems (except for target item) + _player->RemoveTradeableItem(itemTarget); itemTarget->ClearSoulboundTradeable(_player); // clear tradeable flag } diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index 82afdfb9044..9c66ca44383 100755 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -529,7 +529,7 @@ void WorldSession::SendLfgBootPlayer(const LfgPlayerBoot* pBoot) } sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_LFG_BOOT_PROPOSAL_UPDATE [" UI64FMTD "] inProgress: %u - didVote: %u - agree: %u - victim: [" UI64FMTD "] votes: %u - agrees: %u - left: %u - needed: %u - reason %s", guid, uint8(pBoot->inProgress), uint8(playerVote != LFG_ANSWER_PENDING), uint8(playerVote == LFG_ANSWER_AGREE), pBoot->victim, votesNum, agreeNum, secsleft, pBoot->votedNeeded, pBoot->reason.c_str()); - WorldPacket data(SMSG_LFG_BOOT_PLAYER, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length()); + WorldPacket data(SMSG_LFG_BOOT_PROPOSAL_UPDATE, 1 + 1 + 1 + 8 + 4 + 4 + 4 + 4 + pBoot->reason.length()); data << uint8(pBoot->inProgress); // Vote in progress data << uint8(playerVote != LFG_ANSWER_PENDING); // Did Vote data << uint8(playerVote == LFG_ANSWER_AGREE); // Agree diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index 8e4b41a9be4..339c7a44d9f 100755 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -220,16 +220,18 @@ void WorldSession::HandleLootOpcode(WorldPacket & recv_data) GetPlayer()->InterruptNonMeleeSpells(false); } -void WorldSession::HandleLootReleaseOpcode(WorldPacket & recv_data) +void WorldSession::HandleLootReleaseOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_RELEASE"); // cheaters can modify lguid to prevent correct apply loot release code and re-loot // use internal stored guid - recv_data.read_skip<uint64>(); // guid; + uint64 guid; + recvData >> guid; if (uint64 lguid = GetPlayer()->GetLootGUID()) - DoLootRelease(lguid); + if (lguid == guid) + DoLootRelease(lguid); } void WorldSession::DoLootRelease(uint64 lguid) diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index 988857558c9..ce056d2729c 100755 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -107,7 +107,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) uint32 reqmoney = cost + money; - if (!player->HasEnoughMoney(reqmoney)) + if (!player->HasEnoughMoney(reqmoney) && !player->isGameMaster()) { player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY); return; diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 247db1975a4..46e40e16c08 100755 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -494,7 +494,7 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket & recv_data) uint32 newZone; recv_data >> newZone; - sLog->outDetail("WORLD: Recvd ZONE_UPDATE: %u", newZone); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd ZONE_UPDATE: %u", newZone); // use server size data uint32 newzone, newarea; @@ -737,7 +737,7 @@ void WorldSession::HandleBugOpcode(WorldPacket & recv_data) void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) { - sLog->outDetail("WORLD: Received CMSG_RECLAIM_CORPSE"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RECLAIM_CORPSE"); uint64 guid; recv_data >> guid; @@ -774,7 +774,7 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) void WorldSession::HandleResurrectResponseOpcode(WorldPacket & recv_data) { - sLog->outDetail("WORLD: Received CMSG_RESURRECT_RESPONSE"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_RESURRECT_RESPONSE"); uint64 guid; uint8 status; @@ -945,7 +945,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recv_data) void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) { - sLog->outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); uint32 type, timestamp, decompressedSize; recv_data >> type >> timestamp >> decompressedSize; @@ -1000,7 +1000,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) { - sLog->outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); uint32 type; recv_data >> type; @@ -1079,12 +1079,12 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) void WorldSession::HandleCompleteCinematic(WorldPacket & /*recv_data*/) { - sLog->outStaticDebug("WORLD: Player is watching cinema"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_COMPLETE_CINEMATIC"); } void WorldSession::HandleNextCinematicCamera(WorldPacket & /*recv_data*/) { - sLog->outStaticDebug("WORLD: Which movie to play"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_NEXT_CINEMATIC_CAMERA"); } void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) @@ -1127,7 +1127,7 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket & recv_data) void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data) { - sLog->outStaticDebug("WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_MOVE_FEATHER_FALL_ACK"); // no used recv_data.rfinish(); // prevent warnings spam @@ -1215,13 +1215,17 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recv_data) { uint64 guid; recv_data >> guid; - sLog->outStaticDebug("Inspected guid is " UI64FMTD, guid); + + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_INSPECT"); _player->SetSelection(guid); Player* player = ObjectAccessor::FindPlayer(guid); - if (!player) // wrong player + if (!player) + { + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_INSPECT: No player found from GUID: " UI64FMTD, guid); return; + } uint32 talent_points = 41; WorldPacket data(SMSG_INSPECT_TALENT, 8 + 4 + 1 + 1 + talent_points + 8 + 4 + 8 + 4); @@ -1256,7 +1260,7 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) if (!player) { - sLog->outError("InspectHonorStats: WTF, player not found..."); + sLog->outDebug(LOG_FILTER_NETWORKIO, "MSG_INSPECT_HONOR_STATS: No player found from GUID: " UI64FMTD, guid); return; } @@ -1270,10 +1274,6 @@ void WorldSession::HandleInspectHonorStatsOpcode(WorldPacket& recv_data) void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) { - // write in client console: worldport 469 452 6454 2536 180 or /console worldport 469 452 6454 2536 180 - // Received opcode CMSG_WORLD_TELEPORT - // Time is ***, map=469, x=452.000000, y=6454.000000, z=2536.000000, orient=3.141593 - uint32 time; uint32 mapid; float PositionX; @@ -1288,20 +1288,20 @@ void WorldSession::HandleWorldTeleportOpcode(WorldPacket& recv_data) recv_data >> PositionZ; recv_data >> Orientation; // o (3.141593 = 180 degrees) - //sLog->outDebug("Received opcode CMSG_WORLD_TELEPORT"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_WORLD_TELEPORT"); + if (GetPlayer()->isInFlight()) { sLog->outDebug(LOG_FILTER_NETWORKIO, "Player '%s' (GUID: %u) in flight, ignore worldport command.", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow()); return; } - sLog->outStaticDebug("Time %u sec, map=%u, x=%f, y=%f, z=%f, orient=%f", time/1000, mapid, PositionX, PositionY, PositionZ, Orientation); + sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_WORLD_TELEPORT: Player = %s, Time = %u, map = %u, x = %f, y = %f, z = %f, o = %f", GetPlayer()->GetName(), time, mapid, PositionX, PositionY, PositionZ, Orientation); if (AccountMgr::IsAdminAccount(GetSecurity())) GetPlayer()->TeleportTo(mapid, PositionX, PositionY, PositionZ, Orientation); else SendNotification(LANG_YOU_NOT_HAVE_PERMISSION); - sLog->outDebug(LOG_FILTER_NETWORKIO, "Received worldport command from player %s", GetPlayer()->GetName()); } void WorldSession::HandleWhoisOpcode(WorldPacket& recv_data) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 40d63235af3..598dafb200a 100755 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -193,7 +193,7 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data) sLog->outDebug(LOG_FILTER_NETWORKIO, "CMSG_MOVE_TELEPORT_ACK"); BitStream mask = recv_data.ReadBitStream(8); - + uint32 flags, time; recv_data >> flags >> time; @@ -264,6 +264,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) // ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck if (plrMover && plrMover->IsBeingTeleported()) { + recvData.rfinish(); // prevent warnings spam return; } @@ -302,16 +303,42 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recvData) } // if we boarded a transport, add us to it - if (plrMover && !plrMover->GetTransport()) + if (plrMover) { - // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list - for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) + if (!plrMover->GetTransport()) { - if ((*iter)->GetGUID() == movementInfo.t_guid) + // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list + for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) { - plrMover->m_transport = (*iter); - (*iter)->AddPassenger(plrMover); - break; + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + plrMover->m_transport = *iter; + (*iter)->AddPassenger(plrMover); + break; + } + } + } + else if (plrMover->GetTransport()->GetGUID() != movementInfo.t_guid) + { + bool foundNewTransport = false; + plrMover->m_transport->RemovePassenger(plrMover); + for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter) + { + if ((*iter)->GetGUID() == movementInfo.t_guid) + { + foundNewTransport = true; + plrMover->m_transport = *iter; + (*iter)->AddPassenger(plrMover); + break; + } + } + + if (!foundNewTransport) + { + plrMover->m_transport = NULL; + movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); + movementInfo.t_time = 0; + movementInfo.t_seat = -1; } } } @@ -971,4 +998,4 @@ void WorldSession::WriteMovementInfo(WorldPacket &data, MovementInfo* mi) WPError(false, "Incorrect sequence element detected at ReadMovementInfo"); } } -}
\ No newline at end of file +} diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 5f7e4ce04a8..3660bfbfcc7 100755 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -344,9 +344,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid if (unit_target2->GetTypeId() == TYPEID_PLAYER) pet->SendUpdateToPlayer((Player*)unit_target2); } + if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) - pet->SendUpdateToPlayer(powner->ToPlayer()); + pet->SendUpdateToPlayer(powner->ToPlayer()); + result = SPELL_CAST_OK; } @@ -738,7 +740,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { - sLog->outDetail("WORLD: CMSG_PET_CAST_SPELL"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_PET_CAST_SPELL"); uint64 guid; uint8 castCount; diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index f0e681b535c..c22fc309770 100755 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -113,7 +113,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket & recv_data) ObjectMgr::GetLocaleString(cl->SubName, loc_idx, SubName); } } - sLog->outDetail("WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry); // guess size WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100); data << uint32(entry); // creature entry @@ -184,7 +184,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) ObjectMgr::GetLocaleString(gl->CastBarCaption, loc_idx, CastBarCaption); } } - sLog->outDetail("WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_GAMEOBJECT_QUERY '%s' - Entry: %u. ", info->name.c_str(), entry); WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 150); data << uint32(entry); data << uint32(info->type); @@ -215,7 +215,7 @@ void WorldSession::HandleGameObjectQueryOpcode(WorldPacket & recv_data) void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) { - sLog->outDetail("WORLD: Received MSG_CORPSE_QUERY"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received MSG_CORPSE_QUERY"); Corpse* corpse = GetPlayer()->GetCorpse(); @@ -270,7 +270,7 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) uint64 guid; recv_data >> textID; - sLog->outDetail("WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID); recv_data >> guid; GetPlayer()->SetSelection(guid); @@ -350,7 +350,7 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket & recv_data) /// Only _static_ data is sent in this packet !!! void WorldSession::HandlePageTextQueryOpcode(WorldPacket & recv_data) { - sLog->outDetail("WORLD: Received CMSG_PAGE_TEXT_QUERY"); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_PAGE_TEXT_QUERY"); uint32 pageID; recv_data >> pageID; diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index ccd2e178f88..2998b8a1c75 100755 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -324,7 +324,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(quest, true)) + if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) { _player->AddQuest(nextQuest, object); if (_player->CanCompleteQuest(nextQuest->GetQuestId())) @@ -343,7 +343,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket & recv_data) // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { - if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(quest, true)) + if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true) && _player->CanTakeQuest(nextQuest, true)) { _player->AddQuest(nextQuest, object); if (_player->CanCompleteQuest(nextQuest->GetQuestId())) @@ -496,10 +496,9 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recv_data) if (!_player->CanInteractWithQuestGiver(object)) return; - Quest const* quest = sObjectMgr->GetQuestTemplate(questId); - if (quest) + if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { - if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId)==QUEST_STATUS_NONE) + if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) { sLog->outError("Possible hacking attempt: Player %s [playerGuid: %u] tried to complete questId [entry: %u] without being in possession of the questId!", _player->GetName(), _player->GetGUIDLow(), questId); diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index c56d86d11db..5823a38fb42 100755 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -100,7 +100,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) return; } - sLog->outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size()); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, castCount: %u, spellId: %u, Item: %u, glyphIndex: %u, data length = %i", bagIndex, slot, castCount, spellId, pItem->GetEntry(), glyphIndex, (uint32)recvPacket.size()); ItemTemplate const* proto = pItem->GetTemplate(); if (!proto) @@ -176,7 +176,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) { - sLog->outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); + sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_OPEN_ITEM packet, data length = %i", (uint32)recvPacket.size()); Player* pUser = _player; @@ -669,13 +669,16 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) recvPacket >> z; Unit* caster = ObjectAccessor::GetUnit(*_player, casterGuid); - Spell* spell = caster ? caster->FindCurrentSpellBySpellId(spellId) : NULL; - if (spell && spell->m_targets.HasDst()) - { - Position pos = *spell->m_targets.GetDstPos(); - pos.Relocate(x, y, z); - spell->m_targets.ModDst(pos); - } + if (!caster) + return; + + Spell* spell = caster->FindCurrentSpellBySpellId(spellId); + if (!spell || !spell->m_targets.HasDst()) + return; + + Position pos = *spell->m_targets.GetDstPos(); + pos.Relocate(x, y, z); + spell->m_targets.ModDst(pos); WorldPacket data(SMSG_SET_PROJECTILE_POSITION, 21); data << uint64(casterGuid); @@ -683,5 +686,5 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) data << float(x); data << float(y); data << float(z); - SendPacket(&data); + caster->SendMessageToSet(&data, true); } diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 8078a91d082..59bb86cb68e 100755 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -543,7 +543,10 @@ void InstanceSaveManager::_ResetInstance(uint32 mapid, uint32 instanceId) if (iMap && iMap->IsDungeon()) ((InstanceMap*)iMap)->Reset(INSTANCE_RESET_RESPAWN_DELAY); - sObjectMgr->DeleteRespawnTimeForInstance(instanceId); // even if map is not loaded + if (iMap) + iMap->DeleteRespawnTimes(); + else + Map::DeleteRespawnTimesInDB(mapid, instanceId); // Free up the instance id and allow it to be reused sMapMgr->FreeInstanceId(instanceId); diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 2100eb26346..24338d5f0ad 100755 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -356,18 +356,14 @@ bool LootItem::AllowedForPlayer(Player const* player) const if ((pProto->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY) && player->GetTeam() != ALLIANCE) return false; - if (needs_quest) - { - // Checking quests for quest-only drop (check only quests requirements in this case) - if (!player->HasQuestForItem(itemid)) - return false; - } - else - { - // Not quest only drop (check quest starting items for already accepted non-repeatable quests) - if (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE && !player->HasQuestForItem(itemid)) - return false; - } + // check quest requirements + if (!(pProto->FlagsCu & ITEM_FLAGS_CU_IGNORE_QUEST_STATUS) && ((needs_quest || (pProto->StartQuest && player->GetQuestStatus(pProto->StartQuest) != QUEST_STATUS_NONE)) && !player->HasQuestForItem(itemid))) + if (Group const* group = player->GetGroup()) + { + if (pProto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT || ((pProto->Flags & ITEM_PROTO_FLAG_PARTY_LOOT) == 0 && (group->GetLootMethod() != MASTER_LOOT || group->GetLooterGuid() != player->GetGUID()))) + return false; + } + else return false; return true; } @@ -483,7 +479,7 @@ void Loot::FillNotNormalLootFor(Player* player, bool presentAtLooting) if (!item->is_looted && item->freeforall && item->AllowedForPlayer(player)) if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item->itemid)) - if (proto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + if (proto->IsCurrencyToken()) player->StoreLootItem(i, this); } } @@ -899,6 +895,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) } LootSlotType slotType = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT; + LootSlotType partySlotType = lv.permission == MASTER_PERMISSION ? LOOT_SLOT_TYPE_MASTER : (lv.permission == GROUP_PERMISSION ? LOOT_SLOT_TYPE_ROLL_ONGOING : slotType); QuestItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems(); QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUIDLow()); if (q_itr != lootPlayerQuestItems.end()) @@ -911,7 +908,10 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { b << uint8(l.items.size() + (qi - q_list->begin())); b << item; - b << uint8(slotType); + if (!item.freeforall) + b << uint8(partySlotType); + else + b << uint8(slotType); ++itemsShown; } } @@ -929,7 +929,10 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { b << uint8(fi->index); b << item; - b << uint8(slotType); + if (!item.freeforall) + b << uint8(partySlotType); + else + b << uint8(slotType); ++itemsShown; } } @@ -947,7 +950,10 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { b << uint8(ci->index); b << item; - b << uint8(slotType); + if (!item.freeforall) + b << uint8(partySlotType); + else + b << uint8(slotType); ++itemsShown; } } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 073ceae5b62..8df8feb6cac 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -1230,7 +1230,7 @@ bool GridMap::loadLiquidData(FILE* in, uint32 offset, uint32 /*size*/) return true; } -uint16 GridMap::getArea(float x, float y) +uint16 GridMap::getArea(float x, float y) const { if (!_areaMap) return _gridArea; @@ -1463,7 +1463,7 @@ float GridMap::getHeightFromUint16(float x, float y) const return (float)((a * x) + (b * y) + c)*_gridIntHeightMultiplier + _gridHeight; } -float GridMap::getLiquidLevel(float x, float y) +float GridMap::getLiquidLevel(float x, float y) const { if (!_liquidMap) return _liquidLevel; @@ -1483,7 +1483,7 @@ float GridMap::getLiquidLevel(float x, float y) } // Why does this return LIQUID data? -uint8 GridMap::getTerrainType(float x, float y) +uint8 GridMap::getTerrainType(float x, float y) const { if (!_liquidFlags) return 0; @@ -2633,7 +2633,7 @@ void InstanceMap::UnloadAll() ASSERT(!HavePlayers()); if (m_resetAfterUnload == true) - sObjectMgr->DeleteRespawnTimeForInstance(GetInstanceId()); + DeleteRespawnTimes(); Map::UnloadAll(); } @@ -2782,3 +2782,134 @@ void Map::UpdateIteratorBack(Player* player) if (m_mapRefIter == player->GetMapRef()) m_mapRefIter = m_mapRefIter->nocheck_prev(); } + +void Map::SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime) +{ + if (!respawnTime) + { + // Delete only + RemoveCreatureRespawnTime(dbGuid); + return; + } + + _creatureRespawnTimes[dbGuid] = respawnTime; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CREATURE_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt32(1, uint32(respawnTime)); + stmt->setUInt16(2, GetId()); + stmt->setUInt32(3, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::RemoveCreatureRespawnTime(uint32 dbGuid) +{ + _creatureRespawnTimes.erase(dbGuid); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt16(1, GetId()); + stmt->setUInt32(2, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::SaveGORespawnTime(uint32 dbGuid, time_t respawnTime) +{ + if (!respawnTime) + { + // Delete only + RemoveGORespawnTime(dbGuid); + return; + } + + _goRespawnTimes[dbGuid] = respawnTime; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt32(1, uint32(respawnTime)); + stmt->setUInt16(2, GetId()); + stmt->setUInt32(3, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::RemoveGORespawnTime(uint32 dbGuid) +{ + _goRespawnTimes.erase(dbGuid); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN); + stmt->setUInt32(0, dbGuid); + stmt->setUInt16(1, GetId()); + stmt->setUInt32(2, GetInstanceId()); + CharacterDatabase.Execute(stmt); +} + +void Map::LoadRespawnTimes() +{ + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CREATURE_RESPAWNS); + stmt->setUInt16(0, GetId()); + stmt->setUInt32(1, GetInstanceId()); + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + { + do + { + Field* fields = result->Fetch(); + uint32 loguid = fields[0].GetUInt32(); + uint32 respawnTime = fields[1].GetUInt32(); + + _creatureRespawnTimes[loguid] = time_t(respawnTime); + } while (result->NextRow()); + } + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GO_RESPAWNS); + stmt->setUInt16(0, GetId()); + stmt->setUInt32(1, GetInstanceId()); + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + { + do + { + Field* fields = result->Fetch(); + uint32 loguid = fields[0].GetUInt32(); + uint32 respawnTime = fields[1].GetUInt32(); + + _goRespawnTimes[loguid] = time_t(respawnTime); + } while (result->NextRow()); + } +} + +void Map::DeleteRespawnTimes() +{ + _creatureRespawnTimes.clear(); + _goRespawnTimes.clear(); + + DeleteRespawnTimesInDB(GetId(), GetInstanceId()); +} + +void Map::DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId) +{ + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE); + stmt->setUInt16(0, mapId); + stmt->setUInt32(1, instanceId); + CharacterDatabase.Execute(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE); + stmt->setUInt16(0, mapId); + stmt->setUInt32(1, instanceId); + CharacterDatabase.Execute(stmt); +} + +time_t Map::GetLinkedRespawnTime(uint64 guid) const +{ + uint64 linkedGuid = sObjectMgr->GetLinkedRespawnGuid(guid); + switch (GUID_HIPART(linkedGuid)) + { + case HIGHGUID_UNIT: + return GetCreatureRespawnTime(GUID_LOPART(linkedGuid)); + case HIGHGUID_GAMEOBJECT: + return GetGORespawnTime(GUID_LOPART(linkedGuid)); + default: + break; + } + + return time_t(0); +} + diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 6ba08646f25..6d526f23a94 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -193,10 +193,10 @@ public: bool loadData(char* filaname); void unloadData(); - uint16 getArea(float x, float y); - inline float getHeight(float x, float y) {return (this->*_gridGetHeight)(x, y);} - float getLiquidLevel(float x, float y); - uint8 getTerrainType(float x, float y); + uint16 getArea(float x, float y) const; + inline float getHeight(float x, float y) const {return (this->*_gridGetHeight)(x, y);} + float getLiquidLevel(float x, float y) const; + uint8 getTerrainType(float x, float y) const; ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0); }; @@ -443,6 +443,38 @@ class Map : public GridRefManager<NGridType> void Insert(const GameObjectModel& mdl) { _dynamicTree.insert(mdl); } bool Contains(const GameObjectModel& mdl) const { return _dynamicTree.contains(mdl);} bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist); + + /* + RESPAWN TIMES + */ + time_t GetLinkedRespawnTime(uint64 guid) const; + time_t GetCreatureRespawnTime(uint32 dbGuid) const + { + UNORDERED_MAP<uint32 /*dbGUID*/, time_t>::const_iterator itr = _creatureRespawnTimes.find(dbGuid); + if (itr != _creatureRespawnTimes.end()) + return itr->second; + + return time_t(0); + } + + time_t GetGORespawnTime(uint32 dbGuid) const + { + UNORDERED_MAP<uint32 /*dbGUID*/, time_t>::const_iterator itr = _goRespawnTimes.find(dbGuid); + if (itr != _goRespawnTimes.end()) + return itr->second; + + return time_t(0); + } + + void SaveCreatureRespawnTime(uint32 dbGuid, time_t respawnTime); + void RemoveCreatureRespawnTime(uint32 dbGuid); + void SaveGORespawnTime(uint32 dbGuid, time_t respawnTime); + void RemoveGORespawnTime(uint32 dbGuid); + void LoadRespawnTimes(); + void DeleteRespawnTimes(); + + static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId); + private: void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); @@ -488,6 +520,7 @@ class Map : public GridRefManager<NGridType> void ScriptsProcess(); void UpdateActiveCells(const float &x, const float &y, const uint32 t_diff); + protected: void SetUnloadReferenceLock(const GridCoord &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); } @@ -570,6 +603,9 @@ class Map : public GridRefManager<NGridType> else m_activeNonPlayers.erase(obj); } + + UNORDERED_MAP<uint32 /*dbGUID*/, time_t> _creatureRespawnTimes; + UNORDERED_MAP<uint32 /*dbGUID*/, time_t> _goRespawnTimes; }; enum InstanceResetMethod diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 5543251e115..2c1bdb00834 100755 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -211,6 +211,8 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); ASSERT(map->IsDungeon()); + map->LoadRespawnTimes(); + bool load_data = save != NULL; map->CreateInstanceData(load_data); diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index ce93fe5af1a..8736c8b3782 100755 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -110,6 +110,7 @@ Map* MapManager::CreateBaseMap(uint32 id) else { map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); + map->LoadRespawnTimes(); } i_maps[id] = map; } diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index 1049325237a..aa07eef2204 100755 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -71,7 +71,7 @@ class MapManager void SetMapUpdateInterval(uint32 t) { - if (t > MIN_MAP_UPDATE_DELAY) + if (t < MIN_MAP_UPDATE_DELAY) t = MIN_MAP_UPDATE_DELAY; i_timer.SetInterval(t); @@ -143,7 +143,7 @@ class MapManager void RegisterInstanceId(uint32 instanceId); void FreeInstanceId(uint32 instanceId); - uint32 GetNextInstanceId() { return _nextInstanceId; }; + uint32 GetNextInstanceId() const { return _nextInstanceId; }; void SetNextInstanceId(uint32 nextInstanceId) { _nextInstanceId = nextInstanceId; }; MapUpdater * GetMapUpdater() { return &m_updater; } diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 7b77ecaa17e..7d12f94d155 100755 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3279,8 +3279,6 @@ enum SummonType enum EventId { - EVENT_SPELLCLICK = 1001, - EVENT_FALL_GROUND = 1002, EVENT_CHARGE = 1003, }; diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index c0e1eb842ae..bc0570bb73b 100755 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -298,7 +298,7 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z) } } -void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed) +void MotionMaster::MoveLand(uint32 id, Position const& pos) { float x, y, z; pos.GetPosition(x, y, z); @@ -307,13 +307,12 @@ void MotionMaster::MoveLand(uint32 id, Position const& pos, float speed) Movement::MoveSplineInit init(*_owner); init.MoveTo(x,y,z); - init.SetVelocity(speed); init.SetAnimation(Movement::ToGround); init.Launch(); Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); } -void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed) +void MotionMaster::MoveTakeoff(uint32 id, Position const& pos) { float x, y, z; pos.GetPosition(x, y, z); @@ -322,7 +321,6 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed) Movement::MoveSplineInit init(*_owner); init.MoveTo(x,y,z); - init.SetVelocity(speed); init.SetAnimation(Movement::ToFly); init.Launch(); Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index d6144bfcc3a..727f626cdea 100755 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -157,8 +157,8 @@ class MotionMaster //: private std::stack<MovementGenerator *> void MovePoint(uint32 id, float x, float y, float z); // These two movement types should only be used with creatures having landing/takeoff animations - void MoveLand(uint32 id, Position const& pos, float speed); - void MoveTakeoff(uint32 id, Position const& pos, float speed); + void MoveLand(uint32 id, Position const& pos); + void MoveTakeoff(uint32 id, Position const& pos); void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE); void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index a922c937b5f..07a5761517e 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -33,6 +33,7 @@ void PointMovementGenerator<T>::Initialize(T &unit) unit.StopMoving(); unit.AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); + i_recalculateSpeed = false; Movement::MoveSplineInit init(unit); init.MoveTo(i_x, i_y, i_z); if (speed > 0.0f) @@ -53,6 +54,17 @@ bool PointMovementGenerator<T>::Update(T &unit, const uint32 & /*diff*/) } unit.AddUnitState(UNIT_STATE_ROAMING_MOVE); + + if (i_recalculateSpeed && !unit.movespline->Finalized()) + { + i_recalculateSpeed = false; + Movement::MoveSplineInit init(unit); + init.MoveTo(i_x, i_y, i_z); + if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit + init.SetVelocity(speed); + init.Launch(); + } + return !unit.movespline->Finalized(); } @@ -81,11 +93,6 @@ void PointMovementGenerator<T>::MovementInform(T & /*unit*/) template <> void PointMovementGenerator<Creature>::MovementInform(Creature &unit) { - //if (id == EVENT_FALL_GROUND) - //{ - // unit.setDeathState(JUST_DIED); - // unit.SetFlying(true); - //} if (unit.AI()) unit.AI()->MovementInform(POINT_MOTION_TYPE, id); } diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h index 13be9fee77b..d2833a5ee10 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.h @@ -36,6 +36,8 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG void MovementInform(T &); + void unitSpeedChanged() { i_recalculateSpeed = true; } + MovementGeneratorType GetMovementGeneratorType() { return POINT_MOTION_TYPE; } bool GetDestination(float& x, float& y, float& z) const { x=i_x; y=i_y; z=i_z; return true; } @@ -43,6 +45,7 @@ class PointMovementGenerator : public MovementGeneratorMedium< T, PointMovementG uint32 id; float i_x, i_y, i_z; float speed; + bool i_recalculateSpeed; }; class AssistanceMovementGenerator : public PointMovementGenerator<Creature> diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index 91b4ff08250..b1c25aedfd7 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -203,7 +203,7 @@ bool MoveSplineInitArgs::Validate() const return false;\ } CHECK(path.size() > 1); - CHECK(velocity > 0.f); + CHECK(velocity > 0.1f); CHECK(time_perc >= 0.f && time_perc <= 1.f); //CHECK(_checkPathBounds()); return true; diff --git a/src/server/game/Movement/Spline/MoveSplineFlag.h b/src/server/game/Movement/Spline/MoveSplineFlag.h index 33973064e09..cfc2fdee450 100644 --- a/src/server/game/Movement/Spline/MoveSplineFlag.h +++ b/src/server/game/Movement/Spline/MoveSplineFlag.h @@ -34,43 +34,43 @@ namespace Movement { public: enum eFlags{ - None = 0x00000000, - // x00-xFF(first byte) used as animation Ids storage in pair with Animation flag - Done = 0x00000100, - Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag - No_Spline = 0x00000400, - Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag - Walkmode = 0x00001000, - Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation - OrientationFixed = 0x00004000, // Model orientation fixed - Final_Point = 0x00008000, - Final_Target = 0x00010000, - Final_Angle = 0x00020000, - Catmullrom = 0x00040000, // Used Catmullrom interpolation mode - Cyclic = 0x00080000, // Movement by cycled spline - Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done - Animation = 0x00200000, // Plays animation after some time passed - Frozen = 0x00400000, // Will never arrive - Unknown5 = 0x00800000, - Unknown6 = 0x01000000, - Unknown7 = 0x02000000, - Unknown8 = 0x04000000, + None = 0x00000000, + // x00-xFF(first byte) used as animation Ids storage in pair with Animation flag + Done = 0x00000100, + Falling = 0x00000200, // Affects elevation computation, can't be combined with Parabolic flag + No_Spline = 0x00000400, + Parabolic = 0x00000800, // Affects elevation computation, can't be combined with Falling flag + Walkmode = 0x00001000, + Flying = 0x00002000, // Smooth movement(Catmullrom interpolation mode), flying animation + OrientationFixed = 0x00004000, // Model orientation fixed + Final_Point = 0x00008000, + Final_Target = 0x00010000, + Final_Angle = 0x00020000, + Catmullrom = 0x00040000, // Used Catmullrom interpolation mode + Cyclic = 0x00080000, // Movement by cycled spline + Enter_Cycle = 0x00100000, // Everytimes appears with cyclic flag in monster move packet, erases first spline vertex after first cycle done + Animation = 0x00200000, // Plays animation after some time passed + Frozen = 0x00400000, // Will never arrive + TransportEnter = 0x00800000, + TransportExit = 0x01000000, + Unknown7 = 0x02000000, + Unknown8 = 0x04000000, OrientationInversed = 0x08000000, - Unknown10 = 0x10000000, - Unknown11 = 0x20000000, - Unknown12 = 0x40000000, - Unknown13 = 0x80000000, + Unknown10 = 0x10000000, + Unknown11 = 0x20000000, + Unknown12 = 0x40000000, + Unknown13 = 0x80000000, // Masks - Mask_Final_Facing = Final_Point | Final_Target | Final_Angle, + Mask_Final_Facing = Final_Point | Final_Target | Final_Angle, // animation ids stored here, see AnimType enum, used with Animation flag - Mask_Animations = 0xFF, + Mask_Animations = 0xFF, // flags that shouldn't be appended into SMSG_MONSTER_MOVE\SMSG_MONSTER_MOVE_TRANSPORT packet, should be more probably Mask_No_Monster_Move = Mask_Final_Facing | Mask_Animations | Done, // CatmullRom interpolation mode used - Mask_CatmullRom = Flying | Catmullrom, + Mask_CatmullRom = Flying | Catmullrom, // Unused, not suported flags - Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown5|Unknown6|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13, + Mask_Unused = No_Spline|Enter_Cycle|Frozen|Unknown7|Unknown8|Unknown10|Unknown11|Unknown12|Unknown13, }; inline uint32& raw() { return (uint32&)*this;} @@ -98,14 +98,16 @@ namespace Movement void operator &= (uint32 f) { raw() &= f;} void operator |= (uint32 f) { raw() |= f;} - void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations|Falling|Parabolic)) | Animation|anim;} - void EnableParabolic() { raw() = (raw() & ~(Mask_Animations|Falling|Animation)) | Parabolic;} - void EnableFalling() { raw() = (raw() & ~(Mask_Animations|Parabolic|Animation)) | Falling;} + void EnableAnimation(uint8 anim) { raw() = (raw() & ~(Mask_Animations | Falling | Parabolic)) | Animation | anim; } + void EnableParabolic() { raw() = (raw() & ~(Mask_Animations | Falling | Animation)) | Parabolic; } + void EnableFalling() { raw() = (raw() & ~(Mask_Animations | Parabolic | Animation)) | Falling; } void EnableFlying() { raw() = (raw() & ~Catmullrom) | Flying; } void EnableCatmullRom() { raw() = (raw() & ~Flying) | Catmullrom; } - void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point;} - void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle;} - void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target;} + void EnableFacingPoint() { raw() = (raw() & ~Mask_Final_Facing) | Final_Point; } + void EnableFacingAngle() { raw() = (raw() & ~Mask_Final_Facing) | Final_Angle; } + void EnableFacingTarget() { raw() = (raw() & ~Mask_Final_Facing) | Final_Target; } + void EnableTransportEnter() { raw() = (raw() & ~TransportExit) | TransportEnter; } + void EnableTransportExit() { raw() = (raw() & ~TransportEnter) | TransportExit; } uint8 animId : 8; bool done : 1; @@ -123,8 +125,8 @@ namespace Movement bool enter_cycle : 1; bool animation : 1; bool frozen : 1; - bool unknown5 : 1; - bool unknown6 : 1; + bool transportEnter: 1; + bool transportExit : 1; bool unknown7 : 1; bool unknown8 : 1; bool orientationInversed : 1; diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index e586cb4f4f9..c539dd3cc39 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -20,6 +20,8 @@ #include "MoveSpline.h" #include "MovementPacketBuilder.h" #include "Unit.h" +#include "Transport.h" +#include "Vehicle.h" namespace Movement { @@ -58,17 +60,26 @@ namespace Movement { MoveSpline& move_spline = *unit.movespline; - Location real_position(unit.GetPositionX(),unit.GetPositionY(),unit.GetPositionZMinusOffset(),unit.GetOrientation()); - // there is a big chane that current position is unknown if current state is not finalized, need compute it + bool transport = false; + Location real_position(unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZMinusOffset(), unit.GetOrientation()); + // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes + if (unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit.GetTransGUID()) + { + transport = true; + real_position.x = unit.GetTransOffsetX(); + real_position.y = unit.GetTransOffsetY(); + real_position.z = unit.GetTransOffsetZ(); + real_position.orientation = unit.GetTransOffsetO(); + } + + // there is a big chance that current position is unknown if current state is not finalized, need compute it // this also allows calculate spline position and update map position in much greater intervals if (!move_spline.Finalized()) real_position = move_spline.ComputePosition(); + // should i do the things that user should do? - no. if (args.path.empty()) - { - // should i do the things that user should do? - MoveTo(real_position); - } + return; // corrent first vertex args.path[0] = real_position; @@ -82,7 +93,7 @@ namespace Movement moveFlags |= (MOVEMENTFLAG_SPLINE_ENABLED|MOVEMENTFLAG_FORWARD); - if (args.velocity == 0.f) + if (!args.HasVelocity) args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags)); if (!args.Validate()) @@ -94,14 +105,22 @@ namespace Movement unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags); move_spline.Initialize(args); - WorldPacket data(SMSG_MONSTER_MOVE, 64); + WorldPacket data(!transport ? SMSG_MONSTER_MOVE : SMSG_MONSTER_MOVE_TRANSPORT, 64); data.append(unit.GetPackGUID()); + if (transport) + { + data.appendPackGUID(unit.GetTransGUID()); + data << int8(unit.GetTransSeat()); + } + PacketBuilder::WriteMonsterMove(move_spline, data); unit.SendMessageToSet(&data,true); } MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) { + // Elevators also use MOVEMENTFLAG_ONTRANSPORT but we do not keep track of their position changes + args.TransformForTransport = unit.HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && unit.GetTransGUID(); // mix existing state into new args.flags.walkmode = unit.m_movementInfo.HasMovementFlag(MOVEMENTFLAG_WALKING); args.flags.flying = unit.m_movementInfo.HasMovementFlag((MovementFlags)(MOVEMENTFLAG_CAN_FLY|MOVEMENTFLAG_DISABLE_GRAVITY)); @@ -110,13 +129,48 @@ namespace Movement void MoveSplineInit::SetFacing(const Unit * target) { args.flags.EnableFacingTarget(); - //args.facing.target = target->GetObjectGuid().GetRawValue(); - args.facing.target = target->GetUInt64Value(OBJECT_FIELD_GUID); + args.facing.target = target->GetGUID(); } void MoveSplineInit::SetFacing(float angle) { + if (args.TransformForTransport) + { + if (Unit* vehicle = unit.GetVehicleBase()) + angle -= vehicle->GetOrientation(); + else if (Transport* transport = unit.GetTransport()) + angle -= transport->GetOrientation(); + } + args.facing.angle = G3D::wrap(angle, 0.f, (float)G3D::twoPi()); args.flags.EnableFacingAngle(); } + + void MoveSplineInit::MoveTo(Vector3 const& dest) + { + args.path_Idx_offset = 0; + args.path.resize(2); + TransportPathTransform transform(unit, args.TransformForTransport); + args.path[1] = transform(dest); + } + + Vector3 TransportPathTransform::operator()(Vector3 input) + { + if (_transformForTransport) + { + if (Unit* vehicle = _owner.GetVehicleBase()) + { + input.x -= vehicle->GetPositionX(); + input.y -= vehicle->GetPositionY(); + input.z -= vehicle->GetPositionZMinusOffset(); + } + else if (Transport* transport = _owner.GetTransport()) + { + float unused = 0.0f; + transport->CalculatePassengerOffset(input.x, input.y, input.z, unused); + } + } + + return input; + } } diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h index 7ef6cd7a120..ef847809ac8 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.h +++ b/src/server/game/Movement/Spline/MoveSplineInit.h @@ -33,6 +33,19 @@ namespace Movement FlyToGround = 3, // 463 = FlyToGround }; + // Transforms coordinates from global to transport offsets + class TransportPathTransform + { + public: + TransportPathTransform(Unit& owner, bool transformForTransport) + : _owner(owner), _transformForTransport(transformForTransport) { } + Vector3 operator()(Vector3 input); + + private: + Unit& _owner; + bool _transformForTransport; + }; + /* Initializes and launches spline movement */ class MoveSplineInit @@ -96,6 +109,12 @@ namespace Movement /* Enables falling mode. Disabled by default */ void SetFall(); + /* Enters transport. Disabled by default + */ + void SetTransportEnter(); + /* Exits transport. Disabled by default + */ + void SetTransportExit(); /* Inverses unit model orientation. Disabled by default */ void SetOrientationInversed(); @@ -112,40 +131,39 @@ namespace Movement PointsArray& Path() { return args.path; } + /* Disables transport coordinate transformations for cases where raw offsets are available + */ + void DisableTransportPathTransformations(); protected: MoveSplineInitArgs args; Unit& unit; }; - inline void MoveSplineInit::SetFly() { args.flags.EnableFlying();} + inline void MoveSplineInit::SetFly() { args.flags.EnableFlying(); } inline void MoveSplineInit::SetWalk(bool enable) { args.flags.walkmode = enable;} inline void MoveSplineInit::SetSmooth() { args.flags.EnableCatmullRom();} inline void MoveSplineInit::SetCyclic() { args.flags.cyclic = true;} inline void MoveSplineInit::SetFall() { args.flags.EnableFalling();} - inline void MoveSplineInit::SetVelocity(float vel){ args.velocity = vel;} + inline void MoveSplineInit::SetVelocity(float vel) { args.velocity = vel; args.HasVelocity = true; } inline void MoveSplineInit::SetOrientationInversed() { args.flags.orientationInversed = true;} + inline void MoveSplineInit::SetTransportEnter() { args.flags.EnableTransportEnter(); } + inline void MoveSplineInit::SetTransportExit() { args.flags.EnableTransportExit(); } inline void MoveSplineInit::SetOrientationFixed(bool enable) { args.flags.orientationFixed = enable;} inline void MoveSplineInit::MovebyPath(const PointsArray& controls, int32 path_offset) { args.path_Idx_offset = path_offset; - args.path.assign(controls.begin(),controls.end()); + args.path.resize(controls.size()); + std::transform(controls.begin(), controls.end(), args.path.begin(), TransportPathTransform(unit, args.TransformForTransport)); } inline void MoveSplineInit::MoveTo(float x, float y, float z) { - Vector3 v(x,y,z); + Vector3 v(x, y, z); MoveTo(v); } - inline void MoveSplineInit::MoveTo(const Vector3& dest) - { - args.path_Idx_offset = 0; - args.path.resize(2); - args.path[1] = dest; - } - inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift) { args.time_perc = time_shift; @@ -161,10 +179,14 @@ namespace Movement inline void MoveSplineInit::SetFacing(Vector3 const& spot) { - args.facing.f.x = spot.x; - args.facing.f.y = spot.y; - args.facing.f.z = spot.z; + TransportPathTransform transform(unit, args.TransformForTransport); + Vector3 finalSpot = transform(spot); + args.facing.f.x = finalSpot.x; + args.facing.f.y = finalSpot.y; + args.facing.f.z = finalSpot.z; args.flags.EnableFacingPoint(); } + + inline void MoveSplineInit::DisableTransportPathTransformations() { args.TransformForTransport = false; } } #endif // TRINITYSERVER_MOVESPLINEINIT_H diff --git a/src/server/game/Movement/Spline/MoveSplineInitArgs.h b/src/server/game/Movement/Spline/MoveSplineInitArgs.h index 26fbbdd0fcc..de02b35d0a0 100644 --- a/src/server/game/Movement/Spline/MoveSplineInitArgs.h +++ b/src/server/game/Movement/Spline/MoveSplineInitArgs.h @@ -42,7 +42,8 @@ namespace Movement struct MoveSplineInitArgs { MoveSplineInitArgs(size_t path_capacity = 16) : path_Idx_offset(0), - velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f) + velocity(0.f), parabolic_amplitude(0.f), time_perc(0.f), splineId(0), initialOrientation(0.f), + HasVelocity(false), TransformForTransport(true) { path.reserve(path_capacity); } @@ -56,6 +57,8 @@ namespace Movement float time_perc; uint32 splineId; float initialOrientation; + bool HasVelocity; + bool TransformForTransport; /** Returns true to show that the arguments were configured correctly and MoveSpline initialization will succeed. */ bool Validate() const; diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp index 0260767dbe2..8aef671d2d1 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp @@ -44,24 +44,12 @@ namespace Movement void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data) { MoveSplineFlag splineflags = move_spline.splineflags; - /*if (unit->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - { - data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); - if (unit->GetVehicle()) - data << unit->GetVehicle()->GetBase()->GetPackGUID(); - else if (unit->GetTransport()) - data << unit->GetTransport()->GetPackGUID(); - else - data << uint64(0); - - data << int8(unit->GetTransSeat()); - }*/ - data << uint8(0); + data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) data << move_spline.spline.getPoint(move_spline.spline.first()); data << move_spline.GetId(); - switch(splineflags & MoveSplineFlag::Mask_Final_Facing) + switch (splineflags & MoveSplineFlag::Mask_Final_Facing) { case MoveSplineFlag::Final_Target: data << uint8(MonsterMoveFacingTarget); diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp index 465fca75030..dfdd4fc4ffc 100755 --- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp @@ -166,8 +166,10 @@ bool OPvPCapturePoint::DelCreature(uint32 type) //if (Map* map = sMapMgr->FindMap(cr->GetMapId())) // map->Remove(cr, false); // delete respawn time for this creature - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN_BY_GUID); + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN); stmt->setUInt32(0, guid); + stmt->setUInt16(1, cr->GetMapId()); + stmt->setUInt32(2, 0); // instance id, always 0 for world maps CharacterDatabase.Execute(stmt); cr->AddObjectToRemoveList(); diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 26f4ad71cda..ff351f90f74 100755 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -132,16 +132,16 @@ Quest::Quest(Field* questRecord) ObjectiveText[i] = questRecord[128+i].GetString(); for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - RewardCurrencyId[i] = questRecord[132+i].GetUInt32(); + RewardCurrencyId[i] = questRecord[132+i].GetUInt16(); for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - RewardCurrencyCount[i] = questRecord[136+i].GetUInt32(); + RewardCurrencyCount[i] = questRecord[136+i].GetUInt8(); for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) - RequiredCurrencyId[i] = questRecord[140+i].GetUInt32(); + RequiredCurrencyId[i] = questRecord[140+i].GetUInt16(); for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) - RequiredCurrencyCount[i] = questRecord[144+i].GetUInt32(); + RequiredCurrencyCount[i] = questRecord[144+i].GetUInt8(); QuestGiverTextWindow = questRecord[148].GetString(); QuestGiverTargetName = questRecord[149].GetString(); diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index f64d0953e86..58b9c55cdd1 100755 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -46,21 +46,27 @@ void AddSC_SmartSCripts(); //Commands void AddSC_account_commandscript(); void AddSC_achievement_commandscript(); +void AddSC_cast_commandscript(); void AddSC_debug_commandscript(); void AddSC_event_commandscript(); void AddSC_gm_commandscript(); void AddSC_go_commandscript(); void AddSC_gobject_commandscript(); void AddSC_honor_commandscript(); +void AddSC_instance_commandscript(); void AddSC_learn_commandscript(); +void AddSC_list_commandscript(); void AddSC_misc_commandscript(); void AddSC_modify_commandscript(); void AddSC_npc_commandscript(); void AddSC_quest_commandscript(); void AddSC_reload_commandscript(); +void AddSC_reset_commandscript(); void AddSC_tele_commandscript(); +void AddSC_server_commandscript(); void AddSC_titles_commandscript(); void AddSC_wp_commandscript(); +void AddSC_character_commandscript(); #ifdef SCRIPTS //world @@ -648,21 +654,27 @@ void AddCommandScripts() { AddSC_account_commandscript(); AddSC_achievement_commandscript(); + AddSC_cast_commandscript(); AddSC_debug_commandscript(); AddSC_event_commandscript(); AddSC_gm_commandscript(); AddSC_go_commandscript(); AddSC_gobject_commandscript(); AddSC_honor_commandscript(); + AddSC_instance_commandscript(); AddSC_learn_commandscript(); + AddSC_list_commandscript(); AddSC_misc_commandscript(); AddSC_modify_commandscript(); AddSC_npc_commandscript(); AddSC_quest_commandscript(); AddSC_reload_commandscript(); + AddSC_reset_commandscript(); AddSC_tele_commandscript(); + AddSC_server_commandscript(); AddSC_titles_commandscript(); AddSC_wp_commandscript(); + AddSC_character_commandscript(); } void AddWorldScripts() diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index bf701d41ec2..195dd9391bd 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1041,7 +1041,6 @@ void InitOpcodes() //DEFINE_OPCODE_HANDLER(SMSG_LEARNED_DANCE_MOVES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_LEARNED_SPELL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_LEVELUP_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_LFG_BOOT_PLAYER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_LFG_BOOT_PROPOSAL_UPDATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_LFG_DISABLED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_LFG_JOIN_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1102,9 +1101,9 @@ void InitOpcodes() //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_COLLISION_HEIGHT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_HOVERING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1112,30 +1111,12 @@ void InitOpcodes() //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SKIP_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_RUN_MODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_WALK_MODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_SET_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_UNSET_FLYING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SPLINE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SKIP_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_KNOCK_BACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_MULTIPLE_PACKETS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_NAME_QUERY_RESPONSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1297,16 +1278,32 @@ void InitOpcodes() //DEFINE_OPCODE_HANDLER(SMSG_SPELL_START, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPELL_UPDATE_CHAIN_TARGETS, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPIRIT_HEALER_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_DISABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_COLLISION_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_DISABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_FLYING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_RUN_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WALK_MODE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_START_SWIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_STOP_SWIM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_FLYING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_UNSET_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 14f9687cdcd..4f6cda222e9 100755 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -792,7 +792,7 @@ enum Opcodes SMSG_LEARNED_DANCE_MOVES = 0x0E05, SMSG_LEARNED_SPELL = 0x58A2, SMSG_LEVELUP_INFO = 0x0000, - SMSG_LFG_BOOT_PLAYER = 0x0000, + SMSG_LFG_BOOT_PROPOSAL_UPDATE = 0x0000, SMSG_LFG_DISABLED = 0x0000, SMSG_LFG_JOIN_RESULT = 0x0000, SMSG_LFG_OFFER_CONTINUE = 0x0000, @@ -844,22 +844,21 @@ enum Opcodes SMSG_MOUNTSPECIAL_ANIM = 0x0000, SMSG_MOVE_DISABLE_COLLISION = 0x0000, SMSG_MOVE_DISABLE_GRAVITY = 0x0000, - SMSG_MOVE_DISABLE_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x0000, SMSG_MOVE_ENABLE_COLLISION = 0x0000, SMSG_MOVE_ENABLE_GRAVITY = 0x0000, - SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x0000, + SMSG_MOVE_FEATHER_FALL = 0x0000, SMSG_MOVE_KNOCK_BACK = 0x0000, + SMSG_MOVE_LAND_WALK = 0x0000, + SMSG_MOVE_NORMAL_FALL = 0x0000, SMSG_MOVE_ROOT = 0x0000, SMSG_MOVE_SET_ACTIVE_MOVER = 0x0000, SMSG_MOVE_SET_CAN_FLY = 0x0000, + SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x0000, SMSG_MOVE_SET_COLLISION_HEIGHT = 0x0000, SMSG_MOVE_SET_COMPOUND_STATE = 0x0000, - SMSG_MOVE_SET_FEATHER_FALL = 0x0000, SMSG_MOVE_SET_FLIGHT_BACK_SPEED = 0x0000, SMSG_MOVE_SET_FLIGHT_SPEED = 0x0000, - SMSG_MOVE_SET_HOVERING = 0x0000, - SMSG_MOVE_SET_LAND_WALK = 0x0000, - SMSG_MOVE_SET_NORMAL_FALL = 0x0000, + SMSG_MOVE_SET_HOVER = 0x0000, SMSG_MOVE_SET_PITCH_RATE = 0x0000, SMSG_MOVE_SET_RUN_BACK_SPEED = 0x0000, SMSG_MOVE_SET_RUN_SPEED = 0x0000, @@ -869,42 +868,16 @@ enum Opcodes SMSG_MOVE_SET_VEHICLE_REC_ID = 0x0000, SMSG_MOVE_SET_WALK_IN_AIR = 0x0000, SMSG_MOVE_SET_WALK_SPEED = 0x0000, - SMSG_MOVE_SET_WATER_WALK = 0x0000, SMSG_MOVE_SKIP_TIME = 0x0000, - SMSG_MOVE_SPLINE_DISABLE_COLLISION = 0x0000, - SMSG_MOVE_SPLINE_DISABLE_GRAVITY = 0x0000, - SMSG_MOVE_SPLINE_ENABLE_COLLISION = 0x0000, - SMSG_MOVE_SPLINE_ENABLE_GRAVITY = 0x0000, - SMSG_MOVE_SPLINE_ROOT = 0x0000, - SMSG_MOVE_SPLINE_SET_FEATHER_FALL = 0x0000, - SMSG_MOVE_SPLINE_SET_FLIGHT_BACK_SPEED = 0x0000, - SMSG_MOVE_SPLINE_SET_FLIGHT_SPEED = 0x0000, - SMSG_MOVE_SPLINE_SET_FLYING = 0x0000, - SMSG_MOVE_SPLINE_SET_HOVER = 0x0000, - SMSG_MOVE_SPLINE_SET_LAND_WALK = 0x0000, - SMSG_MOVE_SPLINE_SET_NORMAL_FALL = 0x0000, - SMSG_MOVE_SPLINE_SET_PITCH_RATE = 0x0000, - SMSG_MOVE_SPLINE_SET_RUN_BACK_SPEED = 0x0000, - SMSG_MOVE_SPLINE_SET_RUN_MODE = 0x0000, - SMSG_MOVE_SPLINE_SET_RUN_SPEED = 0x0000, - SMSG_MOVE_SPLINE_SET_SWIM_BACK_SPEED = 0x0000, - SMSG_MOVE_SPLINE_SET_SWIM_SPEED = 0x0000, - SMSG_MOVE_SPLINE_SET_TURN_RATE = 0x0000, - SMSG_MOVE_SPLINE_SET_WALK_MODE = 0x0000, - SMSG_MOVE_SPLINE_SET_WALK_SPEED = 0x0000, - SMSG_MOVE_SPLINE_SET_WATER_WALK = 0x0000, - SMSG_MOVE_SPLINE_START_SWIM = 0x0000, - SMSG_MOVE_SPLINE_STOP_SWIM = 0x0000, - SMSG_MOVE_SPLINE_UNROOT = 0x0000, - SMSG_MOVE_SPLINE_UNSET_FLYING = 0x0000, - SMSG_MOVE_SPLINE_UNSET_HOVER = 0x0000, SMSG_MOVE_TELEPORT = 0x0000, SMSG_MOVE_UNROOT = 0x0000, SMSG_MOVE_UNSET_CAN_FLY = 0x0000, - SMSG_MOVE_UNSET_HOVERING = 0x0000, + SMSG_MOVE_UNSET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0x0000, + SMSG_MOVE_UNSET_HOVER = 0x0000, SMSG_MOVE_UNSET_WALK_IN_AIR = 0x0000, SMSG_MOVE_UPDATE_KNOCK_BACK = 0x0000, SMSG_MOVE_UPDATE_TELEPORT = 0x0000, + SMSG_MOVE_WATER_WALK = 0x0000, SMSG_MULTIPLE_PACKETS = 0x0000, SMSG_NAME_QUERY_RESPONSE = 0x6E04, SMSG_NEW_TAXI_PATH = 0x0000, @@ -1046,6 +1019,33 @@ enum Opcodes SMSG_SPELL_START = 0x6415, SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x0000, SMSG_SPIRIT_HEALER_CONFIRM = 0x0000, + SMSG_SPLINE_MOVE_COLLISION_DISABLE = 0x0000, + SMSG_SPLINE_MOVE_COLLISION_ENABLE = 0x0000, + SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0x0000, + SMSG_SPLINE_MOVE_GRAVITY_ENABLE = 0x0000, + SMSG_SPLINE_MOVE_ROOT = 0x0000, + SMSG_SPLINE_MOVE_SET_FEATHER_FALL = 0x0000, + SMSG_SPLINE_MOVE_SET_FLIGHT_BACK_SPEED = 0x0000, + SMSG_SPLINE_MOVE_SET_FLIGHT_SPEED = 0x0000, + SMSG_SPLINE_MOVE_SET_FLYING = 0x0000, + SMSG_SPLINE_MOVE_SET_HOVER = 0x0000, + SMSG_SPLINE_MOVE_SET_LAND_WALK = 0x0000, + SMSG_SPLINE_MOVE_SET_NORMAL_FALL = 0x0000, + SMSG_SPLINE_MOVE_SET_PITCH_RATE = 0x0000, + SMSG_SPLINE_MOVE_SET_RUN_BACK_SPEED = 0x0000, + SMSG_SPLINE_MOVE_SET_RUN_MODE = 0x0000, + SMSG_SPLINE_MOVE_SET_RUN_SPEED = 0x0000, + SMSG_SPLINE_MOVE_SET_SWIM_BACK_SPEED = 0x0000, + SMSG_SPLINE_MOVE_SET_SWIM_SPEED = 0x0000, + SMSG_SPLINE_MOVE_SET_TURN_RATE = 0x0000, + SMSG_SPLINE_MOVE_SET_WALK_MODE = 0x0000, + SMSG_SPLINE_MOVE_SET_WALK_SPEED = 0x0000, + SMSG_SPLINE_MOVE_SET_WATER_WALK = 0x0000, + SMSG_SPLINE_MOVE_START_SWIM = 0x0000, + SMSG_SPLINE_MOVE_STOP_SWIM = 0x0000, + SMSG_SPLINE_MOVE_UNROOT = 0x0000, + SMSG_SPLINE_MOVE_UNSET_FLYING = 0x0000, + SMSG_SPLINE_MOVE_UNSET_HOVER = 0x0000, SMSG_STABLE_RESULT = 0x0000, SMSG_STANDSTATE_UPDATE = 0x6F04, SMSG_START_MIRROR_TIMER = 0x0000, @@ -1112,7 +1112,7 @@ enum SessionStatus STATUS_AUTHED = 0, // Player authenticated (_player == NULL, m_playerRecentlyLogout = false or will be reset before handler call, m_GUID have garbage) STATUS_LOGGEDIN, // Player in game (_player != NULL, m_GUID == _player->GetGUID(), inWorld()) STATUS_TRANSFER, // Player transferring to another map (_player != NULL, m_GUID == _player->GetGUID(), !inWorld()) - STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, // _player!= NULL or _player == NULL && m_playerRecentlyLogout, m_GUID store last _player guid) + STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, // _player != NULL or _player == NULL && m_playerRecentlyLogout && m_playerLogout, m_GUID store last _player guid) STATUS_NEVER, // Opcode not accepted from client (deprecated or server side only) STATUS_UNHANDLED, // Opcode not handled yet }; diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp new file mode 100644 index 00000000000..cb6dcdbdb9e --- /dev/null +++ b/src/server/game/Server/Protocol/PacketLog.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "PacketLog.h" +#include "Config.h" +#include "ByteBuffer.h" +#include "WorldPacket.h" + +PacketLog::PacketLog() : _file(NULL) +{ + Initialize(); +} + +PacketLog::~PacketLog() +{ + if (_file) + fclose(_file); + + _file = NULL; +} + +void PacketLog::Initialize() +{ + std::string logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); + + if (!logsDir.empty()) + if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) + logsDir.push_back('/'); + + std::string logname = ConfigMgr::GetStringDefault("PacketLogFile", ""); + if (!logname.empty()) + _file = fopen((logsDir + logname).c_str(), "wb"); +} + +void PacketLog::LogPacket(WorldPacket const& packet, Direction direction) +{ + ByteBuffer data(4+4+4+1+packet.size()); + data << int32(packet.GetOpcode()); + data << int32(packet.size()); + data << uint32(time(NULL)); + data << uint8(direction); + + for (uint32 i = 0; i < packet.size(); i++) + data << const_cast<WorldPacket&>(packet)[i]; + + fwrite(data.contents(), 1, data.size(), _file); + fflush(_file); +} diff --git a/src/server/game/Server/Protocol/WorldLog.h b/src/server/game/Server/Protocol/PacketLog.h index fb344f195de..b899daae198 100755..100644 --- a/src/server/game/Server/Protocol/WorldLog.h +++ b/src/server/game/Server/Protocol/PacketLog.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,46 +15,36 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/// \addtogroup u2w -/// @{ -/// \file - -#ifndef TRINITY_WORLDLOG_H -#define TRINITY_WORLDLOG_H +#ifndef TRINITY_PACKETLOG_H +#define TRINITY_PACKETLOG_H #include "Common.h" #include <ace/Singleton.h> -#include "Errors.h" -#include <stdarg.h> +enum Direction +{ + CLIENT_TO_SERVER, + SERVER_TO_CLIENT +}; + +class WorldPacket; -/// %Log packets to a file -class WorldLog +class PacketLog { - friend class ACE_Singleton<WorldLog, ACE_Thread_Mutex>; + friend class ACE_Singleton<PacketLog, ACE_Thread_Mutex>; private: - WorldLog(); - ~WorldLog(); - WorldLog(const WorldLog &); - WorldLog& operator=(const WorldLog &); - ACE_Thread_Mutex Lock; + PacketLog(); + ~PacketLog(); public: void Initialize(); - /// Is the world logger active? - bool LogWorld(void) const { return (i_file != NULL); } - /// %Log to the file - void outLog(char const* fmt, ...); - void outTimestampLog(char const* fmt, ...); + bool CanLogPacket() const { return (_file != NULL); } + void LogPacket(WorldPacket const& packet, Direction direction); private: - FILE* i_file; - - bool m_dbWorld; + FILE* _file; }; -#define sWorldLog ACE_Singleton<WorldLog, ACE_Thread_Mutex>::instance() +#define sPacketLog ACE_Singleton<PacketLog, ACE_Thread_Mutex>::instance() #endif -/// @} - diff --git a/src/server/game/Server/Protocol/WorldLog.cpp b/src/server/game/Server/Protocol/WorldLog.cpp deleted file mode 100755 index 38b13dff095..00000000000 --- a/src/server/game/Server/Protocol/WorldLog.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/** \file - \ingroup u2w -*/ - -#include "WorldLog.h" -#include "Config.h" -#include "Log.h" -#include "DatabaseWorkerPool.h" - -WorldLog::WorldLog() : i_file(NULL) -{ - Initialize(); -} - -WorldLog::~WorldLog() -{ - if (i_file != NULL) - fclose(i_file); - - i_file = NULL; -} - -/// Open the log file (if specified so in the configuration file) -void WorldLog::Initialize() -{ - std::string logsDir = ConfigMgr::GetStringDefault("LogsDir", ""); - - if (!logsDir.empty()) - { - if ((logsDir.at(logsDir.length()-1) != '/') && (logsDir.at(logsDir.length()-1) != '\\')) - logsDir.push_back('/'); - } - - std::string logname = ConfigMgr::GetStringDefault("WorldLogFile", ""); - if (!logname.empty()) - { - i_file = fopen((logsDir+logname).c_str(), "w"); - } - - m_dbWorld = ConfigMgr::GetBoolDefault("LogDB.World", false); // can be VERY heavy if enabled -} - -void WorldLog::outTimestampLog(char const* fmt, ...) -{ - if (LogWorld()) - { - TRINITY_GUARD(ACE_Thread_Mutex, Lock); - ASSERT(i_file); - - Log::outTimestamp(i_file); - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog->GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog->outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} - -void WorldLog::outLog(char const* fmt, ...) -{ - if (LogWorld()) - { - TRINITY_GUARD(ACE_Thread_Mutex, Lock); - ASSERT(i_file); - - va_list args; - va_start(args, fmt); - vfprintf(i_file, fmt, args); - //fprintf(i_file, "\n"); - va_end(args); - - fflush(i_file); - } - - if (sLog->GetLogDB() && m_dbWorld) - { - va_list ap2; - va_start(ap2, fmt); - char nnew_str[MAX_QUERY_LEN]; - vsnprintf(nnew_str, MAX_QUERY_LEN, fmt, ap2); - sLog->outDB(LOG_TYPE_WORLD, nnew_str); - va_end(ap2); - } -} diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 0f41ea1ca37..9b6eaaea6c3 100755 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -218,7 +218,7 @@ void WorldSession::QueuePacket(WorldPacket* new_packet) /// Logging helper for unexpected opcodes void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char* status, const char *reason) { - sLog->outError("SESSION (account: %u, guidlow: %u, char: %s): received unexpected opcode %s (0x%.4X, status: %s) %s", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION (account: %u, guidlow: %u, char: %s): received unexpected opcode %s (0x%.4X, status: %s) %s", GetAccountId(), m_GUIDLow, _player ? _player->GetName() : "<none>", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode(), status, reason); } @@ -226,7 +226,7 @@ void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char* status, /// Logging helper for unexpected opcodes void WorldSession::LogUnprocessedTail(WorldPacket* packet) { - sLog->outError("SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", + sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: opcode %s (0x%.4X) have unprocessed tail data (read stop at %u from %u)", LookupOpcodeName(packet->GetOpcode()), packet->GetOpcode(), uint32(packet->rpos()), uint32(packet->wpos())); packet->print_storage(); } diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index c7c19eeeacd..c1d1cb5d53c 100755 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -333,7 +333,7 @@ class WorldSession void LoadTutorialsData(); void SendTutorialsData(); void SaveTutorialsData(SQLTransaction& trans); - uint32 GetTutorialInt(uint8 index) { return m_Tutorials[index]; } + uint32 GetTutorialInt(uint8 index) const { return m_Tutorials[index]; } void SetTutorialInt(uint8 index, uint32 value) { if (m_Tutorials[index] != value) @@ -400,8 +400,8 @@ class WorldSession } // Recruit-A-Friend Handling - uint32 GetRecruiterId() { return recruiterId; } - bool IsARecruiter() { return isRecruiter; } + uint32 GetRecruiterId() const { return recruiterId; } + bool IsARecruiter() const { return isRecruiter; } public: // opcodes handlers diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 5f55ddbc254..c2a02d6f12c 100755 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -42,7 +42,7 @@ #include "WorldSession.h" #include "WorldSocketMgr.h" #include "Log.h" -#include "WorldLog.h" +#include "PacketLog.h" #include "ScriptMgr.h" #include "AccountMgr.h" @@ -78,7 +78,7 @@ struct ServerPktHeader return 2+(isLargePacket()?3:2); } - bool isLargePacket() + bool isLargePacket() const { return size > 0x7FFF; } @@ -152,7 +152,7 @@ const std::string& WorldSocket::GetRemoteAddress (void) const return m_Address; } -int WorldSocket::SendPacket(const WorldPacket& pct) +int WorldSocket::SendPacket(WorldPacket const& pct) { ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, -1); @@ -160,24 +160,8 @@ int WorldSocket::SendPacket(const WorldPacket& pct) return -1; // Dump outgoing packet. - if (sWorldLog->LogWorld()) - { - sWorldLog->outTimestampLog ("SERVER:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - pct.size(), - LookupOpcodeName (pct.GetOpcode()), - pct.GetOpcode()); - - uint32 p = 0; - while (p < pct.size()) - { - for (uint32 j = 0; j < 16 && p < pct.size(); j++) - sWorldLog->outLog("%.2X ", const_cast<WorldPacket&>(pct)[p++]); - - sWorldLog->outLog("\n"); - } - sWorldLog->outLog("\n"); - } + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(pct, SERVER_TO_CLIENT); sLog->outOpCode(uint32(pct.GetOpcode()), LookupOpcodeName(pct.GetOpcode()), true); @@ -668,7 +652,7 @@ int WorldSocket::schedule_wakeup_output (GuardType& g) return 0; } -int WorldSocket::ProcessIncoming (WorldPacket* new_pct) +int WorldSocket::ProcessIncoming(WorldPacket* new_pct) { ACE_ASSERT (new_pct); @@ -681,24 +665,8 @@ int WorldSocket::ProcessIncoming (WorldPacket* new_pct) return -1; // Dump received packet. - if (sWorldLog->LogWorld()) - { - sWorldLog->outTimestampLog ("CLIENT:\nSOCKET: %u\nLENGTH: %u\nOPCODE: %s (0x%.4X)\nDATA:\n", - (uint32) get_handle(), - new_pct->size(), - LookupOpcodeName (new_pct->GetOpcode()), - new_pct->GetOpcode()); - - uint32 p = 0; - while (p < new_pct->size()) - { - for (uint32 j = 0; j < 16 && p < new_pct->size(); j++) - sWorldLog->outLog ("%.2X ", (*new_pct)[p++]); - - sWorldLog->outLog ("\n"); - } - sWorldLog->outLog ("\n"); - } + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(*new_pct, CLIENT_TO_SERVER); sLog->outOpCode(uint32(Opcodes(opcode)), LookupOpcodeName(Opcodes(opcode)), false); @@ -808,7 +776,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) LocaleConstant locale; std::string account; SHA1Hash sha; - BigNumber v, s, g, N, k; + BigNumber k; WorldPacket addonsData; recvPacket.read_skip<uint32>(); @@ -891,21 +859,9 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) if (expansion > world_expansion) expansion = world_expansion; - N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); - g.SetDword(7); - - v.SetHexStr(fields[4].GetCString()); - s.SetHexStr(fields[5].GetCString()); - - const char* sStr = s.AsHexStr(); //Must be freed by OPENSSL_free() - const char* vStr = v.AsHexStr(); //Must be freed by OPENSSL_free() - sLog->outStaticDebug("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s", - sStr, - vStr); - - OPENSSL_free((void*) sStr); - OPENSSL_free((void*) vStr); + fields[5].GetCString(), + fields[4].GetCString()); ///- Re-check ip locking (same check as in realmd). if (fields[3].GetUInt8() == 1) // if ip is locked diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 7cff80cf6a0..7817e5e0d4d 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -831,33 +831,18 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load) m_amplitude = 1 * IN_MILLISECONDS; case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_PERIODIC_ENERGIZE: case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + case SPELL_AURA_PERIODIC_ENERGIZE: case SPELL_AURA_PERIODIC_LEECH: case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: case SPELL_AURA_PERIODIC_MANA_LEECH: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: case SPELL_AURA_POWER_BURN: - m_isPeriodic = true; - break; - case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - if (GetId() == 51912) - m_amplitude = 3000; - m_isPeriodic = true; - break; - case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: case SPELL_AURA_PERIODIC_DUMMY: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: m_isPeriodic = true; break; - case SPELL_AURA_DUMMY: - // Haunting Spirits - perdiodic trigger demon - if (GetId() == 7057) - { - m_isPeriodic = true; - m_amplitude = irand (0, 60) + 30; - m_amplitude *= IN_MILLISECONDS; - } - break; default: break; } @@ -1153,14 +1138,6 @@ void AuraEffect::UpdatePeriodic(Unit* caster) { switch (GetAuraType()) { - case SPELL_AURA_DUMMY: - // Haunting Spirits - if (GetId() == 7057) - { - m_amplitude = irand (0, 60) + 30; - m_amplitude *= IN_MILLISECONDS; - } - break; case SPELL_AURA_PERIODIC_DUMMY: switch (GetSpellInfo()->SpellFamilyName) { @@ -1362,11 +1339,6 @@ void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster) const case SPELL_AURA_POWER_BURN: HandlePeriodicPowerBurnAuraTick(target, caster); break; - case SPELL_AURA_DUMMY: - // Haunting Spirits - if (GetId() == 7057) - target->CastSpell((Unit*)NULL, GetAmount(), true); - break; default: break; } @@ -3352,9 +3324,11 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp, { target->SetCanFly(apply); if (!apply) + { target->RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING); target->AddUnitMovementFlag(MOVEMENTFLAG_FALLING); target->m_movementInfo.SetFallTime(0); + } Player* player = target->ToPlayer(); if (!player) @@ -3431,41 +3405,244 @@ void AuraEffect::HandleModStateImmunityMask(AuraApplication const* aurApp, uint8 return; Unit* target = aurApp->GetTarget(); + std::list <AuraType> aura_immunity_list; + uint32 mechanic_immunity_list = 0; + int32 miscVal = GetMiscValue(); - std::list <AuraType> immunity_list; - if (GetMiscValue() & (1<<10)) - immunity_list.push_back(SPELL_AURA_MOD_STUN); - if (GetMiscValue() & (1<<1)) - immunity_list.push_back(SPELL_AURA_TRANSFORM); + switch (miscVal) + { + case 96: + case 1615: + { + if (GetAmount()) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 679: + { + if (GetId() == 57742) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 1557: + { + if (GetId() == 64187) + { + mechanic_immunity_list = (1 << MECHANIC_STUN); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + } + else + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 1614: + case 1694: + { + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_TAUNT); + break; + } + case 1630: + { + if (!GetAmount()) + { + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_TAUNT); + } + else + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 477: + case 1733: + { + if (!GetAmount()) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) | (1 << MECHANIC_TURN); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SLEEP, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SAPPED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_HORROR, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_POLYMORPH, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_TURN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + } + break; + } + case 878: + { + if (GetAmount() == 1) + { + mechanic_immunity_list = (1 << MECHANIC_SNARE) | (1 << MECHANIC_STUN) + | (1 << MECHANIC_DISORIENTED) | (1 << MECHANIC_FREEZE); + + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply); + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FREEZE, apply); + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + } + break; + } + default: + break; + } - // These flag can be recognized wrong: - if (GetMiscValue() & (1<<6)) - immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); - if (GetMiscValue() & (1<<0)) - immunity_list.push_back(SPELL_AURA_MOD_ROOT); - if (GetMiscValue() & (1<<2)) - immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); - if (GetMiscValue() & (1<<9)) - immunity_list.push_back(SPELL_AURA_MOD_FEAR); + if (aura_immunity_list.empty()) + { + if (miscVal & (1<<10)) + aura_immunity_list.push_back(SPELL_AURA_MOD_STUN); + if (miscVal & (1<<1)) + aura_immunity_list.push_back(SPELL_AURA_TRANSFORM); - // an exception for Bladestorm - if ((GetMiscValue() & (1<<7)) && (GetId() != 46924)) - immunity_list.push_back(SPELL_AURA_MOD_DISARM); + // These flag can be recognized wrong: + if (miscVal & (1<<6)) + aura_immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + if (miscVal & (1<<0)) + aura_immunity_list.push_back(SPELL_AURA_MOD_ROOT); + if (miscVal & (1<<2)) + aura_immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + if (miscVal & (1<<9)) + aura_immunity_list.push_back(SPELL_AURA_MOD_FEAR); + if (miscVal & (1<<7)) + aura_immunity_list.push_back(SPELL_AURA_MOD_DISARM); + } // apply immunities - for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) + for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter) target->ApplySpellImmune(GetId(), IMMUNITY_STATE, *iter, apply); - // Patch 3.0.3 Bladestorm now breaks all snares and roots on the warrior when activated. - if (apply && GetId() == 46924) - { - target->RemoveAurasByType(SPELL_AURA_MOD_ROOT); - target->RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); - } - if (apply && GetSpellInfo()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) - for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) + { + target->RemoveAurasWithMechanic(mechanic_immunity_list, AURA_REMOVE_BY_DEFAULT, GetId()); + for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter) target->RemoveAurasByType(*iter); + } } void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4861,38 +5038,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool if (Unit* spellTarget = ObjectAccessor::GetUnit(*target, target->ToPlayer()->GetComboTarget())) target->CastSpell(spellTarget, 51699, true); break; - case 28832: // Mark of Korth'azz - case 28833: // Mark of Blaumeux - case 28834: // Mark of Rivendare - case 28835: // Mark of Zeliek - if (caster) // actually we can also use cast(this, originalcasterguid) - { - int32 damage; - switch (GetBase()->GetStackAmount()) - { - case 1: damage = 0; break; - case 2: damage = 500; break; - case 3: damage = 1000; break; - case 4: damage = 1500; break; - case 5: damage = 4000; break; - case 6: damage = 12000; break; - default:damage = 20000 + 1000 * (GetBase()->GetStackAmount() - 7); break; - } - if (damage) - caster->CastCustomSpell(28836, SPELLVALUE_BASE_POINT0, damage, target); - } - break; - case 63322: // Saronite Vapors - { - if (caster) - { - int32 mana = int32(GetAmount() * pow(2.0f, GetBase()->GetStackAmount())); // mana restore - bp * 2^stackamount - int32 damage = mana * 2; // damage - caster->CastCustomSpell(target, 63337, &mana, NULL, NULL, true); - caster->CastCustomSpell(target, 63338, &damage, NULL, NULL, true); - } - break; - } case 71563: if (Aura* newAura = target->AddAura(71564, target)) newAura->SetStackAmount(newAura->GetSpellInfo()->StackAmount); @@ -4986,57 +5131,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool break; } break; - case SPELLFAMILY_MAGE: - // Living Bomb - if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) - { - AuraRemoveMode removeMode = aurApp->GetRemoveMode(); - if (caster && (removeMode == AURA_REMOVE_BY_ENEMY_SPELL || removeMode == AURA_REMOVE_BY_EXPIRE)) - caster->CastSpell(target, GetAmount(), true); - } - break; - case SPELLFAMILY_PRIEST: - // Vampiric Touch - if (m_spellInfo->SpellFamilyFlags[1] & 0x0400 && aurApp->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && GetEffIndex() == 0) - if (AuraEffect const* aurEff = GetBase()->GetEffect(1)) - { - int32 damage = aurEff->GetAmount() * 8; - // backfire damage - target->CastCustomSpell(target, 64085, &damage, NULL, NULL, true, NULL, NULL, GetCasterGUID()); - } - break; - case SPELLFAMILY_WARLOCK: - // Haunt - if (m_spellInfo->SpellFamilyFlags[1] & 0x40000) - if (caster) - target->CastCustomSpell(caster, 48210, &m_amount, 0, 0, true, NULL, this, GetCasterGUID()); - break; - case SPELLFAMILY_DRUID: - // Lifebloom - if (GetSpellInfo()->SpellFamilyFlags[1] & 0x10) - { - // Final heal only on duration end - if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) - return; - - // final heal - int32 stack = GetBase()->GetStackAmount(); - int32 heal = m_amount; - if (caster) - { - heal = caster->SpellHealingBonusDone(target, GetSpellInfo(), heal, HEAL, stack); - heal = target->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, HEAL, stack); - } - target->CastCustomSpell(target, 33778, &heal, &stack, NULL, true, NULL, this, GetCasterGUID()); - - // restore mana - if (caster) - { - int32 returnmana = CalculatePctU(caster->GetCreateMana(), GetSpellInfo()->ManaCostPercentage) * stack / 2; - caster->CastCustomSpell(caster, 64372, &returnmana, NULL, NULL, true, NULL, this, GetCasterGUID()); - } - } - break; case SPELLFAMILY_DEATHKNIGHT: // Summon Gargoyle (Dismiss Gargoyle at remove) if (GetId() == 61777) @@ -5044,7 +5138,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool break; case SPELLFAMILY_ROGUE: // Tricks of the trade - switch(GetId()) + switch (GetId()) { case 59628: //Tricks of the trade buff on rogue (6sec duration) target->SetReducedThreatPercent(0,0); @@ -5112,48 +5206,6 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool target->SetEntry(apply ? 17654 : 17326); break; } - //Summon Fire Elemental - case 40133: - { - if (!caster) - break; - - Unit* owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) - { - if (apply) - owner->CastSpell(owner, 8985, true); - else - owner->ToPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - } - break; - } - //Summon Earth Elemental - case 40132 : - { - if (!caster) - break; - - Unit* owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) - { - if (apply) - owner->CastSpell(owner, 19704, true); - else - owner->ToPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - } - break; - } - case 57723: // Exhaustion - case 57724: // Sated - { - switch (GetId()) - { - case 57723: target->ApplySpellImmune(GetId(), IMMUNITY_ID, 32182, apply); break; // Heroism - case 57724: target->ApplySpellImmune(GetId(), IMMUNITY_ID, 2825, apply); break; // Bloodlust - } - break; - } case 57819: // Argent Champion case 57820: // Ebon Champion case 57821: // Champion of the Kirin Tor @@ -5246,69 +5298,14 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool } case SPELLFAMILY_DRUID: { - if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) - break; - switch (GetId()) - { - case 52610: // Savage Roar - { - uint32 spellId = 62071; - if (apply) - { - if (target->GetShapeshiftForm() != FORM_CAT) - break; - - target->CastSpell(target, spellId, true, NULL, NULL, GetCasterGUID()); - break; - } - target->RemoveAurasDueToSpell(spellId); - break; - } - case 61336: // Survival Instincts - { - if (!(mode & AURA_EFFECT_HANDLE_REAL)) - break; - - if (apply) - { - if (!target->IsInFeralForm()) - break; - - int32 bp0 = int32(target->CountPctFromMaxHealth(GetAmount())); - target->CastCustomSpell(target, 50322, &bp0, NULL, NULL, true); - } - else - target->RemoveAurasDueToSpell(50322); - break; - } - } - // Predatory Strikes - if (target->GetTypeId() == TYPEID_PLAYER && GetSpellInfo()->SpellIconID == 1563) - { - target->ToPlayer()->UpdateAttackPowerAndDamage(); - } + //if (!(mode & AURA_EFFECT_HANDLE_REAL)) + //break; break; } case SPELLFAMILY_SHAMAN: { - if (!(mode & AURA_EFFECT_HANDLE_REAL)) - break; - // Sentry Totem - if (GetId() == 6495 && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - if (apply) - { - if (uint64 guid = caster->m_SummonSlot[4]) - { - if (Creature* totem = caster->GetMap()->GetCreature(guid)) - if (totem->isTotem()) - caster->ToPlayer()->CastSpell(totem, 6277, true); - } - } - else - caster->ToPlayer()->StopCastingBindSight(); - return; - } + //if (!(mode & AURA_EFFECT_HANDLE_REAL)) + //break; break; } case SPELLFAMILY_PALADIN: @@ -5941,14 +5938,6 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) if (caster) caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, int32(target->CountPctFromMaxHealth(21)), target, true, NULL, this); return; - // Detonate Mana - case 27819: - if (int32 mana = (int32)(target->GetMaxPower(POWER_MANA) / 10)) - { - mana = target->ModifyPower(POWER_MANA, -mana); - target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana*10, target, true, NULL, this); - } - return; // Inoculate Nestlewood Owlkin case 29528: if (target->GetTypeId() != TYPEID_UNIT) // prevent error reports in case ignored player target @@ -6613,33 +6602,6 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con target->AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo()->GetSchoolMask(), GetSpellInfo()); } - // spell-specific code - switch (GetId()) - { - case 31447: // Mark of Kaz'rogal - if (target->GetPower(powerType) == 0) - { - target->CastSpell(target, 31463, true, 0, this); - // Remove aura - GetBase()->SetDuration(0); - } - break; - case 32960: // Mark of Kazzak - { - int32 modifier = int32(target->GetPower(powerType) * 0.05f); - target->ModifyPower(powerType, -modifier); - - if (target->GetPower(powerType) == 0) - { - target->CastSpell(target, 32961, true, 0, this); - // Remove aura - GetBase()->SetDuration(0); - } - break; - } - default: - break; - } // Drain Mana if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags[0] & 0x00000010) diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 58c8ce5c558..6a8ac5d4eef 100755 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1236,19 +1236,6 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b caster->CastCustomSpell(caster, 75999, &heal, NULL, NULL, true, NULL, GetEffect(0)); } } - // Renew - else if (GetSpellInfo()->SpellFamilyFlags[0] & 0x00000040 && GetEffect(0)) - { - // Empowered Renew - if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3021, 1)) - { - uint32 damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), GetEffect(0)->GetAmount(), HEAL); - damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, HEAL); - - int32 basepoints0 = aurEff->GetAmount() * GetEffect(0)->GetTotalTicks() * int32(damage) / 100; - caster->CastCustomSpell(target, 63544, &basepoints0, NULL, NULL, true, NULL, GetEffect(0)); - } - } // Power Word: Shield else if (m_spellInfo->SpellFamilyFlags[0] & 0x1 && m_spellInfo->SpellFamilyFlags[2] & 0x400 && GetEffect(0)) { diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index d833782bc76..54b3ae310e2 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -828,7 +828,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar break; } - switch(targetType.GetSelectionCategory()) + switch (targetType.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_CHANNEL: SelectImplicitChannelTargets(effIndex, targetType); @@ -846,7 +846,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetObjectType()) { case TARGET_OBJECT_TYPE_SRC: - switch(targetType.GetReferenceType()) + switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: m_targets.SetSrc(*m_caster); @@ -857,7 +857,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar } break; case TARGET_OBJECT_TYPE_DEST: - switch(targetType.GetReferenceType()) + switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: SelectImplicitCasterDestTargets(effIndex, targetType); @@ -874,7 +874,7 @@ void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTar } break; default: - switch(targetType.GetReferenceType()) + switch (targetType.GetReferenceType()) { case TARGET_REFERENCE_TYPE_CASTER: SelectImplicitCasterObjectTargets(effIndex, targetType); @@ -915,17 +915,25 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa switch (targetType.GetTarget()) { case TARGET_UNIT_CHANNEL_TARGET: + { + WorldObject* target = ObjectAccessor::GetUnit(*m_caster, channeledSpell->m_targets.GetUnitTargetGUID()); + CallScriptObjectTargetSelectHandlers(target, effIndex); // unit target may be no longer avalible - teleported out of map for example - if (Unit* target = Unit::GetUnit(*m_caster, channeledSpell->m_targets.GetUnitTargetGUID())) - AddUnitTarget(target, 1 << effIndex); + if (target && target->ToUnit()) + AddUnitTarget(target->ToUnit(), 1 << effIndex); else sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex); break; + } case TARGET_DEST_CHANNEL_TARGET: if (channeledSpell->m_targets.HasDst()) m_targets.SetDst(channeledSpell->m_targets); else if (WorldObject* target = ObjectAccessor::GetWorldObject(*m_caster, channeledSpell->m_targets.GetObjectTargetGUID())) - m_targets.SetDst(*target); + { + CallScriptObjectTargetSelectHandlers(target, effIndex); + if (target) + m_targets.SetDst(*target); + } else sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex); break; @@ -1003,6 +1011,8 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar return; } + CallScriptObjectTargetSelectHandlers(target, effIndex); + switch (targetType.GetObjectType()) { case TARGET_OBJECT_TYPE_UNIT: @@ -1042,7 +1052,9 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge { Trinity::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList); Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> searcher(m_caster, targets, check, containerTypeMask); - SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> > (searcher, containerTypeMask, m_caster, m_caster, radius); + SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellConeTargetCheck> >(searcher, containerTypeMask, m_caster, m_caster, radius); + + CallScriptObjectAreaTargetSelectHandlers(targets, effIndex); if (!targets.empty()) { @@ -1070,8 +1082,6 @@ void Spell::SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTarge gObjTargets.push_back(gObjTarget); } - CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex); - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) AddUnitTarget(*itr, effMask, false); @@ -1206,6 +1216,9 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge default: break; } + + CallScriptObjectAreaTargetSelectHandlers(targets, effIndex); + std::list<Unit*> unitTargets; std::list<GameObject*> gObjTargets; // for compability with older code - add only unit and go targets @@ -1287,18 +1300,6 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth power = POWER_HEALTH; } - else if (m_spellInfo->SpellFamilyFlags[2] == 0x0100) // Starfall - { - // Remove targets not in LoS or in stealth - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end();) - { - if ((*itr)->HasStealthAura() || (*itr)->HasInvisibilityAura() || !(*itr)->IsWithinLOSInMap(m_caster)) - itr = unitTargets.erase(itr); - else - ++itr; - } - break; - } else break; @@ -1339,6 +1340,11 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge } } + // todo: move to scripts, but we must call it before resize list by MaxAffectedTargets + // Intimidating Shout + if (m_spellInfo->Id == 5246 && effIndex != EFFECT_0) + unitTargets.remove(m_targets.GetUnitTarget()); + // Other special target selection goes here if (uint32 maxTargets = m_spellValue->MaxAffectedTargets) { @@ -1347,13 +1353,9 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge if ((*j)->IsAffectingSpell(m_spellInfo)) maxTargets += (*j)->GetAmount(); - if (m_spellInfo->Id == 5246) //Intimidating Shout - unitTargets.remove(m_targets.GetUnitTarget()); Trinity::Containers::RandomResizeList(unitTargets, maxTargets); } - CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex); - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) AddUnitTarget(*itr, effMask, false); } @@ -1369,6 +1371,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge Trinity::Containers::RandomResizeList(gObjTargets, maxTargets); } + for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr) AddGOTarget(*itr, effMask); } @@ -1376,7 +1379,7 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { - switch(targetType.GetTarget()) + switch (targetType.GetTarget()) { case TARGET_DEST_CASTER: m_targets.SetDst(*m_caster); @@ -1441,7 +1444,7 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici void Spell::SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { WorldObject* target = m_targets.GetObjectTarget(); - switch(targetType.GetTarget()) + switch (targetType.GetTarget()) { case TARGET_DEST_TARGET_ENEMY: case TARGET_DEST_TARGET_ANY: @@ -1474,7 +1477,7 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT if (!m_targets.HasDst()) m_targets.SetDst(*m_caster); - switch(targetType.GetTarget()) + switch (targetType.GetTarget()) { case TARGET_DEST_DYNOBJ_ENEMY: case TARGET_DEST_DYNOBJ_ALLY: @@ -1500,27 +1503,27 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { - switch(targetType.GetTarget()) + WorldObject* target = NULL; + bool checkIfValid = true; + + switch (targetType.GetTarget()) { case TARGET_UNIT_CASTER: - AddUnitTarget(m_caster, 1 << effIndex, false); + target = m_caster; + checkIfValid = false; break; case TARGET_UNIT_MASTER: - if (Unit* owner = m_caster->GetCharmerOrOwner()) - AddUnitTarget(owner, 1 << effIndex); + target = m_caster->GetCharmerOrOwner(); break; case TARGET_UNIT_PET: - if (Guardian* pet = m_caster->GetGuardianPet()) - AddUnitTarget(pet, 1 << effIndex); + target = m_caster->GetGuardianPet(); break; case TARGET_UNIT_SUMMONER: if (m_caster->isSummon()) - if (Unit* unit = m_caster->ToTempSummon()->GetSummoner()) - AddUnitTarget(unit, 1 << effIndex); + target = m_caster->ToTempSummon()->GetSummoner(); break; case TARGET_UNIT_VEHICLE: - if (Unit *vehicle = m_caster->GetVehicleBase()) - AddUnitTarget(vehicle, 1 << effIndex); + target = m_caster->GetVehicleBase(); break; case TARGET_UNIT_PASSENGER_0: case TARGET_UNIT_PASSENGER_1: @@ -1531,26 +1534,38 @@ void Spell::SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImpli case TARGET_UNIT_PASSENGER_6: case TARGET_UNIT_PASSENGER_7: if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsVehicle()) - if (Unit *unit = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0)) - AddUnitTarget(unit, 1 << effIndex); + target = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0); break; default: break; } + + CallScriptObjectTargetSelectHandlers(target, effIndex); + + if (target && target->ToUnit()) + AddUnitTarget(target->ToUnit(), 1 << effIndex, checkIfValid); } void Spell::SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType) { ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!"); - if (Unit* unit = m_targets.GetUnitTarget()) - AddUnitTarget(unit, 1 << effIndex, true, false); - else if (GameObject* gobj = m_targets.GetGOTarget()) - AddGOTarget(gobj, 1 << effIndex); - else - AddItemTarget(m_targets.GetItemTarget(), 1 << effIndex); - if (WorldObject* target = m_targets.GetObjectTarget()) + WorldObject* target = m_targets.GetObjectTarget(); + + CallScriptObjectTargetSelectHandlers(target, effIndex); + + if (target) + { + if (Unit* unit = target->ToUnit()) + AddUnitTarget(unit, 1 << effIndex, true, false); + else if (GameObject* gobj = target->ToGameObject()) + AddGOTarget(gobj, 1 << effIndex); + SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex); + } + // Script hook can remove object target and we would wrongly land here + else if (Item* item = m_targets.GetItemTarget()) + AddItemTarget(item, 1 << effIndex); } void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, WorldObject* target, uint32 effMask) @@ -1571,14 +1586,15 @@ void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTarg SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType() , m_spellInfo->Effects[effIndex].ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); + // Chain primary target is added earlier + CallScriptObjectAreaTargetSelectHandlers(targets, effIndex); + // for backward compability std::list<Unit*> unitTargets; for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) if (Unit* unitTarget = (*itr)->ToUnit()) unitTargets.push_back(unitTarget); - CallScriptAfterUnitTargetSelectHandlers(unitTargets, effIndex); - for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr) AddUnitTarget(*itr, effMask, false); } @@ -1741,9 +1757,12 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) case SPELL_EFFECT_SUMMON_PLAYER: if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->GetSelection()) { - Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection()); - if (target) - AddUnitTarget(target, 1 << effIndex, false); + WorldObject* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection()); + + CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex)); + + if (target && target->ToPlayer()) + AddUnitTarget(target->ToUnit(), 1 << effIndex, false); } return; default: @@ -1759,6 +1778,8 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) if (!targetMask) return; + WorldObject* target = NULL; + switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType()) { // add explicit object target or self to the target map @@ -1767,40 +1788,46 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex) if (targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK)) { if (Unit* unitTarget = m_targets.GetUnitTarget()) - AddUnitTarget(unitTarget, 1 << effIndex, false); + target = unitTarget; else if (targetMask & TARGET_FLAG_CORPSE_MASK) { if (Corpse* corpseTarget = m_targets.GetCorpseTarget()) { // TODO: this is a workaround - corpses should be added to spell target map too, but we can't do that so we add owner instead if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID())) - AddUnitTarget(owner, 1 << effIndex, false); + target = owner; } } else //if (targetMask & TARGET_FLAG_UNIT_MASK) - { - AddUnitTarget(m_caster, 1 << effIndex, false); - } + target = m_caster; } if (targetMask & TARGET_FLAG_ITEM_MASK) { if (Item* itemTarget = m_targets.GetItemTarget()) AddItemTarget(itemTarget, 1 << effIndex); + return; } if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK) - { - if (GameObject* gObjTarget = m_targets.GetGOTarget()) - AddGOTarget(gObjTarget, 1 << effIndex); - } + target = m_targets.GetGOTarget(); break; // add self to the target map case EFFECT_IMPLICIT_TARGET_CASTER: if (targetMask & TARGET_FLAG_UNIT_MASK) - AddUnitTarget(m_caster, 1 << effIndex, false); + target = m_caster; break; default: break; } + + CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex)); + + if (target) + { + if (target->ToUnit()) + AddUnitTarget(target->ToUnit(), 1 << effIndex, false); + else if (target->ToGameObject()) + AddGOTarget(target->ToGameObject(), 1 << effIndex); + } } uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList* condList) @@ -2474,12 +2501,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx); } - // Haunt - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags[1] & 0x40000 && m_spellAura && m_spellAura->GetEffect(1)) - { - AuraEffect* aurEff = m_spellAura->GetEffect(1); - aurEff->SetAmount(CalculatePctU(aurEff->GetAmount(), damageInfo.damage)); - } + m_damage = damageInfo.damage; @@ -2548,12 +2570,31 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA return SPELL_MISS_EVADE; // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case + if (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo))) + return SPELL_MISS_IMMUNE; + // disable effects to which unit is immune + SpellMissInfo returnVal = SPELL_MISS_IMMUNE; for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber) - if (effectMask & (1 << effectNumber) && unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) - effectMask &= ~(1 << effectNumber); - if (!effectMask || (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo)))) - return SPELL_MISS_IMMUNE; + { + if (effectMask & (1 << effectNumber)) + if (unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber)) + effectMask &= ~(1 << effectNumber); + else if (m_spellInfo->Effects[effectNumber].IsAura() && !m_spellInfo->IsPositiveEffect(effectNumber)) + { + int32 debuff_resist_chance = unit->GetMaxPositiveAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel)); + debuff_resist_chance += unit->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(m_spellInfo->Dispel)); + + if (debuff_resist_chance > 0) + if (irand(0,10000) <= (debuff_resist_chance * 100)) + { + effectMask &= ~(1 << effectNumber); + returnVal = SPELL_MISS_RESIST; + } + } + } + if (!effectMask) + return returnVal; PrepareScriptHitHandlers(); CallScriptBeforeHitHandlers(); @@ -3855,7 +3896,7 @@ void Spell::SendSpellStart() data << uint8(0); // unkByte // if (unkByte == 2) // data.append(0); - + } m_caster->SendMessageToSet(&data, true); @@ -3876,6 +3917,7 @@ void Spell::SendSpellGo() castFlags |= CAST_FLAG_PENDING; + if ((m_caster->GetTypeId() == TYPEID_PLAYER || (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->isPet())) && m_spellInfo->PowerType != POWER_HEALTH) @@ -4804,19 +4846,9 @@ SpellCastResult Spell::CheckCast(bool strict) if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target)) return SPELL_FAILED_LINE_OF_SIGHT; } - else - { - if (m_caster->GetTypeId() == TYPEID_PLAYER) // Target - is player caster - { - // Lay on Hands - cannot be self-cast on paladin with Forbearance or after using Avenging Wrath - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellFamilyFlags[0] & 0x0008000) - if (target->HasAura(61988)) // Immunity shield marker - return SPELL_FAILED_TARGET_AURASTATE; - } - } } - //Check for line of sight for spells with dest + // Check for line of sight for spells with dest if (m_targets.HasDst()) { float x, y, z; @@ -4915,7 +4947,9 @@ SpellCastResult Spell::CheckCast(bool strict) bool hasDispellableAura = false; bool hasNonDispelEffect = false; - for (int i = 0; i < MAX_SPELL_EFFECTS; i++) + uint32 dispelMask = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL) { if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->AttributesEx & SPELL_ATTR1_MELEE_COMBAT_START) @@ -4923,28 +4957,28 @@ SpellCastResult Spell::CheckCast(bool strict) hasDispellableAura = true; break; } - if (Unit* target = m_targets.GetUnitTarget()) - { - DispelChargesList dispelList; - uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue)); - target->GetDispellableAuraList(m_caster, dispelMask, dispelList); - if (!dispelList.empty()) - { - hasDispellableAura = true; - break; - } - } + + dispelMask |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue)); } else if (m_spellInfo->Effects[i].IsEffect()) { hasNonDispelEffect = true; break; } + } - if (!hasNonDispelEffect && !hasDispellableAura && m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL) && !IsTriggered()) - return SPELL_FAILED_NOTHING_TO_DISPEL; + if (!hasNonDispelEffect && !hasDispellableAura && dispelMask && !IsTriggered()) + { + if (Unit* target = m_targets.GetUnitTarget()) + { + DispelChargesList dispelList; + target->GetDispellableAuraList(m_caster, dispelMask, dispelList); + if (dispelList.empty()) + return SPELL_FAILED_NOTHING_TO_DISPEL; + } + } - for (int i = 0; i < MAX_SPELL_EFFECTS; i++) + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { // for effects of spells that have only one target switch (m_spellInfo->Effects[i].Effect) @@ -5285,10 +5319,6 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_EFFECT_LEAP_BACK: { - // Spell 781 (Disengage) requires player to be in combat - if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->Id == 781 && !m_caster->isInCombat()) - return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; - if (m_caster->HasUnitState(UNIT_STATE_ROOT)) { if (m_caster->GetTypeId() == TYPEID_PLAYER) @@ -5310,66 +5340,10 @@ SpellCastResult Spell::CheckCast(bool strict) } } - for (int i = 0; i < MAX_SPELL_EFFECTS; i++) + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { switch (m_spellInfo->Effects[i].ApplyAuraName) { - case SPELL_AURA_DUMMY: - { - //custom check - switch (m_spellInfo->Id) - { - // Tag Murloc - case 30877: - { - Unit* target = m_targets.GetUnitTarget(); - if (!target || target->GetEntry() != 17326) - return SPELL_FAILED_BAD_TARGETS; - break; - } - case 61336: - if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_caster->ToPlayer()->IsInFeralForm()) - return SPELL_FAILED_ONLY_SHAPESHIFT; - break; - case 1515: - { - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return SPELL_FAILED_BAD_TARGETS; - - if (!m_targets.GetUnitTarget() || m_targets.GetUnitTarget()->GetTypeId() == TYPEID_PLAYER) - return SPELL_FAILED_BAD_IMPLICIT_TARGETS; - - Creature* target = m_targets.GetUnitTarget()->ToCreature(); - - if (target->getLevel() > m_caster->getLevel()) - return SPELL_FAILED_HIGHLEVEL; - - // use SMSG_PET_TAME_FAILURE? - if (!target->GetCreatureTemplate()->isTameable (m_caster->ToPlayer()->CanTameExoticPets())) - return SPELL_FAILED_BAD_TARGETS; - - if (m_caster->GetPetGUID()) - return SPELL_FAILED_ALREADY_HAVE_SUMMON; - - if (m_caster->GetCharmGUID()) - return SPELL_FAILED_ALREADY_HAVE_CHARM; - - break; - } - case 44795: // Parachute - { - float x, y, z; - m_caster->GetPosition(x, y, z); - float ground_Z = m_caster->GetMap()->GetHeight(m_caster->GetPhaseMask(), x, y, z); - if (fabs(ground_Z - z) < 0.1f) - return SPELL_FAILED_DONT_REPORT; - break; - } - default: - break; - } - break; - } case SPELL_AURA_MOD_POSSESS_PET: { if (m_caster->GetTypeId() != TYPEID_PLAYER) @@ -7047,15 +7021,29 @@ void Spell::CallScriptAfterHitHandlers() } } -void Spell::CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTargets, SpellEffIndex effIndex) +void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex) { for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) { - (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_UNIT_TARGET_SELECT); - std::list<SpellScript::UnitTargetHandler>::iterator hookItrEnd = (*scritr)->OnUnitTargetSelect.end(), hookItr = (*scritr)->OnUnitTargetSelect.begin(); + (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT); + std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectAreaTargetSelect.end(), hookItr = (*scritr)->OnObjectAreaTargetSelect.begin(); for (; hookItr != hookItrEnd; ++hookItr) if ((*hookItr).IsEffectAffected(m_spellInfo, effIndex)) - (*hookItr).Call(*scritr, unitTargets); + (*hookItr).Call(*scritr, targets); + + (*scritr)->_FinishScriptCall(); + } +} + +void Spell::CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex) +{ + for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT); + std::list<SpellScript::ObjectTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectTargetSelect.end(), hookItr = (*scritr)->OnObjectTargetSelect.begin(); + for (; hookItr != hookItrEnd; ++hookItr) + if ((*hookItr).IsEffectAffected(m_spellInfo, effIndex)) + (*hookItr).Call(*scritr, target); (*scritr)->_FinishScriptCall(); } @@ -7089,12 +7077,6 @@ void Spell::PrepareTriggersExecutedOnHit() // todo: move this to scripts switch (m_spellInfo->SpellFamilyName) { - case SPELLFAMILY_GENERIC: - { - if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages - m_preCastSpell = 11196; // Recently Bandaged - break; - } case SPELLFAMILY_MAGE: { // Permafrost diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 777d151440c..50510397056 100755 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -629,7 +629,8 @@ class Spell void CallScriptBeforeHitHandlers(); void CallScriptOnHitHandlers(); void CallScriptAfterHitHandlers(); - void CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTargets, SpellEffIndex effIndex); + void CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex); + void CallScriptObjectTargetSelectHandlers(WorldObject*& target, SpellEffIndex effIndex); std::list<SpellScript*> m_loadedScripts; struct HitTriggerSpell diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index ca3c4197fc3..aba486b0df9 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -366,43 +366,6 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) return; break; } - case 33671: // gruul's shatter - case 50811: // krystallus shatter ( Normal ) - case 61547: // krystallus shatter ( Heroic ) - { - // don't damage self and only players - if (unitTarget->GetGUID() == m_caster->GetGUID() || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - float radius = m_spellInfo->Effects[EFFECT_0].CalcRadius(m_caster); - if (!radius) - return; - float distance = m_caster->GetDistance2d(unitTarget); - damage = (distance > radius) ? 0 : int32(m_spellInfo->Effects[EFFECT_0].CalcValue(m_caster) * ((radius - distance)/radius)); - break; - } - // Loken Pulsing Shockwave - case 59837: - case 52942: - { - // don't damage self and only players - if (unitTarget->GetGUID() == m_caster->GetGUID() || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - float radius = m_spellInfo->Effects[EFFECT_0].CalcRadius(m_caster); - if (!radius) - return; - float distance = m_caster->GetDistance2d(unitTarget); - damage = (distance > radius) ? 0 : int32(m_spellInfo->Effects[EFFECT_0].CalcValue(m_caster) * distance); - break; - } - // TODO: add spell specific target requirement hook for spells - // Shadowbolts only affects targets with Shadow Mark (Gothik) - case 27831: - case 55638: - if (!unitTarget->HasAura(27825)) - return; - break; // Gargoyle Strike case 51963: { @@ -415,11 +378,8 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex) } case SPELLFAMILY_WARRIOR: { - // Bloodthirst - if (m_spellInfo->SpellFamilyFlags[1] & 0x400) - ApplyPctF(damage, m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); // Shield Slam - else if (m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->Category == 1209) + if (m_spellInfo->SpellFamilyFlags[1] & 0x200 && m_spellInfo->Category == 1209) { uint8 level = m_caster->getLevel(); uint32 block_value = m_caster->GetShieldBlockValue(uint32(float(level) * 24.5f), uint32(float(level) * 34.5f)); @@ -2863,6 +2823,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) // add new enchanting if equipped item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, true); + item_owner->RemoveTradeableItem(itemTarget); itemTarget->ClearSoulboundTradeable(item_owner); } } @@ -2927,6 +2888,7 @@ void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex) // add new enchanting if equipped item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, true); + item_owner->RemoveTradeableItem(itemTarget); itemTarget->ClearSoulboundTradeable(item_owner); } @@ -3275,6 +3237,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(2, unitTarget); } } + if (m_spellInfo->SpellFamilyFlags[0] & 0x8000000) // Mocking Blow + { + if (unitTarget->IsImmunedToSpellEffect(m_spellInfo,EFFECT_1) || unitTarget->GetTypeId() == TYPEID_PLAYER) + { + m_damage = 0; + return; + } + } break; } case SPELLFAMILY_ROGUE: @@ -3375,7 +3345,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // Blood Strike if (m_spellInfo->SpellFamilyFlags[0] & 0x400000) { - AddPctF(totalDamagePercentMod, m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f); + float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) / 2.0f; + // Death Knight T8 Melee 4P Bonus + if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) + AddPctF(bonusPct, aurEff->GetAmount()); + AddPctF(totalDamagePercentMod, bonusPct); // Glyph of Blood Strike if (m_caster->GetAuraEffect(59332, EFFECT_0)) @@ -3402,7 +3376,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) if (roll_chance_i(aurEff->GetAmount())) consumeDiseases = false; - AddPctF(totalDamagePercentMod, m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), consumeDiseases) / 2.0f); + float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), consumeDiseases) / 2.0f; + // Death Knight T8 Melee 4P Bonus + if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) + AddPctF(bonusPct, aurEff->GetAmount()); + AddPctF(totalDamagePercentMod, bonusPct); break; } // Blood-Caked Strike - Blood-Caked Blade @@ -3414,7 +3392,12 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) // Heart Strike if (m_spellInfo->SpellFamilyFlags[0] & 0x1000000) { - AddPctN(totalDamagePercentMod, m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID())); + float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue() * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()); + // Death Knight T8 Melee 4P Bonus + if (AuraEffect const* aurEff = m_caster->GetAuraEffect(64736, EFFECT_0)) + AddPctF(bonusPct, aurEff->GetAmount()); + + AddPctF(totalDamagePercentMod, bonusPct); break; } break; @@ -3524,15 +3507,6 @@ void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/) return; int32 addhealth = 0; - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN) // Lay on Hands - { - if (m_caster->GetGUID() == unitTarget->GetGUID()) - { - m_caster->CastSpell(m_caster, 25771, true); // Forbearance - m_caster->CastSpell(m_caster, 61988, true); // Immune shield marker (serverside) - m_caster->CastSpell(m_caster, 61987, true); // Avenging Wrath marker - } - } // damage == 0 - heal for caster max health if (damage == 0) @@ -3763,12 +3737,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) if (!itemTarget && m_caster->GetTypeId() != TYPEID_PLAYER) return; - uint32 spell_id = 0; - switch (urand(1, 5)) - { - case 1: spell_id = 8854; break; - default: spell_id = 8855; break; - } + uint32 spell_id = roll_chance_i(20) ? 8854 : 8855; m_caster->CastSpell(m_caster, spell_id, true, NULL); return; @@ -3815,10 +3784,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); return; } - // Escape artist - case 20589: - m_caster->RemoveMovementImpairingAuras(); - return; // Decimate case 28374: case 54426: @@ -3849,15 +3814,8 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) DoCreateItem(effIndex, item); break; } - // Improved Sprint - case 30918: - { - // Removes snares and roots. - unitTarget->RemoveMovementImpairingAuras(); - break; - } - // Spirit Walk - case 58876: + case 20589: // Escape artist + case 30918: // Improved Sprint { // Removes snares and roots. unitTarget->RemoveMovementImpairingAuras(); @@ -3875,96 +3833,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) } } break; - case 48025: // Headless Horseman's Mount - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts and client crashes upon dismounting - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill and zone - bool canFly = true; - uint32 v_map = GetVirtualMapForMapAndZone(unitTarget->GetMapId(), unitTarget->GetZoneId()); - if (v_map != 530 && v_map != 571) - canFly = false; - - if (canFly && v_map == 571 && !unitTarget->ToPlayer()->HasSpell(54197)) - canFly = false; - - float x, y, z; - unitTarget->GetPosition(x, y, z); - uint32 areaFlag = unitTarget->GetBaseMap()->GetAreaFlag(x, y, z); - AreaTableEntry const* pArea = sAreaStore.LookupEntry(areaFlag); - if (!pArea || (canFly && (pArea->flags & AREA_FLAG_NO_FLY_ZONE))) - canFly = false; - - switch (unitTarget->ToPlayer()->GetBaseSkillValue(SKILL_RIDING)) - { - case 75: unitTarget->CastSpell(unitTarget, 51621, true); break; - case 150: unitTarget->CastSpell(unitTarget, 48024, true); break; - case 225: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 51617, true); - else - unitTarget->CastSpell(unitTarget, 48024, true); - }break; - case 300: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 48023, true); - else - unitTarget->CastSpell(unitTarget, 48024, true); - }break; - } - return; - } - case 47977: // Magic Broom - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts and client crashes upon dismounting - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill and zone - bool canFly = true; - uint32 v_map = GetVirtualMapForMapAndZone(unitTarget->GetMapId(), unitTarget->GetZoneId()); - if (v_map != 530 && v_map != 571) - canFly = false; - - if (canFly && v_map == 571 && !unitTarget->ToPlayer()->HasSpell(54197)) - canFly = false; - - float x, y, z; - unitTarget->GetPosition(x, y, z); - uint32 areaFlag = unitTarget->GetBaseMap()->GetAreaFlag(x, y, z); - AreaTableEntry const* pArea = sAreaStore.LookupEntry(areaFlag); - if (!pArea || (canFly && (pArea->flags & AREA_FLAG_NO_FLY_ZONE))) - canFly = false; - - switch (unitTarget->ToPlayer()->GetBaseSkillValue(SKILL_RIDING)) - { - case 75: unitTarget->CastSpell(unitTarget, 42680, true); break; - case 150: unitTarget->CastSpell(unitTarget, 42683, true); break; - case 225: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 42667, true); - else - unitTarget->CastSpell(unitTarget, 42683, true); - }break; - case 300: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 42668, true); - else - unitTarget->CastSpell(unitTarget, 42683, true); - }break; - } - return; - } // Mug Transformation case 41931: { @@ -4156,25 +4024,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) if (unitTarget) unitTarget->CastSpell(m_caster, damage, true); return; - // Winged Steed of the Ebon Blade - case 54729: - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts and client crashes upon dismounting - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill - if (uint16 skillval = unitTarget->ToPlayer()->GetSkillValue(SKILL_RIDING)) - { - if (skillval >= 300) - unitTarget->CastSpell(unitTarget, 54727, true); - else - unitTarget->CastSpell(unitTarget, 54726, true); - } - return; - } case 57347: // Retrieving (Wintergrasp RP-GG pickup spell) { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER) @@ -4257,188 +4106,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) m_caster->CastSpell(m_caster, 63919, true); return; } - case 71342: // Big Love Rocket - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts and client crashes upon dismounting - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill and zone - bool canFly = true; - uint32 v_map = GetVirtualMapForMapAndZone(unitTarget->GetMapId(), unitTarget->GetZoneId()); - if (v_map != 530 && v_map != 571) - canFly = false; - - if (canFly && v_map == 571 && !unitTarget->ToPlayer()->HasSpell(54197)) - canFly = false; - - float x, y, z; - unitTarget->GetPosition(x, y, z); - uint32 areaFlag = unitTarget->GetBaseMap()->GetAreaFlag(x, y, z); - AreaTableEntry const* pArea = sAreaStore.LookupEntry(areaFlag); - if (!pArea || (canFly && (pArea->flags & AREA_FLAG_NO_FLY_ZONE))) - canFly = false; - - switch (unitTarget->ToPlayer()->GetBaseSkillValue(SKILL_RIDING)) - { - case 0: unitTarget->CastSpell(unitTarget, 71343, true); break; - case 75: unitTarget->CastSpell(unitTarget, 71344, true); break; - case 150: unitTarget->CastSpell(unitTarget, 71345, true); break; - case 225: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 71346, true); - else - unitTarget->CastSpell(unitTarget, 71345, true); - }break; - case 300: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 71347, true); - else - unitTarget->CastSpell(unitTarget, 71345, true); - }break; - } - return; - } - case 72286: // Invincible - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts and client crashes upon dismounting - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill and zone - bool canFly = true; - uint32 v_map = GetVirtualMapForMapAndZone(unitTarget->GetMapId(), unitTarget->GetZoneId()); - if (v_map != 530 && v_map != 571) - canFly = false; - - if (canFly && v_map == 571 && !unitTarget->ToPlayer()->HasSpell(54197)) - canFly = false; - - float x, y, z; - unitTarget->GetPosition(x, y, z); - uint32 areaFlag = unitTarget->GetBaseMap()->GetAreaFlag(x, y, z); - AreaTableEntry const* pArea = sAreaStore.LookupEntry(areaFlag); - if (!pArea || (canFly && (pArea->flags & AREA_FLAG_NO_FLY_ZONE))) - canFly = false; - - switch (unitTarget->ToPlayer()->GetBaseSkillValue(SKILL_RIDING)) - { - case 75: unitTarget->CastSpell(unitTarget, 72281, true); break; - case 150: unitTarget->CastSpell(unitTarget, 72282, true); break; - case 225: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 72283, true); - else - unitTarget->CastSpell(unitTarget, 72282, true); - }break; - case 300: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 72284, true); - else - unitTarget->CastSpell(unitTarget, 72282, true); - }break; - } - return; - } - case 74856: // Blazing Hippogryph - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts and client crashes upon dismounting - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill - if (uint16 skillval = unitTarget->ToPlayer()->GetSkillValue(SKILL_RIDING)) - { - if (skillval >= 300) - unitTarget->CastSpell(unitTarget, 74855, true); - else - unitTarget->CastSpell(unitTarget, 74854, true); - } - return; - } - case 75614: // Celestial Steed - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts and client crashes upon dismounting - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill and zone - bool canFly = true; - uint32 v_map = GetVirtualMapForMapAndZone(unitTarget->GetMapId(), unitTarget->GetZoneId()); - if (v_map != 530 && v_map != 571) - canFly = false; - - if (canFly && v_map == 571 && !unitTarget->ToPlayer()->HasSpell(54197)) - canFly = false; - - float x, y, z; - unitTarget->GetPosition(x, y, z); - uint32 areaFlag = unitTarget->GetBaseMap()->GetAreaFlag(x, y, z); - AreaTableEntry const* pArea = sAreaStore.LookupEntry(areaFlag); - if (!pArea || (canFly && (pArea->flags & AREA_FLAG_NO_FLY_ZONE))) - canFly = false; - - switch (unitTarget->ToPlayer()->GetBaseSkillValue(SKILL_RIDING)) - { - case 75: unitTarget->CastSpell(unitTarget, 75619, true); break; - case 150: unitTarget->CastSpell(unitTarget, 75620, true); break; - case 225: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 75617, true); - else - unitTarget->CastSpell(unitTarget, 75620, true); - } - break; - case 300: - { - if (canFly) - unitTarget->CastSpell(unitTarget, 75618, true); - else - unitTarget->CastSpell(unitTarget, 75620, true); - } - break; - case 375: - if (canFly) - unitTarget->CastSpell(unitTarget, 76153, true); - else - unitTarget->CastSpell(unitTarget, 75620, true); - break; - } - return; - } - case 75973: // X-53 Touring Rocket - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - // Prevent stacking of mounts - unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - - // Triggered spell id dependent on riding skill - if (uint16 skillval = unitTarget->ToPlayer()->GetSkillValue(SKILL_RIDING)) - { - if (skillval >= 375) - unitTarget->CastSpell(unitTarget, 76154, true); - else if (skillval >= 300) - unitTarget->CastSpell(unitTarget, 75972, true); - else - unitTarget->CastSpell(unitTarget, 75957, true); - } - return; - } case 59317: // Teleporting if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; @@ -5058,16 +4725,14 @@ void Spell::EffectDisEnchant(SpellEffIndex /*effIndex*/) if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET) return; - if (m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - Player* p_caster = (Player*)m_caster; if (!itemTarget || !itemTarget->GetTemplate()->DisenchantID) return; - p_caster->UpdateCraftSkill(m_spellInfo->Id); - - m_caster->ToPlayer()->SendLoot(itemTarget->GetGUID(), LOOT_DISENCHANTING); + if (Player* caster = m_caster->ToPlayer()) + { + caster->UpdateCraftSkill(m_spellInfo->Id); + caster->SendLoot(itemTarget->GetGUID(), LOOT_DISENCHANTING); + } // item will be removed at disenchanting end } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 183ca747b37..bb4815d5fc1 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -452,6 +452,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const if (!basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION && _spellInfo->SpellLevel) && Effect != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE && Effect != SPELL_EFFECT_KNOCK_BACK && + Effect != SPELL_EFFECT_ADD_EXTRA_ATTACKS && ApplyAuraName != SPELL_AURA_MOD_SPEED_ALWAYS && ApplyAuraName != SPELL_AURA_MOD_SPEED_NOT_STACK && ApplyAuraName != SPELL_AURA_MOD_INCREASE_SPEED && @@ -1810,6 +1811,7 @@ AuraStateType SpellInfo::GetAuraState() const switch (Id) { case 71465: // Divine Surge + case 50241: // Evasive Charges return AURA_STATE_UNKNOWN22; default: break; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 117953f2bc0..439b0c91324 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2960,8 +2960,10 @@ void SpellMgr::LoadDbcDataCorrections() switch (spellInfo->Id) { - case 40244: case 40245: // Simon Game Visual - case 40246: case 40247: // Simon Game Visual + case 40244: // Simon Game Visual + case 40245: // Simon Game Visual + case 40246: // Simon Game Visual + case 40247: // Simon Game Visual case 42835: // Spout, remove damage effect, only anim is needed spellInfo->Effect[0] = 0; break; @@ -2973,7 +2975,6 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->EffectImplicitTargetB[0] = 0; break; case 63665: // Charge (Argent Tournament emote on riders) - case 31447: // Mark of Kaz'rogal (needs target selection script) case 31298: // Sleep (needs target selection script) case 51904: // Summon Ghouls On Scarlet Crusade (this should use conditions table, script for this spell needs to be fixed) case 2895: // Wrath of Air Totem rank 1 (Aura) @@ -3045,6 +3046,9 @@ void SpellMgr::LoadDbcDataCorrections() case 48246: // Ball of Flame spellInfo->MaxAffectedTargets = 1; break; + case 36384: // Skartax Purple Beam + spellInfo->MaxAffectedTargets = 2; + break; case 41376: // Spite case 39992: // Needle Spine case 29576: // Multi-Shot @@ -3084,7 +3088,7 @@ void SpellMgr::LoadDbcDataCorrections() case 50312: // Unholy Frenzy spellInfo->MaxAffectedTargets = 15; break; - case 33711: //Murmur's Touch + case 33711: // Murmur's Touch case 38794: spellInfo->MaxAffectedTargets = 1; spellInfo->EffectTriggerSpell[0] = 33760; @@ -3125,6 +3129,9 @@ void SpellMgr::LoadDbcDataCorrections() case 51852: // The Eye of Acherus (no spawn in phase 2 in db) spellInfo->EffectMiscValue[0] |= 1; break; + case 51912: // Crafty's Ultra-Advanced Proto-Typical Shortening Blaster + spellInfo->EffectAmplitude[0] = 3000; + break; case 29809: // Desecration Arm - 36 instead of 37 - typo? :/ spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_7_YARDS; break; @@ -3238,6 +3245,9 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->EffectDieSides[0] = 0; // was 1, that should probably mean seat 0, but instead it's treated as spell 1 spellInfo->EffectBasePoints[0] = 52391; // Ride Vehicle (forces seat 0) break; + case 45602: // Ride Carpet + spellInfo->EffectBasePoints[EFFECT_0] = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)" + break; case 64745: // Item - Death Knight T8 Tank 4P Bonus case 64936: // Item - Warrior T8 Protection 4P Bonus spellInfo->EffectBasePoints[0] = 100; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit) @@ -3252,9 +3262,16 @@ void SpellMgr::LoadDbcDataCorrections() case 53313: // Entangling Roots (Rank 8) -- Nature's Grasp Proc spellInfo->CastingTimeIndex = 1; break; + case 59414: // Pulsing Shockwave Aura (Loken) + // this flag breaks movement, remove it + spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED_1; + break; case 61719: // Easter Lay Noblegarden Egg Aura - Interrupt flags copied from aura which this aura is linked with spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE; break; + case 70650: // Death Knight T10 Tank 2P Bonus + spellInfo->EffectApplyAuraName[0] = SPELL_AURA_ADD_PCT_MODIFIER; + break; // ULDUAR SPELLS // case 62374: // Pursued (Flame Leviathan) @@ -3293,11 +3310,6 @@ void SpellMgr::LoadDbcDataCorrections() // that will be clear if we get more spells with problem like this spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY; break; - case 62584: // Lifebinder's Gift - case 64185: // Lifebinder's Gift - spellInfo->EffectImplicitTargetB[1] = TARGET_UNIT_NEARBY_ENTRY; - spellInfo->EffectImplicitTargetB[2] = TARGET_UNIT_NEARBY_ENTRY; - break; case 62301: // Cosmic Smash (Algalon the Observer) spellInfo->MaxAffectedTargets = 1; break; @@ -3429,7 +3441,7 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->EffectRadiusIndex[0] = EFFECT_RADIUS_200_YARDS; // 200yd break; case 70598: // Sindragosa's Fury - spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_CASTER; + spellInfo->EffectImplicitTargetA[0] = TARGET_DEST_DEST; break; case 69846: // Frost Bomb spellInfo->speed = 0.0f; // This spell's summon happens instantly @@ -3539,11 +3551,6 @@ void SpellMgr::LoadDbcDataCorrections() switch (spellInfo->SpellFamilyName) { - case SPELLFAMILY_DRUID: - // Starfall Target Selection - if (spellInfo->SpellFamilyFlags[2] & 0x100) - spellInfo->MaxAffectedTargets = 2; - break; case SPELLFAMILY_PALADIN: // Seals of the Pure should affect Seal of Righteousness if (spellInfo->SpellIconID == 25 && spellInfo->Attributes & SPELL_ATTR0_PASSIVE) diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index e6ce80c20f0..d0ae6fe3098 100755 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -203,52 +203,106 @@ void SpellScript::HitHandler::Call(SpellScript* spellScript) (spellScript->*pHitHandlerScript)(); } -SpellScript::UnitTargetHandler::UnitTargetHandler(SpellUnitTargetFnType _pUnitTargetHandlerScript, uint8 _effIndex, uint16 _targetType) - : _SpellScript::EffectHook(_effIndex), targetType(_targetType) +SpellScript::TargetHook::TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area) + : _SpellScript::EffectHook(_effectIndex), targetType(_targetType), area(_area) { - pUnitTargetHandlerScript = _pUnitTargetHandlerScript; } -std::string SpellScript::UnitTargetHandler::ToString() +std::string SpellScript::TargetHook::ToString() { std::ostringstream oss; oss << "Index: " << EffIndexToString() << " Target: " << targetType; return oss.str(); } -bool SpellScript::UnitTargetHandler::CheckEffect(SpellInfo const* spellEntry, uint8 effIndex) +bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellEntry, uint8 effIndex) { if (!targetType) return false; - return (effIndex == EFFECT_ALL) || (spellEntry->Effects[effIndex].TargetA.GetTarget() == targetType || spellEntry->Effects[effIndex].TargetB.GetTarget() == targetType); + + if (spellEntry->Effects[effIndex].TargetA.GetTarget() != targetType && + spellEntry->Effects[effIndex].TargetB.GetTarget() != targetType) + return false; + + SpellImplicitTargetInfo targetInfo(targetType); + switch (targetInfo.GetSelectionCategory()) + { + case TARGET_SELECT_CATEGORY_CHANNEL: // SINGLE + return !area; + case TARGET_SELECT_CATEGORY_NEARBY: // BOTH + return true; + case TARGET_SELECT_CATEGORY_CONE: // AREA + case TARGET_SELECT_CATEGORY_AREA: // AREA + return area; + case TARGET_SELECT_CATEGORY_DEFAULT: + switch (targetInfo.GetObjectType()) + { + case TARGET_OBJECT_TYPE_SRC: // EMPTY + case TARGET_OBJECT_TYPE_DEST: // EMPTY + return false; + default: + switch (targetInfo.GetReferenceType()) + { + case TARGET_REFERENCE_TYPE_CASTER: // SINGLE + return !area; + case TARGET_REFERENCE_TYPE_TARGET: // BOTH + return true; + } + break; + } + break; + } + + return false; +} + +SpellScript::ObjectAreaTargetSelectHandler::ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) + : TargetHook(_effIndex, _targetType, true) +{ + pObjectAreaTargetSelectHandlerScript = _pObjectAreaTargetSelectHandlerScript; +} + +void SpellScript::ObjectAreaTargetSelectHandler::Call(SpellScript* spellScript, std::list<WorldObject*>& targets) +{ + (spellScript->*pObjectAreaTargetSelectHandlerScript)(targets); } -void SpellScript::UnitTargetHandler::Call(SpellScript* spellScript, std::list<Unit*>& unitTargets) +SpellScript::ObjectTargetSelectHandler::ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) + : TargetHook(_effIndex, _targetType, false) { - (spellScript->*pUnitTargetHandlerScript)(unitTargets); + pObjectTargetSelectHandlerScript = _pObjectTargetSelectHandlerScript; +} + +void SpellScript::ObjectTargetSelectHandler::Call(SpellScript* spellScript, WorldObject*& target) +{ + (spellScript->*pObjectTargetSelectHandlerScript)(target); } bool SpellScript::_Validate(SpellInfo const* entry) { - for (std::list<EffectHandler>::iterator itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr) + for (std::list<EffectHandler>::iterator itr = OnEffectLaunch.begin(); itr != OnEffectLaunch.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectLaunch` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); - for (std::list<EffectHandler>::iterator itr = OnEffectLaunchTarget.begin(); itr != OnEffectLaunchTarget.end(); ++itr) + for (std::list<EffectHandler>::iterator itr = OnEffectLaunchTarget.begin(); itr != OnEffectLaunchTarget.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectLaunchTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); - for (std::list<EffectHandler>::iterator itr = OnEffectHit.begin(); itr != OnEffectHit.end(); ++itr) + for (std::list<EffectHandler>::iterator itr = OnEffectHit.begin(); itr != OnEffectHit.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectHit` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); - for (std::list<EffectHandler>::iterator itr = OnEffectHitTarget.begin(); itr != OnEffectHitTarget.end(); ++itr) + for (std::list<EffectHandler>::iterator itr = OnEffectHitTarget.begin(); itr != OnEffectHitTarget.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectHitTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); - for (std::list<UnitTargetHandler>::iterator itr = OnUnitTargetSelect.begin(); itr != OnUnitTargetSelect.end(); ++itr) + for (std::list<ObjectAreaTargetSelectHandler>::iterator itr = OnObjectAreaTargetSelect.begin(); itr != OnObjectAreaTargetSelect.end(); ++itr) + if (!(*itr).GetAffectedEffectsMask(entry)) + sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + + for (std::list<ObjectTargetSelectHandler>::iterator itr = OnObjectTargetSelect.begin(); itr != OnObjectTargetSelect.end(); ++itr) if (!(*itr).GetAffectedEffectsMask(entry)) - sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnUnitTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); + sLog->outError("TSCR: Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str()); return _SpellScript::_Validate(entry); } diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 7b194b7827f..376e7f18edc 100755 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -131,7 +131,8 @@ enum SpellScriptHookType SPELL_SCRIPT_HOOK_BEFORE_HIT, SPELL_SCRIPT_HOOK_HIT, SPELL_SCRIPT_HOOK_AFTER_HIT, - SPELL_SCRIPT_HOOK_UNIT_TARGET_SELECT, + SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT, + SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT, SPELL_SCRIPT_HOOK_CHECK_CAST, SPELL_SCRIPT_HOOK_BEFORE_CAST, SPELL_SCRIPT_HOOK_ON_CAST, @@ -154,7 +155,8 @@ class SpellScript : public _SpellScript typedef void(CLASSNAME::*SpellEffectFnType)(SpellEffIndex); \ typedef void(CLASSNAME::*SpellHitFnType)(); \ typedef void(CLASSNAME::*SpellCastFnType)(); \ - typedef void(CLASSNAME::*SpellUnitTargetFnType)(std::list<Unit*>&); \ + typedef void(CLASSNAME::*SpellObjectAreaTargetSelectFnType)(std::list<WorldObject*>&); \ + typedef void(CLASSNAME::*SpellObjectTargetSelectFnType)(WorldObject*&); SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript) @@ -196,16 +198,33 @@ class SpellScript : public _SpellScript SpellHitFnType pHitHandlerScript; }; - class UnitTargetHandler : public _SpellScript::EffectHook + class TargetHook : public _SpellScript::EffectHook { public: - UnitTargetHandler(SpellUnitTargetFnType _pUnitTargetHandlerScript, uint8 _effIndex, uint16 _targetType); + TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area); + bool CheckEffect(SpellInfo const* spellEntry, uint8 effIndex); std::string ToString(); - bool CheckEffect(SpellInfo const* spellEntry, uint8 targetType); - void Call(SpellScript* spellScript, std::list<Unit*>& unitTargets); - private: - SpellUnitTargetFnType pUnitTargetHandlerScript; + protected: uint16 targetType; + bool area; + }; + + class ObjectAreaTargetSelectHandler : public TargetHook + { + public: + ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); + void Call(SpellScript* spellScript, std::list<WorldObject*>& targets); + private: + SpellObjectAreaTargetSelectFnType pObjectAreaTargetSelectHandlerScript; + }; + + class ObjectTargetSelectHandler : public TargetHook + { + public: + ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType); + void Call(SpellScript* spellScript, WorldObject*& targets); + private: + SpellObjectTargetSelectFnType pObjectTargetSelectHandlerScript; }; #define SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) \ @@ -213,7 +232,8 @@ class SpellScript : public _SpellScript class CheckCastHandlerFunction : public SpellScript::CheckCastHandler { public: CheckCastHandlerFunction(SpellCheckCastFnType _checkCastHandlerScript) : SpellScript::CheckCastHandler((SpellScript::SpellCheckCastFnType)_checkCastHandlerScript) {} }; \ class EffectHandlerFunction : public SpellScript::EffectHandler { public: EffectHandlerFunction(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName) : SpellScript::EffectHandler((SpellScript::SpellEffectFnType)_pEffectHandlerScript, _effIndex, _effName) {} }; \ class HitHandlerFunction : public SpellScript::HitHandler { public: HitHandlerFunction(SpellHitFnType _pHitHandlerScript) : SpellScript::HitHandler((SpellScript::SpellHitFnType)_pHitHandlerScript) {} }; \ - class UnitTargetHandlerFunction : public SpellScript::UnitTargetHandler { public: UnitTargetHandlerFunction(SpellUnitTargetFnType _pUnitTargetHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::UnitTargetHandler((SpellScript::SpellUnitTargetFnType)_pUnitTargetHandlerScript, _effIndex, _targetType) {} }; \ + class ObjectAreaTargetSelectHandlerFunction : public SpellScript::ObjectAreaTargetSelectHandler { public: ObjectAreaTargetSelectHandlerFunction(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectAreaTargetSelectHandler((SpellScript::SpellObjectAreaTargetSelectFnType)_pObjectAreaTargetSelectHandlerScript, _effIndex, _targetType) {} }; \ + class ObjectTargetSelectHandlerFunction : public SpellScript::ObjectTargetSelectHandler { public: ObjectTargetSelectHandlerFunction(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType) : SpellScript::ObjectTargetSelectHandler((SpellScript::SpellObjectTargetSelectFnType)_pObjectTargetSelectHandlerScript, _effIndex, _targetType) {} }; #define PrepareSpellScript(CLASSNAME) SPELLSCRIPT_FUNCTION_TYPE_DEFINES(CLASSNAME) SPELLSCRIPT_FUNCTION_CAST_DEFINES(CLASSNAME) public: @@ -267,15 +287,21 @@ class SpellScript : public _SpellScript // where function is: void function() #define SpellHitFn(F) HitHandlerFunction(&F) - // example: OnUnitTargetSelect += SpellUnitTargetFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); - // where function is void function(std::list<Unit*>& targetList) - HookList<UnitTargetHandler> OnUnitTargetSelect; - #define SpellUnitTargetFn(F, I, N) UnitTargetHandlerFunction(&F, I, N) + // example: OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); + // where function is void function(std::list<WorldObject*>& targets) + HookList<ObjectAreaTargetSelectHandler> OnObjectAreaTargetSelect; + #define SpellObjectAreaTargetSelectFn(F, I, N) ObjectAreaTargetSelectHandlerFunction(&F, I, N) + + // example: OnObjectTargetSelect += SpellObjectTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier); + // where function is void function(WorldObject*& target) + HookList<ObjectTargetSelectHandler> OnObjectTargetSelect; + #define SpellObjectTargetSelectFn(F, I, N) ObjectTargetSelectHandlerFunction(&F, I, N) // hooks are executed in following order, at specified event of spell: // 1. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled // 2. OnCheckCast - allows to override result of CheckCast function - // 3. OnUnitTargetSelect - executed just before adding selected targets to final target list + // 3a. OnObjectAreaTargetSelect - executed just before adding selected targets to final target list (for area targets) + // 3b. OnObjectTargetSelect - executed just before adding selected target to final target list (for single unit targets) // 4. OnCast - executed just before spell is launched (creates missile) or executed // 5. AfterCast - executed after spell missile is launched and immediate spell actions are done // 6. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched @@ -302,7 +328,7 @@ class SpellScript : public _SpellScript // -shadowstep - explicit target is the unit you want to go behind of // -chain heal - explicit target is the unit to be healed first // -holy nova/arcane explosion - explicit target = NULL because target you are selecting doesn't affect how spell targets are selected - // you can determine if spell requires explicit targets by dbc columns: + // you can determine if spell requires explicit targets by dbc columns: // - Targets - mask of explicit target types // - ImplicitTargetXX set to TARGET_XXX_TARGET_YYY, _TARGET_ here means that explicit target is used by the effect, so spell needs one too diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp index 0734e0a0f63..54e56174b1a 100644 --- a/src/server/game/Warden/Warden.cpp +++ b/src/server/game/Warden/Warden.cpp @@ -188,11 +188,14 @@ std::string Warden::Penalty(WardenCheck* check /*= NULL*/) std::string accountName; AccountMgr::GetName(_session->GetAccountId(), accountName); std::stringstream banReason; - banReason << "Warden Anticheat Violation: " << check->Comment << " (CheckId: " << check->CheckId << ")"; + banReason << "Warden Anticheat Violation"; + // Check can be NULL, for example if the client sent a wrong signature in the warden packet (CHECKSUM FAIL) + if (check) + banReason << ": " << check->Comment << " (CheckId: " << check->CheckId << ")"; + sWorld->BanAccount(BAN_ACCOUNT, accountName, duration.str(), banReason.str(),"Server"); return "Ban"; - break; } default: break; @@ -208,7 +211,7 @@ void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData) sLog->outDebug(LOG_FILTER_WARDEN, "Got packet, opcode %02X, size %u", opcode, uint32(recvData.size())); recvData.hexlike(); - switch(opcode) + switch (opcode) { case WARDEN_CMSG_MODULE_MISSING: _warden->SendModuleToClient(); diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp index f4c7a5069cf..abd7ff8f87d 100644 --- a/src/server/game/Warden/WardenCheckMgr.cpp +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -121,7 +121,7 @@ void WardenCheckMgr::LoadWardenChecks() if (checkType == MPQ_CHECK || checkType == MEM_CHECK) { - WardenCheckResult *wr = new WardenCheckResult(); + WardenCheckResult* wr = new WardenCheckResult(); wr->Result.SetHexStr(checkResult.c_str()); int len = checkResult.size() / 2; if (wr->Result.GetNumBytes() < len) diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp index a60ae765013..3cc95b9f3f7 100644 --- a/src/server/game/Warden/WardenMac.cpp +++ b/src/server/game/Warden/WardenMac.cpp @@ -43,8 +43,8 @@ void WardenMac::Init(WorldSession *pClient, BigNumber *K) _session = pClient; // Generate Warden Key SHA1Randx WK(K->AsByteArray(), K->GetNumBytes()); - WK.generate(_inputKey, 16); - WK.generate(_outputKey, 16); + WK.Generate(_inputKey, 16); + WK.Generate(_outputKey, 16); /* Seed: 4D808D2C77D905C41A6380EC08586AFE (0x05 packet) Hash: <?> (0x04 packet) @@ -222,7 +222,7 @@ void WardenMac::HandleData(ByteBuffer &buff) // return; //} - bool found = false; + //bool found = false; std::string str = "Test string!"; @@ -238,7 +238,7 @@ void WardenMac::HandleData(ByteBuffer &buff) if (memcmp(sha1Hash, sha1.GetDigest(), 20)) { sLog->outDebug(LOG_FILTER_WARDEN, "Handle data failed: SHA1 hash is wrong!"); - found = true; + //found = true; } MD5_CTX ctx; @@ -253,7 +253,7 @@ void WardenMac::HandleData(ByteBuffer &buff) if (memcmp(ourMD5Hash, theirsMD5Hash, 16)) { sLog->outDebug(LOG_FILTER_WARDEN, "Handle data failed: MD5 hash is wrong!"); - found = true; + //found = true; } _session->KickPlayer(); diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp index a7485d7da51..9aa439ec8c0 100644 --- a/src/server/game/Warden/WardenWin.cpp +++ b/src/server/game/Warden/WardenWin.cpp @@ -47,8 +47,8 @@ void WardenWin::Init(WorldSession* session, BigNumber *k) _session = session; // Generate Warden Key SHA1Randx WK(k->AsByteArray(), k->GetNumBytes()); - WK.generate(_inputKey, 16); - WK.generate(_outputKey, 16); + WK.Generate(_inputKey, 16); + WK.Generate(_outputKey, 16); memcpy(_seed, Module.Seed, 16); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a3b9054bd68..fc46d8d2d60 100755 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1023,6 +1023,7 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_BG_XP_FOR_KILL] = ConfigMgr::GetBoolDefault("Battleground.GiveXPForKills", false); m_int_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = ConfigMgr::GetIntDefault ("Arena.MaxRatingDifference", 150); m_int_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = ConfigMgr::GetIntDefault ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILLISECONDS); + m_int_configs[CONFIG_ARENA_RATED_UPDATE_TIMER] = ConfigMgr::GetIntDefault ("Arena.RatedUpdateTimer", 5 * IN_MILLISECONDS); m_bool_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = ConfigMgr::GetBoolDefault("Arena.AutoDistributePoints", false); m_int_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = ConfigMgr::GetIntDefault ("Arena.AutoDistributeInterval", 7); m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = ConfigMgr::GetBoolDefault("Arena.QueueAnnouncer.Enable", false); @@ -1413,15 +1414,9 @@ void World::SetInitialWorldSettings() sLog->outString("Loading Creature Addon Data..."); sObjectMgr->LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures() - sLog->outString("Loading Creature Respawn Data..."); // must be after PackInstances() - sObjectMgr->LoadCreatureRespawnTimes(); - sLog->outString("Loading Gameobject Data..."); sObjectMgr->LoadGameobjects(); - sLog->outString("Loading Gameobject Respawn Data..."); // must be after PackInstances() - sObjectMgr->LoadGameobjectRespawnTimes(); - sLog->outString("Loading Creature Linked Respawn..."); sObjectMgr->LoadLinkedRespawn(); // must be after LoadCreatures(), LoadGameObjects() diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 51f384770da..450183226fc 100755 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -289,6 +289,7 @@ enum WorldIntConfigs CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH, CONFIG_ARENA_MAX_RATING_DIFFERENCE, CONFIG_ARENA_RATING_DISCARD_TIMER, + CONFIG_ARENA_RATED_UPDATE_TIMER, CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, CONFIG_ARENA_SEASON_ID, CONFIG_ARENA_START_RATING, diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index 86fe984e197..c27b51a1ca2 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -12,30 +12,30 @@ set(scripts_STAT_SRCS ${scripts_STAT_SRCS} Commands/cs_account.cpp Commands/cs_achievement.cpp + Commands/cs_cast.cpp + Commands/cs_character.cpp Commands/cs_debug.cpp Commands/cs_event.cpp Commands/cs_gm.cpp Commands/cs_go.cpp Commands/cs_gobject.cpp Commands/cs_honor.cpp + Commands/cs_instance.cpp Commands/cs_learn.cpp + Commands/cs_list.cpp Commands/cs_misc.cpp Commands/cs_modify.cpp Commands/cs_npc.cpp Commands/cs_quest.cpp Commands/cs_reload.cpp + Commands/cs_reset.cpp Commands/cs_tele.cpp + Commands/cs_server.cpp Commands/cs_titles.cpp Commands/cs_wp.cpp -# Commands/cs_character.cpp -# Commands/cs_list.cpp # Commands/cs_lookup.cpp # Commands/cs_pdump.cpp # Commands/cs_guild.cpp -# Commands/cs_cast.cpp -# Commands/cs_reset.cpp -# Commands/cs_instance.cpp -# Commands/cs_server.cpp # Commands/cs_channel.cpp # Commands/cs_pet.cpp # Commands/cs_ticket.cpp diff --git a/src/server/scripts/Commands/cs_cast.cpp b/src/server/scripts/Commands/cs_cast.cpp new file mode 100644 index 00000000000..33983411427 --- /dev/null +++ b/src/server/scripts/Commands/cs_cast.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* ScriptData +Name: cast_commandscript +%Complete: 100 +Comment: All cast related commands +Category: commandscripts +EndScriptData */ + +#include "ScriptMgr.h" +#include "Chat.h" + +class cast_commandscript : public CommandScript +{ +public: + cast_commandscript() : CommandScript("cast_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand castCommandTable[] = + { + { "back", SEC_ADMINISTRATOR, false, &HandleCastBackCommand, "", NULL }, + { "dist", SEC_ADMINISTRATOR, false, &HandleCastDistCommand, "", NULL }, + { "self", SEC_ADMINISTRATOR, false, &HandleCastSelfCommand, "", NULL }, + { "target", SEC_ADMINISTRATOR, false, &HandleCastTargetCommad, "", NULL }, + { "dest", SEC_ADMINISTRATOR, false, &HandleCastDestCommand, "", NULL }, + { "", SEC_ADMINISTRATOR, false, &HandleCastCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + static ChatCommand commandTable[] = + { + { "cast", SEC_ADMINISTRATOR, false, NULL, "", castCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + static bool HandleCastCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Unit* target = handler->getSelectedUnit(); + if (!target) + { + handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + if (!spellId) + return false; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo) + { + handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + handler->SetSentErrorMessage(true); + return false; + } + + if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer())) + { + handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); + handler->SetSentErrorMessage(true); + return false; + } + + char* triggeredStr = strtok(NULL, " "); + if (triggeredStr) + { + int l = strlen(triggeredStr); + if (strncmp(triggeredStr, "triggered", l) != 0) + return false; + } + + bool triggered = (triggeredStr != NULL); + + handler->GetSession()->GetPlayer()->CastSpell(target, spellId, triggered); + + return true; + } + + static bool HandleCastBackCommand(ChatHandler* handler, char const* args) + { + Creature* caster = handler->getSelectedCreature(); + if (!caster) + { + handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) + { + handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + handler->SetSentErrorMessage(true); + return false; + } + + char* triggeredStr = strtok(NULL, " "); + if (triggeredStr) + { + int l = strlen(triggeredStr); + if (strncmp(triggeredStr, "triggered", l) != 0) + return false; + } + + bool triggered = (triggeredStr != NULL); + + caster->CastSpell(handler->GetSession()->GetPlayer(), spellId, triggered); + + return true; + } + + static bool HandleCastDistCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + if (!spellId) + return false; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo) + { + handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + handler->SetSentErrorMessage(true); + return false; + } + + if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer())) + { + handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); + handler->SetSentErrorMessage(true); + return false; + } + + char* distStr = strtok(NULL, " "); + + float dist = 0; + + if (distStr) + sscanf(distStr, "%f", &dist); + + char* triggeredStr = strtok(NULL, " "); + if (triggeredStr) + { + int l = strlen(triggeredStr); + if (strncmp(triggeredStr, "triggered", l) != 0) + return false; + } + + bool triggered = (triggeredStr != NULL); + + float x, y, z; + handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, dist); + + handler->GetSession()->GetPlayer()->CastSpell(x, y, z, spellId, triggered); + + return true; + } + + static bool HandleCastSelfCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Unit* target = handler->getSelectedUnit(); + if (!target) + { + handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + if (!spellId) + return false; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo) + return false; + + if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer())) + { + handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); + handler->SetSentErrorMessage(true); + return false; + } + + target->CastSpell(target, spellId, false); + + return true; + } + + static bool HandleCastTargetCommad(ChatHandler* handler, char const* args) + { + Creature* caster = handler->getSelectedCreature(); + if (!caster) + { + handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + if (!caster->getVictim()) + { + handler->SendSysMessage(LANG_SELECTED_TARGET_NOT_HAVE_VICTIM); + handler->SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) + { + handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + handler->SetSentErrorMessage(true); + return false; + } + + char* triggeredStr = strtok(NULL, " "); + if (triggeredStr) + { + int l = strlen(triggeredStr); + if (strncmp(triggeredStr, "triggered", l) != 0) + return false; + } + + bool triggered = (triggeredStr != NULL); + + caster->CastSpell(caster->getVictim(), spellId, triggered); + + return true; + } + + static bool HandleCastDestCommand(ChatHandler* handler, char const* args) + { + Unit* caster = handler->getSelectedUnit(); + if (!caster) + { + handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) + { + handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + handler->SetSentErrorMessage(true); + return false; + } + + char* posX = strtok(NULL, " "); + char* posY = strtok(NULL, " "); + char* posZ = strtok(NULL, " "); + + if (!posX || !posY || !posZ) + return false; + + float x = float(atof(posX)); + float y = float(atof(posY)); + float z = float(atof(posZ)); + + char* triggeredStr = strtok(NULL, " "); + if (triggeredStr) + { + int l = strlen(triggeredStr); + if (strncmp(triggeredStr, "triggered", l) != 0) + return false; + } + + bool triggered = (triggeredStr != NULL); + + caster->CastSpell(x, y, z, spellId, triggered); + + return true; + } +}; + +void AddSC_cast_commandscript() +{ + new cast_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp new file mode 100644 index 00000000000..e6d397ead2b --- /dev/null +++ b/src/server/scripts/Commands/cs_character.cpp @@ -0,0 +1,679 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* ScriptData +Name: character_commandscript +%Complete: 100 +Comment: All character related commands +Category: commandscripts +EndScriptData */ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "AccountMgr.h" +#include "ObjectMgr.h" + +class character_commandscript : public CommandScript +{ +public: + character_commandscript() : CommandScript("character_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand characterDeletedCommandTable[] = + { + { "delete", SEC_CONSOLE, true, &HandleCharacterDeletedDeleteCommand, "", NULL }, + { "list", SEC_ADMINISTRATOR, true, &HandleCharacterDeletedListCommand, "", NULL }, + { "restore", SEC_ADMINISTRATOR, true, &HandleCharacterDeletedRestoreCommand, "", NULL }, + { "old", SEC_CONSOLE, true, &HandleCharacterDeletedOldCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand characterCommandTable[] = + { + { "customize", SEC_GAMEMASTER, true, &HandleCharacterCustomizeCommand, "", NULL }, + { "changefaction", SEC_GAMEMASTER, true, &HandleCharacterChangeFactionCommand, "", NULL }, + { "changerace", SEC_GAMEMASTER, true, &HandleCharacterChangeRaceCommand, "", NULL }, + { "deleted", SEC_GAMEMASTER, true, NULL, "", characterDeletedCommandTable}, + { "erase", SEC_CONSOLE, true, &HandleCharacterEraseCommand, "", NULL }, + { "level", SEC_ADMINISTRATOR, true, &HandleCharacterLevelCommand, "", NULL }, + { "rename", SEC_GAMEMASTER, true, &HandleCharacterRenameCommand, "", NULL }, + { "reputation", SEC_GAMEMASTER, true, &HandleCharacterReputationCommand, "", NULL }, + { "titles", SEC_GAMEMASTER, true, &HandleCharacterTitlesCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "character", SEC_GAMEMASTER, true, NULL, "", characterCommandTable}, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + // Stores informations about a deleted character + struct DeletedInfo + { + uint32 lowGuid; ///< the low GUID from the character + std::string name; ///< the character name + uint32 accountId; ///< the account id + std::string accountName; ///< the account name + time_t deleteDate; ///< the date at which the character has been deleted + }; + + typedef std::list<DeletedInfo> DeletedInfoList; + + /** + * Collects all GUIDs (and related info) from deleted characters which are still in the database. + * + * @param foundList a reference to an std::list which will be filled with info data + * @param searchString the search string which either contains a player GUID or a part fo the character-name + * @return returns false if there was a problem while selecting the characters (e.g. player name not normalizeable) + */ + static bool GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString) + { + PreparedQueryResult result; + PreparedStatement* stmt; + if (!searchString.empty()) + { + // search by GUID + if (isNumeric(searchString.c_str())) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID); + stmt->setUInt32(0, uint32(atoi(searchString.c_str()))); + result = CharacterDatabase.Query(stmt); + } + // search by name + else + { + if (!normalizePlayerName(searchString)) + return false; + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME); + stmt->setString(0, searchString); + result = CharacterDatabase.Query(stmt); + } + } + else + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO); + result = CharacterDatabase.Query(stmt); + } + + if (result) + { + do + { + Field* fields = result->Fetch(); + + DeletedInfo info; + + info.lowGuid = fields[0].GetUInt32(); + info.name = fields[1].GetString(); + info.accountId = fields[2].GetUInt32(); + + // account name will be empty for not existed account + AccountMgr::GetName(info.accountId, info.accountName); + info.deleteDate = time_t(fields[3].GetUInt32()); + foundList.push_back(info); + } + while (result->NextRow()); + } + + return true; + } + + /** + * Shows all deleted characters which matches the given search string, expected non empty list + * + * @see HandleCharacterDeletedListCommand + * @see HandleCharacterDeletedRestoreCommand + * @see HandleCharacterDeletedDeleteCommand + * @see DeletedInfoList + * + * @param foundList contains a list with all found deleted characters + */ + static void HandleCharacterDeletedListHelper(DeletedInfoList const& foundList, ChatHandler* handler) + { + if (!handler->GetSession()) + { + handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); + handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_HEADER); + handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); + } + + for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) + { + std::string dateStr = TimeToTimestampStr(itr->deleteDate); + + if (!handler->GetSession()) + handler->PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE, + itr->lowGuid, itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(), + itr->accountId, dateStr.c_str()); + else + handler->PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CHAT, + itr->lowGuid, itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(), + itr->accountId, dateStr.c_str()); + } + + if (!handler->GetSession()) + handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); + } + + /** + * Restore a previously deleted character + * + * @see HandleCharacterDeletedListHelper + * @see HandleCharacterDeletedRestoreCommand + * @see HandleCharacterDeletedDeleteCommand + * @see DeletedInfoList + * + * @param delInfo the informations about the character which will be restored + */ + static void HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo, ChatHandler* handler) + { + if (delInfo.accountName.empty()) // account not exist + { + handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.lowGuid, delInfo.accountId); + return; + } + + // check character count + uint32 charcount = AccountMgr::GetCharactersCount(delInfo.accountId); + if (charcount >= 10) + { + handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.lowGuid, delInfo.accountId); + return; + } + + if (sObjectMgr->GetPlayerGUIDByName(delInfo.name)) + { + handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.lowGuid, delInfo.accountId); + return; + } + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_RESTORE_DELETE_INFO); + stmt->setString(0, delInfo.name); + stmt->setUInt32(1, delInfo.accountId); + stmt->setUInt32(2, delInfo.lowGuid); + CharacterDatabase.Execute(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA); + stmt->setUInt32(0, delInfo.lowGuid); + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) + sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8()); + } + + static bool HandleCharacterTitlesCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* target; + if (!handler->extractPlayerTarget((char*)args, &target)) + return false; + + LocaleConstant loc = handler->GetSessionDbcLocale(); + char const* targetName = target->GetName(); + char const* knownStr = handler->GetTrinityString(LANG_KNOWN); + + // Search in CharTitles.dbc + for (uint32 id = 0; id < sCharTitlesStore.GetNumRows(); id++) + { + CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id); + + if (titleInfo && target->HasTitle(titleInfo)) + { + std::string name = titleInfo->name; + if (name.empty()) + continue; + + char const* activeStr = target && target->GetUInt32Value(PLAYER_CHOSEN_TITLE) == titleInfo->bit_index + ? handler->GetTrinityString(LANG_ACTIVE) + : ""; + + char titleNameStr[80]; + snprintf(titleNameStr, 80, name.c_str(), targetName); + + // send title in "id (idx:idx) - [namedlink locale]" format + if (handler->GetSession()) + handler->PSendSysMessage(LANG_TITLE_LIST_CHAT, id, titleInfo->bit_index, id, titleNameStr, localeNames[loc], knownStr, activeStr); + else + handler->PSendSysMessage(LANG_TITLE_LIST_CONSOLE, id, titleInfo->bit_index, name.c_str(), localeNames[loc], knownStr, activeStr); + } + } + + return true; + } + + //rename characters + static bool HandleCharacterRenameCommand(ChatHandler* handler, char const* args) + { + Player* target; + uint64 targetGuid; + std::string targetName; + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + return false; + + if (target) + { + // check online security + if (handler->HasLowerSecurity(target, 0)) + return false; + + handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_RENAME); + } + else + { + // check offline security + if (handler->HasLowerSecurity(NULL, targetGuid)) + return false; + + std::string oldNameLink = handler->playerLink(targetName); + handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + CharacterDatabase.Execute(stmt); + } + + return true; + } + + static bool HandleCharacterLevelCommand(ChatHandler* handler, char const* args) + { + char* nameStr; + char* levelStr; + handler->extractOptFirstArg((char*)args, &nameStr, &levelStr); + if (!levelStr) + return false; + + // exception opt second arg: .character level $name + if (isalpha(levelStr[0])) + { + nameStr = levelStr; + levelStr = NULL; // current level will used + } + + Player* target; + uint64 targetGuid; + std::string targetName; + if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &targetName)) + return false; + + int32 oldlevel = target ? target->getLevel() : Player::GetLevelFromDB(targetGuid); + int32 newlevel = levelStr ? atoi(levelStr) : oldlevel; + + if (newlevel < 1) + return false; // invalid level + + if (newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; + + handler->HandleCharacterLevel(target, targetGuid, oldlevel, newlevel); + if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target) // including player == NULL + { + std::string nameLink = handler->playerLink(targetName); + handler->PSendSysMessage(LANG_YOU_CHANGE_LVL, nameLink.c_str(), newlevel); + } + + return true; + } + + // customize characters + static bool HandleCharacterCustomizeCommand(ChatHandler* handler, char const* args) + { + Player* target; + uint64 targetGuid; + std::string targetName; + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + return false; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE)); + if (target) + { + handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); + stmt->setUInt32(1, target->GetGUIDLow()); + } + else + { + std::string oldNameLink = handler->playerLink(targetName); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + } + CharacterDatabase.Execute(stmt); + + return true; + } + + static bool HandleCharacterChangeFactionCommand(ChatHandler* handler, char const* args) + { + Player* target; + uint64 targetGuid; + std::string targetName; + + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + return false; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_CHANGE_FACTION)); + if (target) + { + handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION); + stmt->setUInt32(1, target->GetGUIDLow()); + } + else + { + std::string oldNameLink = handler->playerLink(targetName); + handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + } + CharacterDatabase.Execute(stmt); + + return true; + } + + static bool HandleCharacterChangeRaceCommand(ChatHandler* handler, char const* args) + { + Player* target; + uint64 targetGuid; + std::string targetName; + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + return false; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_CHANGE_RACE)); + if (target) + { + // TODO : add text into database + handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE); + stmt->setUInt32(1, target->GetGUIDLow()); + } + else + { + std::string oldNameLink = handler->playerLink(targetName); + // TODO : add text into database + handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGuid)); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + } + CharacterDatabase.Execute(stmt); + + return true; + } + + static bool HandleCharacterReputationCommand(ChatHandler* handler, char const* args) + { + Player* target; + if (!handler->extractPlayerTarget((char*)args, &target)) + return false; + + LocaleConstant loc = handler->GetSessionDbcLocale(); + + FactionStateList const& targetFSL = target->GetReputationMgr().GetStateList(); + for (FactionStateList::const_iterator itr = targetFSL.begin(); itr != targetFSL.end(); ++itr) + { + FactionState const& faction = itr->second; + FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction.ID); + char const* factionName = factionEntry ? factionEntry->name : "#Not found#"; + ReputationRank rank = target->GetReputationMgr().GetRank(factionEntry); + std::string rankName = handler->GetTrinityString(ReputationRankStrIndex[rank]); + std::ostringstream ss; + if (handler->GetSession()) + ss << faction.ID << " - |cffffffff|Hfaction:" << faction.ID << "|h[" << factionName << ' ' << localeNames[loc] << "]|h|r"; + else + ss << faction.ID << " - " << factionName << ' ' << localeNames[loc]; + + ss << ' ' << rankName << " (" << target->GetReputationMgr().GetReputation(factionEntry) << ')'; + + if (faction.Flags & FACTION_FLAG_VISIBLE) + ss << handler->GetTrinityString(LANG_FACTION_VISIBLE); + if (faction.Flags & FACTION_FLAG_AT_WAR) + ss << handler->GetTrinityString(LANG_FACTION_ATWAR); + if (faction.Flags & FACTION_FLAG_PEACE_FORCED) + ss << handler->GetTrinityString(LANG_FACTION_PEACE_FORCED); + if (faction.Flags & FACTION_FLAG_HIDDEN) + ss << handler->GetTrinityString(LANG_FACTION_HIDDEN); + if (faction.Flags & FACTION_FLAG_INVISIBLE_FORCED) + ss << handler->GetTrinityString(LANG_FACTION_INVISIBLE_FORCED); + if (faction.Flags & FACTION_FLAG_INACTIVE) + ss << handler->GetTrinityString(LANG_FACTION_INACTIVE); + + handler->SendSysMessage(ss.str().c_str()); + } + + return true; + } + + /** + * Handles the '.character deleted list' command, which shows all deleted characters which matches the given search string + * + * @see HandleCharacterDeletedListHelper + * @see HandleCharacterDeletedRestoreCommand + * @see HandleCharacterDeletedDeleteCommand + * @see DeletedInfoList + * + * @param args the search string which either contains a player GUID or a part fo the character-name + */ + static bool HandleCharacterDeletedListCommand(ChatHandler* handler, char const* args) + { + DeletedInfoList foundList; + if (!GetDeletedCharacterInfoList(foundList, args)) + return false; + + // if no characters have been found, output a warning + if (foundList.empty()) + { + handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); + return false; + } + + HandleCharacterDeletedListHelper(foundList, handler); + + return true; + } + + /** + * Handles the '.character deleted restore' command, which restores all deleted characters which matches the given search string + * + * The command automatically calls '.character deleted list' command with the search string to show all restored characters. + * + * @see HandleCharacterDeletedRestoreHelper + * @see HandleCharacterDeletedListCommand + * @see HandleCharacterDeletedDeleteCommand + * + * @param args the search string which either contains a player GUID or a part of the character-name + */ + static bool HandleCharacterDeletedRestoreCommand(ChatHandler* handler, char const* args) + { + // It is required to submit at least one argument + if (!*args) + return false; + + std::string searchString; + std::string newCharName; + uint32 newAccount = 0; + + // GCC by some strange reason fail build code without temporary variable + std::istringstream params(args); + params >> searchString >> newCharName >> newAccount; + + DeletedInfoList foundList; + if (!GetDeletedCharacterInfoList(foundList, searchString)) + return false; + + if (foundList.empty()) + { + handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); + return false; + } + + handler->SendSysMessage(LANG_CHARACTER_DELETED_RESTORE); + HandleCharacterDeletedListHelper(foundList, handler); + + if (newCharName.empty()) + { + // Drop not existed account cases + for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr) + HandleCharacterDeletedRestoreHelper(*itr, handler); + } + else if (foundList.size() == 1 && normalizePlayerName(newCharName)) + { + DeletedInfo delInfo = foundList.front(); + + // update name + delInfo.name = newCharName; + + // if new account provided update deleted info + if (newAccount && newAccount != delInfo.accountId) + { + delInfo.accountId = newAccount; + AccountMgr::GetName(newAccount, delInfo.accountName); + } + + HandleCharacterDeletedRestoreHelper(delInfo, handler); + } + else + handler->SendSysMessage(LANG_CHARACTER_DELETED_ERR_RENAME); + + return true; + } + + /** + * Handles the '.character deleted delete' command, which completely deletes all deleted characters which matches the given search string + * + * @see Player::GetDeletedCharacterGUIDs + * @see Player::DeleteFromDB + * @see HandleCharacterDeletedListCommand + * @see HandleCharacterDeletedRestoreCommand + * + * @param args the search string which either contains a player GUID or a part fo the character-name + */ + static bool HandleCharacterDeletedDeleteCommand(ChatHandler* handler, char const* args) + { + // It is required to submit at least one argument + if (!*args) + return false; + + DeletedInfoList foundList; + if (!GetDeletedCharacterInfoList(foundList, args)) + return false; + + if (foundList.empty()) + { + handler->SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); + return false; + } + + handler->SendSysMessage(LANG_CHARACTER_DELETED_DELETE); + HandleCharacterDeletedListHelper(foundList, handler); + + // Call the appropriate function to delete them (current account for deleted characters is 0) + for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) + Player::DeleteFromDB(itr->lowGuid, 0, false, true); + + return true; + } + + /** + * Handles the '.character deleted old' command, which completely deletes all deleted characters deleted with some days ago + * + * @see Player::DeleteOldCharacters + * @see Player::DeleteFromDB + * @see HandleCharacterDeletedDeleteCommand + * @see HandleCharacterDeletedListCommand + * @see HandleCharacterDeletedRestoreCommand + * + * @param args the search string which either contains a player GUID or a part fo the character-name + */ + static bool HandleCharacterDeletedOldCommand(ChatHandler* /*handler*/, char const* args) + { + int32 keepDays = sWorld->getIntConfig(CONFIG_CHARDELETE_KEEP_DAYS); + + char* daysStr = strtok((char*)args, " "); + if (daysStr) + { + if (!isNumeric(daysStr)) + return false; + + keepDays = atoi(daysStr); + if (keepDays < 0) + return false; + } + // config option value 0 -> disabled and can't be used + else if (keepDays <= 0) + return false; + + Player::DeleteOldCharacters(uint32(keepDays)); + + return true; + } + + static bool HandleCharacterEraseCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + char* characterName_str = strtok((char*)args, " "); + if (!characterName_str) + return false; + + std::string characterName = characterName_str; + if (!normalizePlayerName(characterName)) + return false; + + uint64 characterGuid; + uint32 accountId; + + Player* player = sObjectAccessor->FindPlayerByName(characterName.c_str()); + if (player) + { + characterGuid = player->GetGUID(); + accountId = player->GetSession()->GetAccountId(); + player->GetSession()->KickPlayer(); + } + else + { + characterGuid = sObjectMgr->GetPlayerGUIDByName(characterName); + if (!characterGuid) + { + handler->PSendSysMessage(LANG_NO_PLAYER, characterName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + accountId = sObjectMgr->GetPlayerAccountIdByGUID(characterGuid); + } + + std::string accountName; + AccountMgr::GetName(accountId, accountName); + + Player::DeleteFromDB(characterGuid, accountId, true, true); + handler->PSendSysMessage(LANG_CHARACTER_DELETED, characterName.c_str(), GUID_LOPART(characterGuid), accountName.c_str(), accountId); + + return true; + } +}; + +void AddSC_character_commandscript() +{ + new character_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_instance.cpp b/src/server/scripts/Commands/cs_instance.cpp new file mode 100644 index 00000000000..f51727af2ef --- /dev/null +++ b/src/server/scripts/Commands/cs_instance.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* ScriptData +Name: instance_commandscript +%Complete: 100 +Comment: All instance related commands +Category: commandscripts +EndScriptData */ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "Group.h" +#include "InstanceSaveMgr.h" +#include "InstanceScript.h" +#include "MapManager.h" + +class instance_commandscript : public CommandScript +{ +public: + instance_commandscript() : CommandScript("instance_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand instanceCommandTable[] = + { + { "listbinds", SEC_ADMINISTRATOR, false, &HandleInstanceListBindsCommand, "", NULL }, + { "unbind", SEC_ADMINISTRATOR, false, &HandleInstanceUnbindCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, true, &HandleInstanceStatsCommand, "", NULL }, + { "savedata", SEC_ADMINISTRATOR, false, &HandleInstanceSaveDataCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "instance", SEC_ADMINISTRATOR, true, NULL, "", instanceCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + + return commandTable; + } + + static std::string GetTimeString(uint64 time) + { + uint64 days = time / DAY, hours = (time % DAY) / HOUR, minute = (time % HOUR) / MINUTE; + std::ostringstream ss; + if (days) + ss << days << "d "; + if (hours) + ss << hours << "h "; + ss << minute << 'm'; + return ss.str(); + } + + static bool HandleInstanceListBindsCommand(ChatHandler* handler, char const* /*args*/) + { + Player* player = handler->getSelectedPlayer(); + if (!player) + player = handler->GetSession()->GetPlayer(); + + uint32 counter = 0; + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave* save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + handler->PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); + counter++; + } + } + handler->PSendSysMessage("player binds: %d", counter); + + counter = 0; + if (Group* group = player->GetGroup()) + { + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Group::BoundInstancesMap &binds = group->GetBoundInstances(Difficulty(i)); + for (Group::BoundInstancesMap::const_iterator itr = binds.begin(); itr != binds.end(); ++itr) + { + InstanceSave* save = itr->second.save; + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + handler->PSendSysMessage("map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); + counter++; + } + } + } + handler->PSendSysMessage("group binds: %d", counter); + + return true; + } + + static bool HandleInstanceUnbindCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* player = handler->getSelectedPlayer(); + if (!player) + player = handler->GetSession()->GetPlayer(); + + char* map = strtok((char*)args, " "); + char* pDiff = strtok(NULL, " "); + int8 diff = -1; + if (pDiff) + diff = atoi(pDiff); + uint16 counter = 0; + uint16 MapId = 0; + + if (strcmp(map, "all")) + { + MapId = uint16(atoi(map)); + if (!MapId) + return false; + } + + for (uint8 i = 0; i < MAX_DIFFICULTY; ++i) + { + Player::BoundInstancesMap &binds = player->GetBoundInstances(Difficulty(i)); + for (Player::BoundInstancesMap::iterator itr = binds.begin(); itr != binds.end();) + { + InstanceSave* save = itr->second.save; + if (itr->first != player->GetMapId() && (!MapId || MapId == itr->first) && (diff == -1 || diff == save->GetDifficulty())) + { + std::string timeleft = GetTimeString(save->GetResetTime() - time(NULL)); + handler->PSendSysMessage("unbinding map: %d inst: %d perm: %s diff: %d canReset: %s TTR: %s", itr->first, save->GetInstanceId(), itr->second.perm ? "yes" : "no", save->GetDifficulty(), save->CanReset() ? "yes" : "no", timeleft.c_str()); + player->UnbindInstance(itr, Difficulty(i)); + counter++; + } + else + ++itr; + } + } + handler->PSendSysMessage("instances unbound: %d", counter); + + return true; + } + + static bool HandleInstanceStatsCommand(ChatHandler* handler, char const* /*args*/) + { + handler->PSendSysMessage("instances loaded: %d", sMapMgr->GetNumInstances()); + handler->PSendSysMessage("players in instances: %d", sMapMgr->GetNumPlayersInInstances()); + handler->PSendSysMessage("instance saves: %d", sInstanceSaveMgr->GetNumInstanceSaves()); + handler->PSendSysMessage("players bound: %d", sInstanceSaveMgr->GetNumBoundPlayersTotal()); + handler->PSendSysMessage("groups bound: %d", sInstanceSaveMgr->GetNumBoundGroupsTotal()); + + return true; + } + + static bool HandleInstanceSaveDataCommand(ChatHandler* handler, char const* /*args*/) + { + Player* player = handler->GetSession()->GetPlayer(); + Map* map = player->GetMap(); + if (!map->IsDungeon()) + { + handler->PSendSysMessage("Map is not a dungeon."); + handler->SetSentErrorMessage(true); + return false; + } + + if (!((InstanceMap*)map)->GetInstanceScript()) + { + handler->PSendSysMessage("Map has no instance data."); + handler->SetSentErrorMessage(true); + return false; + } + + ((InstanceMap*)map)->GetInstanceScript()->SaveToDB(); + + return true; + } +}; + +void AddSC_instance_commandscript() +{ + new instance_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp new file mode 100644 index 00000000000..8dd7f8e2cde --- /dev/null +++ b/src/server/scripts/Commands/cs_list.cpp @@ -0,0 +1,469 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* ScriptData +Name: list_commandscript +%Complete: 100 +Comment: All list related commands +Category: commandscripts +EndScriptData */ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "SpellAuraEffects.h" +#include "ObjectAccessor.h" +#include "ObjectMgr.h" + +class list_commandscript : public CommandScript +{ +public: + list_commandscript() : CommandScript("list_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand listCommandTable[] = + { + { "creature", SEC_ADMINISTRATOR, true, &HandleListCreatureCommand, "", NULL }, + { "item", SEC_ADMINISTRATOR, true, &HandleListItemCommand, "", NULL }, + { "object", SEC_ADMINISTRATOR, true, &HandleListObjectCommand, "", NULL }, + { "auras", SEC_ADMINISTRATOR, false, &HandleListAurasCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + static ChatCommand commandTable[] = + { + { "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + static bool HandleListCreatureCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hcreature_entry:creature_id|h[name]|h|r + char* id = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); + if (!id) + return false; + + uint32 creatureId = atol(id); + if (!creatureId) + { + handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, creatureId); + handler->SetSentErrorMessage(true); + return false; + } + + CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creatureId); + if (!cInfo) + { + handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, creatureId); + handler->SetSentErrorMessage(true); + return false; + } + + char* countStr = strtok(NULL, " "); + uint32 count = countStr ? atol(countStr) : 10; + + if (count < 0) + return false; + + QueryResult result; + + uint32 creatureCount = 0; + result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM creature WHERE id='%u'", creatureId); + if (result) + creatureCount = (*result)[0].GetUInt64(); + + if (handler->GetSession()) + { + Player* player = handler->GetSession()->GetPlayer(); + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM creature WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), creatureId, count); + } + else + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map FROM creature WHERE id = '%u' LIMIT %u", + creatureId, count); + + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + uint16 mapId = fields[4].GetUInt16(); + + if (handler->GetSession()) + handler->PSendSysMessage(LANG_CREATURE_LIST_CHAT, guid, guid, cInfo->Name.c_str(), x, y, z, mapId); + else + handler->PSendSysMessage(LANG_CREATURE_LIST_CONSOLE, guid, cInfo->Name.c_str(), x, y, z, mapId); + } + while (result->NextRow()); + } + + handler->PSendSysMessage(LANG_COMMAND_LISTCREATUREMESSAGE, creatureId, creatureCount); + + return true; + } + + static bool HandleListItemCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + char* id = handler->extractKeyFromLink((char*)args, "Hitem"); + if (!id) + return false; + + uint32 itemId = atol(id); + if (!itemId) + { + handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); + handler->SetSentErrorMessage(true); + return false; + } + + ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemId); + if (!itemTemplate) + { + handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); + handler->SetSentErrorMessage(true); + return false; + } + + char* countStr = strtok(NULL, " "); + uint32 count = countStr ? atol(countStr) : 10; + + if (count < 0) + return false; + + PreparedQueryResult result; + + // inventory case + uint32 inventoryCount = 0; + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM); + stmt->setUInt32(0, itemId); + result = CharacterDatabase.Query(stmt); + + if (result) + inventoryCount = (*result)[0].GetUInt64(); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY); + stmt->setUInt32(0, itemId); + stmt->setUInt32(1, count); + result = CharacterDatabase.Query(stmt); + + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 itemGuid = fields[0].GetUInt32(); + uint32 itemBag = fields[1].GetUInt32(); + uint8 itemSlot = fields[2].GetUInt8(); + uint32 ownerGuid = fields[3].GetUInt32(); + uint32 ownerAccountId = fields[4].GetUInt32(); + std::string ownerName = fields[5].GetString(); + + char const* itemPos = 0; + if (Player::IsEquipmentPos(itemBag, itemSlot)) + itemPos = "[equipped]"; + else if (Player::IsInventoryPos(itemBag, itemSlot)) + itemPos = "[in inventory]"; + else if (Player::IsBankPos(itemBag, itemSlot)) + itemPos = "[in bank]"; + else + itemPos = ""; + + handler->PSendSysMessage(LANG_ITEMLIST_SLOT, itemGuid, ownerName.c_str(), ownerGuid, ownerAccountId, itemPos); + } + while (result->NextRow()); + + uint32 resultCount = uint32(result->GetRowCount()); + + if (count > resultCount) + count -= resultCount; + else if (count) + count = 0; + } + + // mail case + uint32 mailCount = 0; + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT_ITEM); + stmt->setUInt32(0, itemId); + result = CharacterDatabase.Query(stmt); + + if (result) + mailCount = (*result)[0].GetUInt64(); + + if (count > 0) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_ITEMS_BY_ENTRY); + stmt->setUInt32(0, itemId); + stmt->setUInt32(1, count); + result = CharacterDatabase.Query(stmt); + } + else + result = PreparedQueryResult(NULL); + + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 itemGuid = fields[0].GetUInt32(); + uint32 itemSender = fields[1].GetUInt32(); + uint32 itemReceiver = fields[2].GetUInt32(); + uint32 itemSenderAccountId = fields[3].GetUInt32(); + std::string itemSenderName = fields[4].GetString(); + uint32 itemReceiverAccount = fields[5].GetUInt32(); + std::string itemReceiverName = fields[6].GetString(); + + char const* itemPos = "[in mail]"; + + handler->PSendSysMessage(LANG_ITEMLIST_MAIL, itemGuid, itemSenderName.c_str(), itemSender, itemSenderAccountId, itemReceiverName.c_str(), itemReceiver, itemReceiverAccount, itemPos); + } + while (result->NextRow()); + + uint32 resultCount = uint32(result->GetRowCount()); + + if (count > resultCount) + count -= resultCount; + else if (count) + count = 0; + } + + // auction case + uint32 auctionCount = 0; + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM); + stmt->setUInt32(0, itemId); + result = CharacterDatabase.Query(stmt); + + if (result) + auctionCount = (*result)[0].GetUInt64(); + + if (count > 0) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTIONHOUSE_ITEM_BY_ENTRY); + stmt->setUInt32(0, itemId); + stmt->setUInt32(1, count); + result = CharacterDatabase.Query(stmt); + } + else + result = PreparedQueryResult(NULL); + + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 itemGuid = fields[0].GetUInt32(); + uint32 owner = fields[1].GetUInt32(); + uint32 ownerAccountId = fields[2].GetUInt32(); + std::string ownerName = fields[3].GetString(); + + char const* itemPos = "[in auction]"; + + handler->PSendSysMessage(LANG_ITEMLIST_AUCTION, itemGuid, ownerName.c_str(), owner, ownerAccountId, itemPos); + } + while (result->NextRow()); + } + + // guild bank case + uint32 guildCount = 0; + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM); + stmt->setUInt32(0, itemId); + result = CharacterDatabase.Query(stmt); + + if (result) + guildCount = (*result)[0].GetUInt64(); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_BANK_ITEM_BY_ENTRY); + stmt->setUInt32(0, itemId); + stmt->setUInt32(1, count); + result = CharacterDatabase.Query(stmt); + + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 itemGuid = fields[0].GetUInt32(); + uint32 guildGuid = fields[1].GetUInt32(); + std::string guildName = fields[2].GetString(); + + char const* itemPos = "[in guild bank]"; + + handler->PSendSysMessage(LANG_ITEMLIST_GUILD, itemGuid, guildName.c_str(), guildGuid, itemPos); + } + while (result->NextRow()); + + uint32 resultCount = uint32(result->GetRowCount()); + + if (count > resultCount) + count -= resultCount; + else if (count) + count = 0; + } + + if (inventoryCount + mailCount + auctionCount + guildCount == 0) + { + handler->SendSysMessage(LANG_COMMAND_NOITEMFOUND); + handler->SetSentErrorMessage(true); + return false; + } + + handler->PSendSysMessage(LANG_COMMAND_LISTITEMMESSAGE, itemId, inventoryCount + mailCount + auctionCount + guildCount, inventoryCount, mailCount, auctionCount, guildCount); + + return true; + } + + static bool HandleListObjectCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + // number or [name] Shift-click form |color|Hgameobject_entry:go_id|h[name]|h|r + char* id = handler->extractKeyFromLink((char*)args, "Hgameobject_entry"); + if (!id) + return false; + + uint32 gameObjectId = atol(id); + if (!gameObjectId) + { + handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, gameObjectId); + handler->SetSentErrorMessage(true); + return false; + } + + GameObjectTemplate const* gInfo = sObjectMgr->GetGameObjectTemplate(gameObjectId); + if (!gInfo) + { + handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, gameObjectId); + handler->SetSentErrorMessage(true); + return false; + } + + char* countStr = strtok(NULL, " "); + uint32 count = countStr ? atol(countStr) : 10; + + if (count < 0) + return false; + + QueryResult result; + + uint32 objectCount = 0; + result = WorldDatabase.PQuery("SELECT COUNT(guid) FROM gameobject WHERE id='%u'", gameObjectId); + if (result) + objectCount = (*result)[0].GetUInt64(); + + if (handler->GetSession()) + { + Player* player = handler->GetSession()->GetPlayer(); + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, id, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE id = '%u' ORDER BY order_ ASC LIMIT %u", + player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), gameObjectId, count); + } + else + result = WorldDatabase.PQuery("SELECT guid, position_x, position_y, position_z, map, id FROM gameobject WHERE id = '%u' LIMIT %u", + gameObjectId, count); + + if (result) + { + do + { + Field* fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + float x = fields[1].GetFloat(); + float y = fields[2].GetFloat(); + float z = fields[3].GetFloat(); + uint16 mapId = fields[4].GetUInt16(); + uint32 entry = fields[5].GetUInt32(); + + if (handler->GetSession()) + handler->PSendSysMessage(LANG_GO_LIST_CHAT, guid, entry, guid, gInfo->name.c_str(), x, y, z, mapId); + else + handler->PSendSysMessage(LANG_GO_LIST_CONSOLE, guid, gInfo->name.c_str(), x, y, z, mapId); + } + while (result->NextRow()); + } + + handler->PSendSysMessage(LANG_COMMAND_LISTOBJMESSAGE, gameObjectId, objectCount); + + return true; + } + + static bool HandleListAurasCommand(ChatHandler* handler, char const* /*args*/) + { + Unit* unit = handler->getSelectedUnit(); + if (!unit) + { + handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + char const* talentStr = handler->GetTrinityString(LANG_TALENT); + char const* passiveStr = handler->GetTrinityString(LANG_PASSIVE); + + Unit::AuraApplicationMap const& auras = unit->GetAppliedAuras(); + handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, auras.size()); + for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; + + AuraApplication const* aurApp = itr->second; + Aura const* aura = aurApp->GetBase(); + char const* name = aura->GetSpellInfo()->SpellName; + + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r"; + + handler->PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), (handler->GetSession() ? ss_name.str().c_str() : name), + aurApp->GetEffectMask(), aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), + aura->GetDuration(), aura->GetMaxDuration(), (aura->IsPassive() ? passiveStr : ""), + (talent ? talentStr : ""), IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature", + GUID_LOPART(aura->GetCasterGUID())); + } + + for (uint16 i = 0; i < TOTAL_AURAS; ++i) + { + Unit::AuraEffectList const& auraList = unit->GetAuraEffectsByType(AuraType(i)); + if (auraList.empty()) + continue; + + handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, auraList.size(), i); + + for (Unit::AuraEffectList::const_iterator itr = auraList.begin(); itr != auraList.end(); ++itr) + handler->PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), (*itr)->GetAmount()); + } + + return true; + } +}; + +void AddSC_list_commandscript() +{ + new list_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 2deac95d287..4aa61bbc297 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -135,15 +135,14 @@ public: else
handler->PSendSysMessage("no VMAP available for area info");
- /*handler->PSendSysMessage(LANG_MAP_POSITION,
- object->GetMapId(), (mapEntry ? mapEntry->name[handler->GetSessionDbcLocale()] : "<unknown>"),
- zoneId, (zoneEntry ? zoneEntry->area_name[handler->GetSessionDbcLocale()] : "<unknown>"),
- areaId, (areaEntry ? areaEntry->area_name[handler->GetSessionDbcLocale()] : "<unknown>"),
+ handler->PSendSysMessage(LANG_MAP_POSITION,
+ object->GetMapId(), (mapEntry ? mapEntry->name : "<unknown>"),
+ zoneId, (zoneEntry ? zoneEntry->area_name : "<unknown>"),
+ areaId, (areaEntry ? areaEntry->area_name : "<unknown>"),
object->GetPhaseMask(),
object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation(),
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), object->GetInstanceId(),
zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap);
- */
LiquidData liquidStatus;
ZLiquidStatus status = map->getLiquidStatus(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus);
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 0de3637586c..57d13fd2fa1 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -64,15 +64,14 @@ public: { "standstate", SEC_GAMEMASTER, false, &HandleModifyStandStateCommand, "", NULL }, { "phase", SEC_ADMINISTRATOR, false, &HandleModifyPhaseCommand, "", NULL }, { "gender", SEC_GAMEMASTER, false, &HandleModifyGenderCommand, "", NULL }, - { "collision", SEC_GAMEMASTER, false, &HandleModifyCollisionCommand, "", NULL }, - { "speed", SEC_MODERATOR, false, NULL, "", modifyspeedCommandTable }, + { "speed", SEC_MODERATOR, false, NULL, "", modifyspeedCommandTable }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { { "morph", SEC_GAMEMASTER, false, &HandleModifyMorphCommand, "", NULL }, { "demorph", SEC_GAMEMASTER, false, &HandleDeMorphCommand, "", NULL }, - { "modify", SEC_MODERATOR, false, NULL, "", modifyCommandTable }, + { "modify", SEC_MODERATOR, false, NULL, "", modifyCommandTable }, { NULL, 0, false, NULL, "", NULL } }; return commandTable; @@ -1391,7 +1390,7 @@ public: if (!target) target = handler->GetSession()->GetPlayer(); - // check online security + // check online security else if (target->GetTypeId() == TYPEID_PLAYER && handler->HasLowerSecurity(target->ToPlayer(), 0)) return false; @@ -1399,88 +1398,6 @@ public: return true; } - - static bool HandleModifyCollisionCommand(ChatHandler* handler, const char* args) - { - if (!*args) - return false; - - Player* target = handler->getSelectedPlayer(); - - if (!target) - { - handler->PSendSysMessage(LANG_PLAYER_NOT_FOUND); - handler->SetSentErrorMessage(true); - return false; - } - - std::string param = (char*)args; - - if (param == "on") - { - // enable collision - WorldPacket data; - uint64 guid = target->GetGUID(); - uint8* bytes = (uint8*)&guid; - - data.Initialize(SMSG_MOVE_SPLINE_ENABLE_COLLISION, 1 + 8); - data.WriteByteMask(bytes[7]); - data.WriteByteMask(bytes[5]); - data.WriteByteMask(bytes[4]); - data.WriteByteMask(bytes[0]); - data.WriteByteMask(bytes[1]); - data.WriteByteMask(bytes[6]); - data.WriteByteMask(bytes[2]); - data.WriteByteMask(bytes[3]); - - data.WriteByteSeq(bytes[6]); - data.WriteByteSeq(bytes[3]); - data.WriteByteSeq(bytes[2]); - data.WriteByteSeq(bytes[7]); - data.WriteByteSeq(bytes[4]); - data.WriteByteSeq(bytes[1]); - data.WriteByteSeq(bytes[5]); - data.WriteByteSeq(bytes[0]); - - target->SendMessageToSet(&data, true); - handler->SendSysMessage("Enabled Collision"); - return true; - } - - if (param == "off") - { - // disable collision - WorldPacket data; - uint64 guid = target->GetGUID(); - uint8* bytes = (uint8*)&guid; - - data.Initialize(SMSG_MOVE_SPLINE_DISABLE_COLLISION, 1 + 8); - data.WriteByteMask(bytes[4]); - data.WriteByteMask(bytes[7]); - data.WriteByteMask(bytes[5]); - data.WriteByteMask(bytes[3]); - data.WriteByteMask(bytes[2]); - data.WriteByteMask(bytes[1]); - data.WriteByteMask(bytes[6]); - data.WriteByteMask(bytes[0]); - - data.WriteByteSeq(bytes[6]); - data.WriteByteSeq(bytes[0]); - data.WriteByteSeq(bytes[5]); - data.WriteByteSeq(bytes[4]); - data.WriteByteSeq(bytes[7]); - data.WriteByteSeq(bytes[3]); - data.WriteByteSeq(bytes[1]); - data.WriteByteSeq(bytes[2]); - - target->SendMessageToSet(&data, true); - handler->SendSysMessage("Disabled Collision"); - return true; - } - - return false; - } - }; void AddSC_modify_commandscript() diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp new file mode 100644 index 00000000000..a8294dc9ddb --- /dev/null +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* ScriptData +Name: reset_commandscript +%Complete: 100 +Comment: All reset related commands +Category: commandscripts +EndScriptData */ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "ObjectAccessor.h" + +class reset_commandscript : public CommandScript +{ +public: + reset_commandscript() : CommandScript("reset_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand resetCommandTable[] = + { + { "achievements", SEC_ADMINISTRATOR, true, &HandleResetAchievementsCommand, "", NULL }, + { "honor", SEC_ADMINISTRATOR, true, &HandleResetHonorCommand, "", NULL }, + { "level", SEC_ADMINISTRATOR, true, &HandleResetLevelCommand, "", NULL }, + { "spells", SEC_ADMINISTRATOR, true, &HandleResetSpellsCommand, "", NULL }, + { "stats", SEC_ADMINISTRATOR, true, &HandleResetStatsCommand, "", NULL }, + { "talents", SEC_ADMINISTRATOR, true, &HandleResetTalentsCommand, "", NULL }, + { "all", SEC_ADMINISTRATOR, true, &HandleResetAllCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + static ChatCommand commandTable[] = + { + { "reset", SEC_ADMINISTRATOR, true, NULL, "", resetCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + static bool HandleResetAchievementsCommand(ChatHandler* handler, char const* args) + { + Player* target; + uint64 targetGuid; + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid)) + return false; + + if (target) + target->GetAchievementMgr().Reset(); + else + AchievementMgr::DeleteFromDB(GUID_LOPART(targetGuid)); + + return true; + } + + static bool HandleResetHonorCommand(ChatHandler* handler, char const* args) + { + Player* target; + if (!handler->extractPlayerTarget((char*)args, &target)) + return false; + + target->SetUInt32Value(PLAYER_FIELD_KILLS, 0); + target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0); + target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); + + return true; + } + + static bool HandleResetStatsOrLevelHelper(Player* player) + { + ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(player->getClass()); + if (!classEntry) + { + sLog->outError("Class %u not found in DBC (Wrong DBC files?)", player->getClass()); + return false; + } + + uint8 powerType = classEntry->powerType; + + // reset m_form if no aura + if (!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) + player->SetShapeshiftForm(FORM_NONE); + + player->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + player->SetFloatValue(UNIT_FIELD_COMBATREACH, DEFAULT_COMBAT_REACH); + + player->setFactionForRace(player->getRace()); + + player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powerType << 24))); + + // reset only if player not in some form; + if (player->GetShapeshiftForm() == FORM_NONE) + player->InitDisplayIds(); + + player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); + + player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + //-1 is default value + player->SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); + + //player->SetUInt32Value(PLAYER_FIELD_BYTES, 0xEEE00000); + return true; + } + + static bool HandleResetLevelCommand(ChatHandler* handler, char const* args) + { + Player* target; + if (!handler->extractPlayerTarget((char*)args, &target)) + return false; + + if (!HandleResetStatsOrLevelHelper(target)) + return false; + + uint8 oldLevel = target->getLevel(); + + // set starting level + uint32 startLevel = target->getClass() != CLASS_DEATH_KNIGHT + ? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL) + : sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + + target->_ApplyAllLevelScaleItemMods(false); + target->SetLevel(startLevel); + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); + target->SetUInt32Value(PLAYER_XP, 0); + + target->_ApplyAllLevelScaleItemMods(true); + + // reset level for pet + if (Pet* pet = target->GetPet()) + pet->SynchronizeLevelWithOwner(); + + sScriptMgr->OnPlayerLevelChanged(target, oldLevel); + + return true; + } + + static bool HandleResetSpellsCommand(ChatHandler* handler, char const* args) + { + Player* target; + uint64 targetGuid; + std::string targetName; + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + return false; + + if (target) + { + target->resetSpells(/* bool myClassOnly */); + + ChatHandler(target).SendSysMessage(LANG_RESET_SPELLS); + if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target) + handler->PSendSysMessage(LANG_RESET_SPELLS_ONLINE, handler->GetNameLink(target).c_str()); + } + else + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_RESET_SPELLS)); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + CharacterDatabase.Execute(stmt); + + handler->PSendSysMessage(LANG_RESET_SPELLS_OFFLINE, targetName.c_str()); + } + + return true; + } + + static bool HandleResetStatsCommand(ChatHandler* handler, char const* args) + { + Player* target; + if (!handler->extractPlayerTarget((char*)args, &target)) + return false; + + if (!HandleResetStatsOrLevelHelper(target)) + return false; + + target->InitRunes(); + target->InitStatsForLevel(true); + target->InitTaxiNodesForLevel(); + target->InitGlyphsForLevel(); + target->InitTalentForLevel(); + + return true; + } + + static bool HandleResetTalentsCommand(ChatHandler* handler, char const* args) + { + Player* target; + uint64 targetGuid; + std::string targetName; + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + { + // Try reset talents as Hunter Pet + Creature* creature = handler->getSelectedCreature(); + if (!*args && creature && creature->isPet()) + { + Unit* owner = creature->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER && creature->ToPet()->IsPermanentPetFor(owner->ToPlayer())) + { + creature->ToPet()->resetTalents(); + owner->ToPlayer()->SendTalentsInfoData(true); + + ChatHandler(owner->ToPlayer()).SendSysMessage(LANG_RESET_PET_TALENTS); + if (!handler->GetSession() || handler->GetSession()->GetPlayer() != owner->ToPlayer()) + handler->PSendSysMessage(LANG_RESET_PET_TALENTS_ONLINE, handler->GetNameLink(owner->ToPlayer()).c_str()); + } + return true; + } + + handler->SendSysMessage(LANG_NO_CHAR_SELECTED); + handler->SetSentErrorMessage(true); + return false; + } + + if (target) + { + target->ResetTalents(true); + target->SendTalentsInfoData(false); + ChatHandler(target).SendSysMessage(LANG_RESET_TALENTS); + if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target) + handler->PSendSysMessage(LANG_RESET_TALENTS_ONLINE, handler->GetNameLink(target).c_str()); + + Pet* pet = target->GetPet(); + Pet::resetTalentsForAllPetsOf(target, pet); + if (pet) + target->SendTalentsInfoData(true); + return true; + } + else if (targetGuid) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_NONE | AT_LOGIN_RESET_PET_TALENTS)); + stmt->setUInt32(1, GUID_LOPART(targetGuid)); + CharacterDatabase.Execute(stmt); + + std::string nameLink = handler->playerLink(targetName); + handler->PSendSysMessage(LANG_RESET_TALENTS_OFFLINE, nameLink.c_str()); + return true; + } + + handler->SendSysMessage(LANG_NO_CHAR_SELECTED); + handler->SetSentErrorMessage(true); + return false; + } + + static bool HandleResetAllCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + std::string caseName = args; + + AtLoginFlags atLogin; + + // Command specially created as single command to prevent using short case names + if (caseName == "spells") + { + atLogin = AT_LOGIN_RESET_SPELLS; + sWorld->SendWorldText(LANG_RESETALL_SPELLS); + if (!handler->GetSession()) + handler->SendSysMessage(LANG_RESETALL_SPELLS); + } + else if (caseName == "talents") + { + atLogin = AtLoginFlags(AT_LOGIN_RESET_TALENTS | AT_LOGIN_RESET_PET_TALENTS); + sWorld->SendWorldText(LANG_RESETALL_TALENTS); + if (!handler->GetSession()) + handler->SendSysMessage(LANG_RESETALL_TALENTS); + } + else + { + handler->PSendSysMessage(LANG_RESETALL_UNKNOWN_CASE, args); + handler->SetSentErrorMessage(true); + return false; + } + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ALL_AT_LOGIN_FLAGS); + stmt->setUInt16(0, uint16(atLogin)); + CharacterDatabase.Execute(stmt); + + TRINITY_READ_GUARD(HashMapHolder<Player>::LockType, *HashMapHolder<Player>::GetLock()); + HashMapHolder<Player>::MapType const& plist = sObjectAccessor->GetPlayers(); + for (HashMapHolder<Player>::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) + itr->second->SetAtLoginFlag(atLogin); + + return true; + } +}; + +void AddSC_reset_commandscript() +{ + new reset_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp new file mode 100644 index 00000000000..8f10af5fe2a --- /dev/null +++ b/src/server/scripts/Commands/cs_server.cpp @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* ScriptData +Name: server_commandscript +%Complete: 100 +Comment: All server related commands +Category: commandscripts +EndScriptData */ + +#include "ScriptMgr.h" +#include "Chat.h" +#include "SystemConfig.h" +#include "Config.h" +#include "ObjectAccessor.h" + +class server_commandscript : public CommandScript +{ +public: + server_commandscript() : CommandScript("server_commandscript") { } + + ChatCommand* GetCommands() const + { + static ChatCommand serverIdleRestartCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , SEC_ADMINISTRATOR, true, &HandleServerIdleRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverIdleShutdownCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , SEC_ADMINISTRATOR, true, &HandleServerIdleShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverRestartCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , SEC_ADMINISTRATOR, true, &HandleServerRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverShutdownCommandTable[] = + { + { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , SEC_ADMINISTRATOR, true, &HandleServerShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverSetCommandTable[] = + { + { "difftime", SEC_CONSOLE, true, &HandleServerSetDiffTimeCommand, "", NULL }, + { "loglevel", SEC_CONSOLE, true, &HandleServerSetLogLevelCommand, "", NULL }, + { "logfilelevel", SEC_CONSOLE, true, &HandleServerSetLogFileLevelCommand, "", NULL }, + { "motd", SEC_ADMINISTRATOR, true, &HandleServerSetMotdCommand, "", NULL }, + { "closed", SEC_ADMINISTRATOR, true, &HandleServerSetClosedCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand serverCommandTable[] = + { + { "corpses", SEC_GAMEMASTER, true, &HandleServerCorpsesCommand, "", NULL }, + { "exit", SEC_CONSOLE, true, &HandleServerExitCommand, "", NULL }, + { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable }, + { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverIdleShutdownCommandTable }, + { "info", SEC_PLAYER, true, &HandleServerInfoCommand, "", NULL }, + { "motd", SEC_PLAYER, true, &HandleServerMotdCommand, "", NULL }, + { "plimit", SEC_ADMINISTRATOR, true, &HandleServerPLimitCommand, "", NULL }, + { "restart", SEC_ADMINISTRATOR, true, NULL, "", serverRestartCommandTable }, + { "shutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, + { "set", SEC_ADMINISTRATOR, true, NULL, "", serverSetCommandTable }, + { "togglequerylog", SEC_CONSOLE, true, &HandleServerToggleQueryLogging, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "server", SEC_ADMINISTRATOR, true, NULL, "", serverCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + // Triggering corpses expire check in world + static bool HandleServerCorpsesCommand(ChatHandler* /*handler*/, char const* /*args*/) + { + sObjectAccessor->RemoveOldCorpses(); + return true; + } + + static bool HandleServerInfoCommand(ChatHandler* handler, char const* /*args*/) + { + uint32 playersNum = sWorld->GetPlayerCount(); + uint32 maxPlayersNum = sWorld->GetMaxPlayerCount(); + uint32 activeClientsNum = sWorld->GetActiveSessionCount(); + uint32 queuedClientsNum = sWorld->GetQueuedSessionCount(); + uint32 maxActiveClientsNum = sWorld->GetMaxActiveSessionCount(); + uint32 maxQueuedClientsNum = sWorld->GetMaxQueuedSessionCount(); + std::string uptime = secsToTimeString(sWorld->GetUptime()); + uint32 updateTime = sWorld->GetUpdateTime(); + + handler->SendSysMessage(_FULLVERSION); + handler->PSendSysMessage(LANG_CONNECTED_PLAYERS, playersNum, maxPlayersNum); + handler->PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); + handler->PSendSysMessage(LANG_UPTIME, uptime.c_str()); + handler->PSendSysMessage(LANG_UPDATE_DIFF, updateTime); + // Can't use sWorld->ShutdownMsg here in case of console command + if (sWorld->IsShuttingDown()) + handler->PSendSysMessage(LANG_SHUTDOWN_TIMELEFT, secsToTimeString(sWorld->GetShutDownTimeLeft()).c_str()); + + return true; + } + // Display the 'Message of the day' for the realm + static bool HandleServerMotdCommand(ChatHandler* handler, char const* /*args*/) + { + handler->PSendSysMessage(LANG_MOTD_CURRENT, sWorld->GetMotd()); + return true; + } + + static bool HandleServerPLimitCommand(ChatHandler* handler, char const* args) + { + if (*args) + { + char* paramStr = strtok((char*)args, " "); + if (!paramStr) + return false; + + int32 limit = strlen(paramStr); + + if (strncmp(paramStr, "player", limit) == 0) + sWorld->SetPlayerSecurityLimit(SEC_PLAYER); + else if (strncmp(paramStr, "moderator", limit) == 0) + sWorld->SetPlayerSecurityLimit(SEC_MODERATOR); + else if (strncmp(paramStr, "gamemaster", limit) == 0) + sWorld->SetPlayerSecurityLimit(SEC_GAMEMASTER); + else if (strncmp(paramStr, "administrator", limit) == 0) + sWorld->SetPlayerSecurityLimit(SEC_ADMINISTRATOR); + else if (strncmp(paramStr, "reset", limit) == 0) + { + sWorld->SetPlayerAmountLimit(ConfigMgr::GetIntDefault("PlayerLimit", 100)); + sWorld->LoadDBAllowedSecurityLevel(); + } + else + { + int32 value = atoi(paramStr); + if (value < 0) + sWorld->SetPlayerSecurityLimit(AccountTypes(-value)); + else + sWorld->SetPlayerAmountLimit(uint32(value)); + } + } + + uint32 playerAmountLimit = sWorld->GetPlayerAmountLimit(); + AccountTypes allowedAccountType = sWorld->GetPlayerSecurityLimit(); + char const* secName = ""; + switch (allowedAccountType) + { + case SEC_PLAYER: + secName = "Player"; + break; + case SEC_MODERATOR: + secName = "Moderator"; + break; + case SEC_GAMEMASTER: + secName = "Gamemaster"; + break; + case SEC_ADMINISTRATOR: + secName = "Administrator"; + break; + default: + secName = "<unknown>"; + break; + } + handler->PSendSysMessage("Player limits: amount %u, min. security level %s.", playerAmountLimit, secName); + + return true; + } + + static bool HandleServerShutDownCancelCommand(ChatHandler* /*handler*/, char const* /*args*/) + { + sWorld->ShutdownCancel(); + + return true; + } + + static bool HandleServerShutDownCommand(ChatHandler* /*handler*/, char const* args) + { + if (!*args) + return false; + + char* timeStr = strtok((char*) args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + return false; + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitCode < 0 || exitCode > 125) + return false; + + sWorld->ShutdownServ(time, 0, exitCode); + } + else + sWorld->ShutdownServ(time, 0, SHUTDOWN_EXIT_CODE); + + return true; + } + + static bool HandleServerRestartCommand(ChatHandler* /*handler*/, char const* args) + { + if (!*args) + return false; + + char* timeStr = strtok((char*) args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + return false; + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitCode < 0 || exitCode > 125) + return false; + + sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART, exitCode); + } + else + sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); + + return true; + } + + static bool HandleServerIdleRestartCommand(ChatHandler* /*handler*/, char const* args) + { + if (!*args) + return false; + + char* timeStr = strtok((char*) args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + return false; + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitCode < 0 || exitCode > 125) + return false; + + sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART | SHUTDOWN_MASK_IDLE, exitCode); + } + else + sWorld->ShutdownServ(time, SHUTDOWN_MASK_RESTART | SHUTDOWN_MASK_IDLE, RESTART_EXIT_CODE); + return true; + } + + static bool HandleServerIdleShutDownCommand(ChatHandler* /*handler*/, char const* args) + { + if (!*args) + return false; + + char* timeStr = strtok((char*) args, " "); + char* exitCodeStr = strtok(NULL, ""); + + int32 time = atoi(timeStr); + + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((time == 0 && (timeStr[0] != '0' || timeStr[1] != '\0')) || time < 0) + return false; + + if (exitCodeStr) + { + int32 exitCode = atoi(exitCodeStr); + + // Handle atoi() errors + if (exitCode == 0 && (exitCodeStr[0] != '0' || exitCodeStr[1] != '\0')) + return false; + + // Exit code should be in range of 0-125, 126-255 is used + // in many shells for their own return codes and code > 255 + // is not supported in many others + if (exitCode < 0 || exitCode > 125) + return false; + + sWorld->ShutdownServ(time, SHUTDOWN_MASK_IDLE, exitCode); + } + else + sWorld->ShutdownServ(time, SHUTDOWN_MASK_IDLE, SHUTDOWN_EXIT_CODE); + return true; + } + + // Exit the realm + static bool HandleServerExitCommand(ChatHandler* handler, char const* /*args*/) + { + handler->SendSysMessage(LANG_COMMAND_EXIT); + World::StopNow(SHUTDOWN_EXIT_CODE); + return true; + } + + // Define the 'Message of the day' for the realm + static bool HandleServerSetMotdCommand(ChatHandler* handler, char const* args) + { + sWorld->SetMotd(args); + handler->PSendSysMessage(LANG_MOTD_NEW, args); + return true; + } + + // Set whether we accept new clients + static bool HandleServerSetClosedCommand(ChatHandler* handler, char const* args) + { + if (strncmp(args, "on", 3) == 0) + { + handler->SendSysMessage(LANG_WORLD_CLOSED); + sWorld->SetClosed(true); + return true; + } + else if (strncmp(args, "off", 4) == 0) + { + handler->SendSysMessage(LANG_WORLD_OPENED); + sWorld->SetClosed(false); + return true; + } + + handler->SendSysMessage(LANG_USE_BOL); + handler->SetSentErrorMessage(true); + return false; + } + + // Set the level of logging + static bool HandleServerSetLogFileLevelCommand(ChatHandler* /*handler*/, char const* args) + { + if (!*args) + return false; + + char* newLevel = strtok((char*)args, " "); + if (!newLevel) + return false; + + sLog->SetLogFileLevel(newLevel); + return true; + } + + // Set the level of logging + static bool HandleServerSetLogLevelCommand(ChatHandler* /*handler*/, char const* args) + { + if (!*args) + return false; + + char* newLevel = strtok((char*)args, " "); + if (!newLevel) + return false; + + sLog->SetLogLevel(newLevel); + return true; + } + + // set diff time record interval + static bool HandleServerSetDiffTimeCommand(ChatHandler* /*handler*/, char const* args) + { + if (!*args) + return false; + + char* newTimeStr = strtok((char*)args, " "); + if (!newTimeStr) + return false; + + int32 newTime = atoi(newTimeStr); + if (newTime < 0) + return false; + + sWorld->SetRecordDiffInterval(newTime); + printf("Record diff every %u ms\n", newTime); + + return true; + } + + // toggle sql driver query logging + static bool HandleServerToggleQueryLogging(ChatHandler* handler, char const* /*args*/) + { + sLog->SetSQLDriverQueryLogging(!sLog->GetSQLDriverQueryLogging()); + + if (sLog->GetSQLDriverQueryLogging()) + handler->PSendSysMessage(LANG_SQLDRIVER_QUERY_LOGGING_ENABLED); + else + handler->PSendSysMessage(LANG_SQLDRIVER_QUERY_LOGGING_DISABLED); + return true; + } +}; + +void AddSC_server_commandscript() +{ + new server_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index ca7c3af7fde..8f390d17cd4 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -97,15 +97,16 @@ public: if (!*args) return false; - std::string name = args; - - if (!sObjectMgr->DeleteGameTele(name)) + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r + GameTele const* tele = handler->extractGameTeleFromLink((char*)args); + if (!tele) { handler->SendSysMessage(LANG_COMMAND_TELE_NOTFOUND); handler->SetSentErrorMessage(true); return false; } - + std::string name = tele->name; + sObjectMgr->DeleteGameTele(name); handler->SendSysMessage(LANG_COMMAND_TP_DELETED); return true; } diff --git a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp index 0279f3e2834..015c13d1098 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockSpire/boss_pyroguard_emberseer.cpp @@ -64,7 +64,7 @@ public: void Reset() { - if(instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS) + if (instance->GetBossState(DATA_PYROGAURD_EMBERSEER) == IN_PROGRESS) OpenDoors(false); instance->SetBossState(DATA_PYROGAURD_EMBERSEER,NOT_STARTED); // respawn any dead Blackhand Incarcerators diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp index 63e753a18ba..676cd7be4f0 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp @@ -27,7 +27,11 @@ EndScriptData */ npc_shadowfang_prisoner EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "ScriptedEscortAI.h" #include "shadowfang_keep.h" @@ -193,8 +197,48 @@ public: }; +class spell_shadowfang_keep_haunting_spirits : public SpellScriptLoader +{ + public: + spell_shadowfang_keep_haunting_spirits() : SpellScriptLoader("spell_shadowfang_keep_haunting_spirits") { } + + class spell_shadowfang_keep_haunting_spirits_AuraScript : public AuraScript + { + PrepareAuraScript(spell_shadowfang_keep_haunting_spirits_AuraScript); + + void CalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude) + { + isPeriodic = true; + amplitude = (irand(0, 60) + 30) * IN_MILLISECONDS; + } + + void HandleDummyTick(AuraEffect const* aurEff) + { + GetTarget()->CastSpell((Unit*)NULL, aurEff->GetAmount(), true); + } + + void HandleUpdatePeriodic(AuraEffect* aurEff) + { + aurEff->CalculatePeriodic(GetCaster()); + } + + void Register() + { + DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::CalcPeriodic, EFFECT_0, SPELL_AURA_DUMMY); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::HandleDummyTick, EFFECT_0, SPELL_AURA_DUMMY); + OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_shadowfang_keep_haunting_spirits_AuraScript::HandleUpdatePeriodic, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_shadowfang_keep_haunting_spirits_AuraScript(); + } +}; + void AddSC_shadowfang_keep() { new npc_shadowfang_prisoner(); new npc_arugal_voidwalker(); + new spell_shadowfang_keep_haunting_spirits(); } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp index b5698d851f8..4fcfa8a046e 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -23,7 +23,10 @@ SDComment: SDCategory: Zul'Aman EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "zulaman.h" #define YELL_AGGRO "Da shadow gonna fall on you... " @@ -47,54 +50,58 @@ EndScriptData */ //Defines for various powers he uses after using soul drain -//Druid -#define SPELL_DR_LIFEBLOOM 43421 -#define SPELL_DR_THORNS 43420 -#define SPELL_DR_MOONFIRE 43545 - -//Hunter -#define SPELL_HU_EXPLOSIVE_TRAP 43444 -#define SPELL_HU_FREEZING_TRAP 43447 -#define SPELL_HU_SNAKE_TRAP 43449 - -//Mage -#define SPELL_MG_FIREBALL 41383 -#define SPELL_MG_FROSTBOLT 43428 -#define SPELL_MG_FROST_NOVA 43426 -#define SPELL_MG_ICE_LANCE 43427 - -//Paladin -#define SPELL_PA_CONSECRATION 43429 -#define SPELL_PA_HOLY_LIGHT 43451 -#define SPELL_PA_AVENGING_WRATH 43430 - -//Priest -#define SPELL_PR_HEAL 41372 -#define SPELL_PR_MIND_CONTROL 43550 -#define SPELL_PR_MIND_BLAST 41374 -#define SPELL_PR_SW_DEATH 41375 -#define SPELL_PR_PSYCHIC_SCREAM 43432 -#define SPELL_PR_PAIN_SUPP 44416 - -//Rogue -#define SPELL_RO_BLIND 43433 -#define SPELL_RO_SLICE_DICE 43457 -#define SPELL_RO_WOUND_POISON 39665 - -//Shaman -#define SPELL_SH_FIRE_NOVA 43436 -#define SPELL_SH_HEALING_WAVE 43548 -#define SPELL_SH_CHAIN_LIGHT 43435 - -//Warlock -#define SPELL_WL_CURSE_OF_DOOM 43439 -#define SPELL_WL_RAIN_OF_FIRE 43440 -#define SPELL_WL_UNSTABLE_AFFL 35183 - -//Warrior -#define SPELL_WR_SPELL_REFLECT 43443 -#define SPELL_WR_WHIRLWIND 43442 -#define SPELL_WR_MORTAL_STRIKE 43441 +enum Spells +{ + // Druid + SPELL_DR_THORNS = 43420, + SPELL_DR_LIFEBLOOM = 43421, + SPELL_DR_MOONFIRE = 43545, + + // Hunter + SPELL_HU_EXPLOSIVE_TRAP = 43444, + SPELL_HU_FREEZING_TRAP = 43447, + SPELL_HU_SNAKE_TRAP = 43449, + + // Mage + SPELL_MG_FIREBALL = 41383, + SPELL_MG_FROST_NOVA = 43426, + SPELL_MG_ICE_LANCE = 43427, + SPELL_MG_FROSTBOLT = 43428, + + // Paladin + SPELL_PA_CONSECRATION = 43429, + SPELL_PA_AVENGING_WRATH = 43430, + SPELL_PA_HOLY_LIGHT = 43451, + + // Priest + SPELL_PR_HEAL = 41372, + SPELL_PR_MIND_BLAST = 41374, + SPELL_PR_SW_DEATH = 41375, + SPELL_PR_PSYCHIC_SCREAM = 43432, + SPELL_PR_MIND_CONTROL = 43550, + SPELL_PR_PAIN_SUPP = 44416, + + // Rogue + SPELL_RO_BLIND = 43433, + SPELL_RO_SLICE_DICE = 43457, + SPELL_RO_WOUND_POISON = 43461, + + // Shaman + SPELL_SH_CHAIN_LIGHT = 43435, + SPELL_SH_FIRE_NOVA = 43436, + SPELL_SH_HEALING_WAVE = 43548, + + // Warlock + SPELL_WL_CURSE_OF_DOOM = 43439, + SPELL_WL_RAIN_OF_FIRE = 43440, + SPELL_WL_UNSTABLE_AFFL = 43522, + SPELL_WL_UNSTABLE_AFFL_DISPEL = 43523, + + // Warrior + SPELL_WR_MORTAL_STRIKE = 43441, + SPELL_WR_WHIRLWIND = 43442, + SPELL_WR_SPELL_REFLECT = 43443 +}; #define ORIENT 1.5696f #define POS_Y 921.2795f @@ -936,6 +943,40 @@ class boss_koragg : public CreatureScript } }; +class spell_hexlord_unstable_affliction : public SpellScriptLoader +{ + public: + spell_hexlord_unstable_affliction() : SpellScriptLoader("spell_hexlord_unstable_affliction") { } + + class spell_hexlord_unstable_affliction_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hexlord_unstable_affliction_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_WL_UNSTABLE_AFFL_DISPEL)) + return false; + return true; + } + + void HandleDispel(DispelInfo* dispelInfo) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(dispelInfo->GetDispeller(), SPELL_WL_UNSTABLE_AFFL_DISPEL, true, NULL, GetEffect(EFFECT_0)); + } + + void Register() + { + AfterDispel += AuraDispelFn(spell_hexlord_unstable_affliction_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hexlord_unstable_affliction_AuraScript(); + } +}; + void AddSC_boss_hex_lord_malacrass() { new boss_hexlord_malacrass(); @@ -947,5 +988,6 @@ void AddSC_boss_hex_lord_malacrass() new boss_fenstalker(); new boss_koragg(); new boss_alyson_antille(); + new spell_hexlord_unstable_affliction(); } diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp index a86b2b8b17a..a70d05fa0ef 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp @@ -15,11 +15,13 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "blackfathom_deeps.h" #include "ScriptedEscortAI.h" -enum eSpells +enum Spells { SPELL_BLESSING_OF_BLACKFATHOM = 8733, SPELL_RAVAGE = 8391, @@ -94,11 +96,11 @@ public: uint32 frostNovaTimer; uint32 frostBoltVolleyTimer; - bool bFlee; + bool Flee; void Reset() { - bFlee = false; + Flee = false; ravageTimer = urand(5000, 8000); frostNovaTimer = urand(9000, 12000); @@ -140,7 +142,7 @@ public: { if (ravageTimer <= diff) { - DoCast(me->getVictim(), SPELL_RAVAGE); + DoCastVictim(SPELL_RAVAGE); ravageTimer = urand(9000, 14000); } else ravageTimer -= diff; break; @@ -148,9 +150,9 @@ public: case NPC_MURKSHALLOW_SOFTSHELL: case NPC_BARBED_CRUSTACEAN: { - if (!bFlee && HealthBelowPct(15)) + if (!Flee && HealthBelowPct(15)) { - bFlee = true; + Flee = true; me->DoFleeToGetAssistance(); } break; @@ -160,10 +162,7 @@ public: if (frostBoltVolleyTimer <= diff) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - if (target) - DoCast(target, SPELL_FROST_BOLT_VOLLEY); - } + DoCast(target, SPELL_FROST_BOLT_VOLLEY); frostBoltVolleyTimer = urand(5000, 8000); } else frostBoltVolleyTimer -= diff; @@ -190,7 +189,7 @@ public: }; }; -enum eMorridune +enum Morridune { SAY_MORRIDUNE_1 = -1048003, SAY_MORRIDUNE_2 = -1048004 diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp index 32a6bcbde77..7071395812e 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "blackfathom_deeps.h" enum Spells @@ -42,14 +43,14 @@ public: } uint32 poisonCloudTimer; - bool bIsEnraged; + bool IsEnraged; InstanceScript* instance; void Reset() { poisonCloudTimer = urand(5000, 9000); - bIsEnraged = false; + IsEnraged = false; if (instance) instance->SetData(TYPE_AKU_MAI, NOT_STARTED); } @@ -77,10 +78,10 @@ public: poisonCloudTimer = urand(25000, 50000); } else poisonCloudTimer -= diff; - if (!bIsEnraged && HealthBelowPct(30)) + if (!IsEnraged && HealthBelowPct(30)) { DoCast(me, SPELL_FRENZIED_RAGE); - bIsEnraged = true; + IsEnraged = true; } DoMeleeAttackIfReady(); diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp index 5a60a849b75..1488772dc8a 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_gelihast.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "blackfathom_deeps.h" enum Spells diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp index 7ee17172102..1c754b78672 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/boss_kelris.cpp @@ -15,7 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "blackfathom_deeps.h" enum Spells diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp index ea33499a960..236c7b1ba69 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Blackfathom Deeps EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" #include "blackfathom_deeps.h" #define MAX_ENCOUNTER 4 diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp index 85f82c62079..222626240ea 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -15,42 +15,30 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "hyjal.h" #include "hyjal_trash.h" -#define SPELL_CARRION_SWARM 31306 -#define SPELL_SLEEP 31298 -#define SPELL_VAMPIRIC_AURA 38196 -#define SPELL_INFERNO 31299 - -#define SAY_ONDEATH "The clock... is still... ticking." -#define SOUND_ONDEATH 10982 - -#define SAY_ONSLAY1 "Your hopes are lost!" -#define SAY_ONSLAY2 "Scream for me!" -#define SAY_ONSLAY3 "Pity, no time for a slow death!" -#define SOUND_ONSLAY1 10981 -#define SOUND_ONSLAY2 11038 -#define SOUND_ONSLAY3 11039 - -#define SAY_SWARM1 "The swarm is eager to feed!" -#define SAY_SWARM2 "Pestilence upon you!" -#define SOUND_SWARM1 10979 -#define SOUND_SWARM2 11037 - -#define SAY_SLEEP1 "You look tired..." -#define SAY_SLEEP2 "Sweet dreams..." -#define SOUND_SLEEP1 10978 -#define SOUND_SLEEP2 11545 - -#define SAY_INFERNO1 "Let fire rain from above!" -#define SAY_INFERNO2 "Earth and sky shall burn!" -#define SOUND_INFERNO1 10980 -#define SOUND_INFERNO2 11036 +enum Spells +{ + SPELL_CARRION_SWARM = 31306, + SPELL_SLEEP = 31298, + SPELL_VAMPIRIC_AURA = 38196, + SPELL_INFERNO = 31299, + SPELL_IMMOLATION = 31303, + SPELL_INFERNO_EFFECT = 31302, +}; -#define SAY_ONAGGRO "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!" -#define SOUND_ONAGGRO 10977 +enum Texts +{ + SAY_ONDEATH = 0, + SAY_ONSLAY = 1, + SAY_SWARM = 2, + SAY_SLEEP = 3, + SAY_INFERNO = 4, + SAY_ONAGGRO = 5, +}; class boss_anetheron : public CreatureScript { @@ -92,27 +80,12 @@ public: { if (instance && IsEvent) instance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + Talk(SAY_ONAGGRO); } void KilledUnit(Unit* /*victim*/) { - switch (urand(0, 2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_ONSLAY); } void WaypointReached(uint32 waypointId) @@ -130,8 +103,7 @@ public: hyjal_trashAI::JustDied(killer); if (instance && IsEvent) instance->SetData(DATA_ANETHERONEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); + Talk(SAY_ONDEATH); } void UpdateAI(const uint32 diff) @@ -169,17 +141,7 @@ public: DoCast(target, SPELL_CARRION_SWARM); SwarmTimer = urand(45000, 60000); - switch (urand(0, 1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SWARM1); - me->MonsterYell(SAY_SWARM1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SWARM2); - me->MonsterYell(SAY_SWARM2, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_SWARM); } else SwarmTimer -= diff; if (SleepTimer <= diff) @@ -190,17 +152,7 @@ public: target->CastSpell(target, SPELL_SLEEP, true); } SleepTimer = 60000; - switch (urand(0, 1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SLEEP1); - me->MonsterYell(SAY_SLEEP1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SLEEP2); - me->MonsterYell(SAY_SLEEP2, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_SLEEP); } else SleepTimer -= diff; if (AuraTimer <= diff) { @@ -211,17 +163,7 @@ public: { DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO); InfernoTimer = 45000; - switch (urand(0, 1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_INFERNO1); - me->MonsterYell(SAY_INFERNO1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_INFERNO2); - me->MonsterYell(SAY_INFERNO2, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_INFERNO); } else InfernoTimer -= diff; DoMeleeAttackIfReady(); @@ -230,9 +172,6 @@ public: }; -#define SPELL_IMMOLATION 31303 -#define SPELL_INFERNO_EFFECT 31302 - class mob_towering_infernal : public CreatureScript { public: diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index f07aaaa1f2a..ee988accbac 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -23,56 +23,57 @@ SDComment: Doomfires not completely offlike due to core limitations for random m SDCategory: Caverns of Time, Mount Hyjal EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "hyjal.h" #include "SpellAuras.h" #include "hyjal_trash.h" -//text id -1534018 are the text used when previous events complete. Not part of this script. -#define SAY_AGGRO -1534019 -#define SAY_DOOMFIRE1 -1534020 -#define SAY_DOOMFIRE2 -1534021 -#define SAY_AIR_BURST1 -1534022 -#define SAY_AIR_BURST2 -1534023 -#define SAY_SLAY1 -1534024 -#define SAY_SLAY2 -1534025 -#define SAY_SLAY3 -1534026 -#define SAY_ENRAGE -1534027 -#define SAY_DEATH -1534028 -#define SAY_SOUL_CHARGE1 -1534029 -#define SAY_SOUL_CHARGE2 -1534030 - -#define SPELL_DENOUEMENT_WISP 32124 -#define SPELL_ANCIENT_SPARK 39349 -#define SPELL_PROTECTION_OF_ELUNE 38528 - -#define SPELL_DRAIN_WORLD_TREE 39140 -#define SPELL_DRAIN_WORLD_TREE_2 39141 - -#define SPELL_FINGER_OF_DEATH 31984 -#define SPELL_HAND_OF_DEATH 35354 -#define SPELL_AIR_BURST 32014 -#define SPELL_GRIP_OF_THE_LEGION 31972 -#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures -#define SPELL_DOOMFIRE_SPAWN 32074 -#define SPELL_DOOMFIRE 31945 -#define SPELL_SOUL_CHARGE_YELLOW 32045 -#define SPELL_SOUL_CHARGE_GREEN 32051 -#define SPELL_SOUL_CHARGE_RED 32052 -#define SPELL_UNLEASH_SOUL_YELLOW 32054 -#define SPELL_UNLEASH_SOUL_GREEN 32057 -#define SPELL_UNLEASH_SOUL_RED 32053 -#define SPELL_FEAR 31970 - -#define CREATURE_ARCHIMONDE 17968 -#define CREATURE_DOOMFIRE 18095 -#define CREATURE_DOOMFIRE_SPIRIT 18104 -#define CREATURE_ANCIENT_WISP 17946 -#define CREATURE_CHANNEL_TARGET 22418 - -#define NORDRASSIL_X 5503.713f -#define NORDRASSIL_Y -3523.436f -#define NORDRASSIL_Z 1608.781f +enum Texts +{ + SAY_AGGRO = 1, + SAY_DOOMFIRE = 2, + SAY_AIR_BURST = 3, + SAY_SLAY = 4, + SAY_ENRAGE = 5, + SAY_DEATH = 6, + SAY_SOUL_CHARGE = 7, +}; + +enum Spells +{ + SPELL_DENOUEMENT_WISP = 32124, + SPELL_ANCIENT_SPARK = 39349, + SPELL_PROTECTION_OF_ELUNE = 38528, + + SPELL_DRAIN_WORLD_TREE = 39140, + SPELL_DRAIN_WORLD_TREE_2 = 39141, + + SPELL_FINGER_OF_DEATH = 31984, + SPELL_HAND_OF_DEATH = 35354, + SPELL_AIR_BURST = 32014, + SPELL_GRIP_OF_THE_LEGION = 31972, + SPELL_DOOMFIRE_STRIKE = 31903, //summons two creatures + SPELL_DOOMFIRE_SPAWN = 32074, + SPELL_DOOMFIRE = 31945, + SPELL_SOUL_CHARGE_YELLOW = 32045, + SPELL_SOUL_CHARGE_GREEN = 32051, + SPELL_SOUL_CHARGE_RED = 32052, + SPELL_UNLEASH_SOUL_YELLOW = 32054, + SPELL_UNLEASH_SOUL_GREEN = 32057, + SPELL_UNLEASH_SOUL_RED = 32053, + SPELL_FEAR = 31970, +}; + +enum Summons +{ + CREATURE_DOOMFIRE = 18095, + CREATURE_DOOMFIRE_SPIRIT = 18104, + CREATURE_ANCIENT_WISP = 17946, + CREATURE_CHANNEL_TARGET = 22418, +}; + +Position const NordrassilLoc = {5503.713f, -3523.436f, 1608.781f, 0.0f}; class mob_ancient_wisp : public CreatureScript { @@ -258,11 +259,11 @@ public: uint32 GripOfTheLegionTimer; uint32 DoomfireTimer; uint32 SoulChargeTimer; - uint32 SoulChargeCount; + uint8 SoulChargeCount; uint32 MeleeRangeCheckTimer; uint32 HandOfDeathTimer; uint32 SummonWispTimer; - uint32 WispCount; + uint8 WispCount; uint32 EnrageTimer; uint32 CheckDistanceTimer; @@ -303,7 +304,7 @@ public: void EnterCombat(Unit* /*who*/) { me->InterruptSpell(CURRENT_CHANNELED_SPELL); - DoScriptText(SAY_AGGRO, me); + Talk(SAY_AGGRO); DoZoneInCombat(); if (instance) @@ -312,7 +313,7 @@ public: void KilledUnit(Unit* victim) { - DoScriptText(RAND(SAY_SLAY1, SAY_SLAY2, SAY_SLAY3), me); + Talk(SAY_SLAY); if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) GainSoulCharge(CAST_PLR(victim)); @@ -346,7 +347,7 @@ public: void JustDied(Unit* killer) { hyjal_trashAI::JustDied(killer); - DoScriptText(SAY_DEATH, me); + Talk(SAY_DEATH); if (instance) instance->SetData(DATA_ARCHIMONDEEVENT, DONE); @@ -488,7 +489,7 @@ public: { if (!IsChanneling) { - Creature* temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); + Creature* temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 1200000); if (temp) WorldTreeGUID = temp->GetGUID(); @@ -525,14 +526,14 @@ public: me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MoveIdle(); Enraged = true; - DoScriptText(SAY_ENRAGE, me); + Talk(SAY_ENRAGE); } } else EnrageTimer -= diff; if (CheckDistanceTimer <= diff) { // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature - Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); + Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 2000); if (Check) { Check->SetVisible(false); @@ -542,7 +543,7 @@ public: me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MoveIdle(); Enraged = true; - DoScriptText(SAY_ENRAGE, me); + Talk(SAY_ENRAGE); } } CheckDistanceTimer = 5000; @@ -598,11 +599,7 @@ public: if (AirBurstTimer <= diff) { - if (urand(0, 1)) - DoScriptText(SAY_AIR_BURST1, me); - else - DoScriptText(SAY_AIR_BURST2, me); - + Talk(SAY_AIR_BURST); DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank AirBurstTimer = urand(25000, 40000); } else AirBurstTimer -= diff; @@ -615,11 +612,7 @@ public: if (DoomfireTimer <= diff) { - if (urand(0, 1)) - DoScriptText(SAY_DOOMFIRE1, me); - else - DoScriptText(SAY_DOOMFIRE2, me); - + Talk(SAY_DOOMFIRE); Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 1); if (!temp) temp = me->getVictim(); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp index a9e0c866ab9..bfdaed35dd4 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -15,33 +15,31 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "hyjal.h" #include "hyjal_trash.h" -#define SPELL_RAIN_OF_FIRE 31340 -#define SPELL_DOOM 31347 -#define SPELL_HOWL_OF_AZGALOR 31344 -#define SPELL_CLEAVE 31345 -#define SPELL_BERSERK 26662 - -#define SAY_ONDEATH "Your time is almost... up" -#define SOUND_ONDEATH 11002 - -#define SAY_ONSLAY1 "Reesh, hokta!" -#define SAY_ONSLAY2 "Don't fight it" -#define SAY_ONSLAY3 "No one is going to save you" -#define SOUND_ONSLAY1 11001 -#define SOUND_ONSLAY2 11048 -#define SOUND_ONSLAY3 11047 - -#define SAY_DOOM1 "Just a taste... of what awaits you" -#define SAY_DOOM2 "Suffer you despicable insect!" -#define SOUND_DOOM1 11046 -#define SOUND_DOOM2 11000 +enum Spells +{ + SPELL_RAIN_OF_FIRE = 31340, + SPELL_DOOM = 31347, + SPELL_HOWL_OF_AZGALOR = 31344, + SPELL_CLEAVE = 31345, + SPELL_BERSERK = 26662, + + SPELL_THRASH = 12787, + SPELL_CRIPPLE = 31406, + SPELL_WARSTOMP = 31408, +}; -#define SAY_ONAGGRO "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!" -#define SOUND_ONAGGRO 10999 +enum Texts +{ + SAY_ONDEATH = 0, + SAY_ONSLAY = 1, + SAY_DOOM = 2, // Not used? + SAY_ONAGGRO = 3, +}; class boss_azgalor : public CreatureScript { @@ -88,27 +86,12 @@ public: { if (instance && IsEvent) instance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + Talk(SAY_ONAGGRO); } void KilledUnit(Unit* /*victim*/) { - switch (urand(0, 2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_ONSLAY); } void WaypointReached(uint32 waypointId) @@ -126,7 +109,7 @@ public: hyjal_trashAI::JustDied(killer); if (instance && IsEvent) instance->SetData(DATA_AZGALOREVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); + Talk(SAY_ONDEATH); } void UpdateAI(const uint32 diff) @@ -196,10 +179,6 @@ public: }; -#define SPELL_THRASH 12787 -#define SPELL_CRIPPLE 31406 -#define SPELL_WARSTOMP 31408 - class mob_lesser_doomguard : public CreatureScript { public: diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp index 407faa19eaa..29eff68dfbd 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp @@ -15,30 +15,32 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" #include "hyjal.h" #include "hyjal_trash.h" -#define SPELL_CLEAVE 31436 -#define SPELL_WARSTOMP 31480 -#define SPELL_MARK 31447 - -#define SOUND_ONDEATH 11018 - -#define SAY_ONSLAY1 "Shaza-Kiel!" -#define SAY_ONSLAY2 "You... are nothing!" -#define SAY_ONSLAY3 "Miserable nuisance!" -#define SOUND_ONSLAY1 11017 -#define SOUND_ONSLAY2 11053 -#define SOUND_ONSLAY3 11054 +enum Spells +{ + SPELL_CLEAVE = 31436, + SPELL_WARSTOMP = 31480, + SPELL_MARK = 31447, + SPELL_MARK_DAMAGE = 31463 +}; -#define SAY_MARK1 "Your death will be a painful one." -#define SAY_MARK2 "You... are marked." -#define SOUND_MARK1 11016 -#define SOUND_MARK2 11052 +enum Texts +{ + SAY_ONSLAY = 0, + SAY_MARK = 1, + SAY_ONAGGRO = 2, +}; -#define SAY_ONAGGRO "Cry for mercy! Your meaningless lives will soon be forfeit." -#define SOUND_ONAGGRO 11015 +enum Sounds +{ + SOUND_ONDEATH = 11018, +}; class boss_kazrogal : public CreatureScript { @@ -80,27 +82,12 @@ public: { if (instance && IsEvent) instance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + Talk(SAY_ONAGGRO); } void KilledUnit(Unit* /*victim*/) { - switch (urand(0, 2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_ONSLAY); } void WaypointReached(uint32 waypointId) @@ -162,37 +149,15 @@ public: WarStompTimer = 60000; } else WarStompTimer -= diff; - if (me->HasAura(SPELL_MARK)) - me->RemoveAurasDueToSpell(SPELL_MARK); if (MarkTimer <= diff) { - //cast dummy, useful for bos addons - me->CastCustomSpell(me, SPELL_MARK, NULL, NULL, NULL, false, NULL, NULL, me->GetGUID()); + DoCastAOE(SPELL_MARK); - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit* target = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (target && target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() == POWER_MANA) - { - target->CastSpell(target, SPELL_MARK, true);//only cast on mana users - } - } MarkTimerBase -= 5000; if (MarkTimerBase < 5500) MarkTimerBase = 5500; MarkTimer = MarkTimerBase; - switch (urand(0, 2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_MARK1); - me->MonsterYell(SAY_MARK1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_MARK2); - me->MonsterYell(SAY_MARK2, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_MARK); } else MarkTimer -= diff; DoMeleeAttackIfReady(); @@ -201,7 +166,79 @@ public: }; +class MarkTargetFilter +{ + public: + bool operator()(WorldObject* target) const + { + if (Unit* unit = target->ToUnit()) + return unit->getPowerType() != POWER_MANA; + return false; + } +}; + +class spell_mark_of_kazrogal : public SpellScriptLoader +{ + public: + spell_mark_of_kazrogal() : SpellScriptLoader("spell_mark_of_kazrogal") { } + + class spell_mark_of_kazrogal_SpellScript : public SpellScript + { + PrepareSpellScript(spell_mark_of_kazrogal_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(MarkTargetFilter()); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_kazrogal_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + class spell_mark_of_kazrogal_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mark_of_kazrogal_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MARK_DAMAGE)) + return false; + return true; + } + + void OnPeriodic(AuraEffect const* aurEff) + { + Unit* target = GetTarget(); + + if (target->GetPower(POWER_MANA) == 0) + { + target->CastSpell(target, SPELL_MARK_DAMAGE, true, NULL, aurEff); + // Remove aura + SetDuration(0); + } + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_kazrogal_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_mark_of_kazrogal_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_mark_of_kazrogal_AuraScript(); + } +}; + void AddSC_boss_kazrogal() { new boss_kazrogal(); + new spell_mark_of_kazrogal(); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp index 5d7ee1fe194..09c8c1605b3 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp @@ -15,36 +15,27 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "hyjal.h" #include "hyjal_trash.h" -#define SPELL_FROST_ARMOR 31256 -#define SPELL_DEATH_AND_DECAY 31258 - -#define SPELL_FROST_NOVA 31250 -#define SPELL_ICEBOLT 31249 - -#define SAY_ONDEATH "You have won this battle, but not... the... war" -#define SOUND_ONDEATH 11026 - -#define SAY_ONSLAY1 "All life must perish!" -#define SAY_ONSLAY2 "Victory to the Legion!" -#define SOUND_ONSLAY1 11025 -#define SOUND_ONSLAY2 11057 - -#define SAY_DECAY1 "Crumble and rot!" -#define SAY_DECAY2 "Ashes to ashes, dust to dust" -#define SOUND_DECAY1 11023 -#define SOUND_DECAY2 11055 - -#define SAY_NOVA1 "Succumb to the icy chill... of death!" -#define SAY_NOVA2 "It will be much colder in your grave" -#define SOUND_NOVA1 11024 -#define SOUND_NOVA2 11058 +enum Spells +{ + SPELL_FROST_ARMOR = 31256, + SPELL_DEATH_AND_DECAY = 31258, + SPELL_FROST_NOVA = 31250, + SPELL_ICEBOLT = 31249, +}; -#define SAY_ONAGGRO "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!" -#define SOUND_ONAGGRO 11022 +enum Texts +{ + SAY_ONDEATH = 0, + SAY_ONSLAY = 1, + SAY_DECAY = 2, + SAY_NOVA = 3, + SAY_ONAGGRO = 4, +}; class boss_rage_winterchill : public CreatureScript { @@ -86,23 +77,12 @@ public: { if (instance && IsEvent) instance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + Talk(SAY_ONAGGRO); } void KilledUnit(Unit* /*victim*/) { - switch (urand(0, 1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_ONSLAY); } void WaypointReached(uint32 waypointId) @@ -120,8 +100,7 @@ public: hyjal_trashAI::JustDied(killer); if (instance && IsEvent) instance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); + Talk(SAY_ONDEATH); } void UpdateAI(const uint32 diff) @@ -162,33 +141,13 @@ public: { DoCast(me->getVictim(), SPELL_DEATH_AND_DECAY); DecayTimer = 60000+rand()%20000; - switch (urand(0, 1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_DECAY1); - me->MonsterYell(SAY_DECAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_DECAY2); - me->MonsterYell(SAY_DECAY2, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_DECAY); } else DecayTimer -= diff; if (NovaTimer <= diff) { DoCast(me->getVictim(), SPELL_FROST_NOVA); NovaTimer = 30000+rand()%15000; - switch (urand(0, 1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_NOVA1); - me->MonsterYell(SAY_NOVA1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_NOVA2); - me->MonsterYell(SAY_NOVA2, LANG_UNIVERSAL, 0); - break; - } + Talk(SAY_NOVA); } else NovaTimer -= diff; if (IceboltTimer <= diff) { diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp index 22307468f14..1be8f8e058f 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp @@ -29,7 +29,9 @@ npc_thrall npc_tyrande_whisperwind EndContentData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedGossip.h" #include "hyjalAI.h" #define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore." diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h index e045d3cbf05..6d62072608d 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h @@ -21,7 +21,7 @@ #define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy." -enum eTypes +enum Types { WORLD_STATE_WAVES = 2842, WORLD_STATE_ENEMY = 2453, diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp index 2f6bbb7edb5..a407f86ba70 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -23,17 +23,22 @@ SDComment: SDCategory: Caverns of Time, Mount Hyjal EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "ScriptedEscortAI.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "Cell.h" +#include "CellImpl.h" #include "hyjalAI.h" #include "hyjal_trash.h" -#include "MapManager.h" -#include "Language.h" -#include "Chat.h" -#include "Object.h" - -#define SPAWN_GARG_GATE 0 -#define SPAWN_WYRM_GATE 1 -#define SPAWN_NEAR_TOWER 2 + +enum Spawns +{ + SPAWN_GARG_GATE = 0, + SPAWN_WYRM_GATE = 1, + SPAWN_NEAR_TOWER = 2, +}; #define YELL_HURRY "Hurry, we don't have much time" diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h index b32288ca43a..68efa94d98b 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h @@ -24,43 +24,49 @@ #define HYJAL_AI_MAX_SPELLS 3 -// Trash Mobs summoned in waves -#define NECROMANCER 17899//done -#define ABOMINATION 17898//done -#define GHOUL 17895//done -#define BANSHEE 17905//done -#define CRYPT_FIEND 17897//done -#define GARGOYLE 17906//done -#define FROST_WYRM 17907//done -#define GIANT_INFERNAL 17908//done -#define FEL_STALKER 17916//done - -#define JAINA 17772 -#define THRALL 17852 -#define TYRANDE 17948 - -#define ANCIENT_VEIN 185557 -#define FLAMEOBJECT 182592 - -// Bosses summoned after every 8 waves -#define RAGE_WINTERCHILL 17767 -#define ANETHERON 17808 -#define KAZROGAL 17888 -#define AZGALOR 17842 -#define ARCHIMONDE 17968 - -#define SPELL_TELEPORT_VISUAL 41232 -#define SPELL_MASS_TELEPORT 16807 - -//Spells for Jaina -#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon(it should, but is removed in evade..) -#define SPELL_BLIZZARD 31266 -#define SPELL_PYROBLAST 31263 -#define SPELL_SUMMON_ELEMENTALS 31264 - -//Thrall spells -#define SPELL_CHAIN_LIGHTNING 31330 -#define SPELL_SUMMON_DIRE_WOLF 31331 +enum CreaturesIds +{ + // Trash Mobs summoned in waves + NECROMANCER = 17899, + ABOMINATION = 17898, + GHOUL = 17895, + BANSHEE = 17905, + CRYPT_FIEND = 17897, + GARGOYLE = 17906, + FROST_WYRM = 17907, + GIANT_INFERNAL = 17908, + FEL_STALKER = 17916, + + JAINA = 17772, + THRALL = 17852, + TYRANDE = 17948, + + ANCIENT_VEIN = 185557, + FLAMEOBJECT = 182592, + + // Bosses summoned after every 8 waves + RAGE_WINTERCHILL = 17767, + ANETHERON = 17808, + KAZROGAL = 17888, + AZGALOR = 17842, + ARCHIMONDE = 17968, +}; + +enum SpellIds +{ + SPELL_TELEPORT_VISUAL = 41232, + SPELL_MASS_TELEPORT = 16807, + + //Spells for Jaina + SPELL_BRILLIANCE_AURA = 31260, // The database must handle this spell via creature_addon(it should, but is removed in evade..) + SPELL_BLIZZARD = 31266, + SPELL_PYROBLAST = 31263, + SPELL_SUMMON_ELEMENTALS = 31264, + + //Thrall spells + SPELL_CHAIN_LIGHTNING = 31330, + SPELL_SUMMON_DIRE_WOLF = 31331, +}; struct Wave { diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp index 840aa5de081..d3218e1729e 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -15,16 +15,35 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "hyjal.h" #include "hyjal_trash.h" #include "hyjalAI.h" -#define SPELL_METEOR 33814 //infernal visual -#define SPELL_IMMOLATION 37059 -#define SPELL_FLAME_BUFFET 31724 -#define NPC_TRIGGER 21987 //World Trigger (Tiny) -#define MODEL_INVIS 11686 //invisible model +enum Spells +{ + SPELL_METEOR = 33814, //infernal visual + SPELL_IMMOLATION = 37059, + SPELL_FLAME_BUFFET = 31724, + NPC_TRIGGER = 21987, //World Trigger (Tiny) + MODEL_INVIS = 11686, //invisible model + SPELL_DISEASE_CLOUD = 31607, + SPELL_KNOCKDOWN = 31610, + SPELL_FRENZY = 31540, + SPELL_RAISE_DEAD_1 = 31617, + SPELL_RAISE_DEAD_2 = 31624, + SPELL_RAISE_DEAD_3 = 31625, + SPELL_SHADOW_BOLT = 31627, + SPELL_BANSHEE_CURSE = 31651, + SPELL_BANSHEE_WAIL = 38183, + SPELL_ANTI_MAGIC_SHELL = 31662, + SPELL_WEB = 28991, + SPELL_MANA_BURN = 31729, + SPELL_FROST_BREATH = 31688, + SPELL_GARGOYLE_STRIKE = 31664, + SPELL_EXPLODING_SHOT = 7896, +}; float HordeWPs[8][3]=//basic waypoints from spawn to leader { @@ -522,9 +541,6 @@ public: } }; -#define SPELL_DISEASE_CLOUD 31607 -#define SPELL_KNOCKDOWN 31610 - class mob_abomination : public CreatureScript { public: @@ -623,8 +639,6 @@ public: }; -#define SPELL_FRENZY 31540 - class mob_ghoul : public CreatureScript { public: @@ -727,11 +741,6 @@ public: }; -#define SPELL_RAISE_DEAD_1 31617 -#define SPELL_RAISE_DEAD_2 31624 -#define SPELL_RAISE_DEAD_3 31625 -#define SPELL_SHADOW_BOLT 31627 - class mob_necromancer : public CreatureScript { public: @@ -859,10 +868,6 @@ public: }; -#define SPELL_BANSHEE_CURSE 31651 -#define SPELL_BANSHEE_WAIL 38183 -#define SPELL_ANTI_MAGIC_SHELL 31662 - class mob_banshee : public CreatureScript { public: @@ -966,8 +971,6 @@ public: }; -#define SPELL_WEB 28991 - class mob_crypt_fiend : public CreatureScript { public: @@ -1058,8 +1061,6 @@ public: }; -#define SPELL_MANA_BURN 31729 - class mob_fel_stalker : public CreatureScript { public: @@ -1150,8 +1151,6 @@ public: }; -#define SPELL_FROST_BREATH 31688 - class mob_frost_wyrm : public CreatureScript { public: @@ -1264,8 +1263,6 @@ public: }; -#define SPELL_GARGOYLE_STRIKE 31664 - class mob_gargoyle : public CreatureScript { public: @@ -1402,8 +1399,6 @@ public: }; -#define SPELL_EXPLODING_SHOT 7896 - class alliance_rifleman : public CreatureScript { public: diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp index ad8ebdb370a..69bb8285404 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -23,15 +23,16 @@ SDComment: Instance Data Scripts and functions to acquire mobs and set encounter SDCategory: Caverns of Time, Mount Hyjal EndScriptData */ -#include "ScriptPCH.h" -#include "hyjal.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" +#include "ScriptedCreature.h" #include "hyjal_trash.h" -enum eEnums +enum Misc { MAX_ENCOUNTER = 5, - GO_ANCIENT_GEM = 185557 + GO_ANCIENT_GEM = 185557, }; /* Battle of Mount Hyjal encounters: 0 - Rage Winterchill event diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp index d7043965271..b23d15cd1b5 100644 --- a/src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp +++ b/src/server/scripts/Kalimdor/Maraudon/boss_celebras_the_cursed.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Maraudon EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" enum Spells { @@ -46,15 +47,15 @@ public: { celebras_the_cursedAI(Creature* creature) : ScriptedAI(creature) {} - uint32 Wrath_Timer; - uint32 EntanglingRoots_Timer; - uint32 CorruptForces_Timer; + uint32 WrathTimer; + uint32 EntanglingRootsTimer; + uint32 CorruptForcesTimer; void Reset() { - Wrath_Timer = 8000; - EntanglingRoots_Timer = 2000; - CorruptForces_Timer = 30000; + WrathTimer = 8000; + EntanglingRootsTimer = 2000; + CorruptForcesTimer = 30000; } void EnterCombat(Unit* /*who*/) { } @@ -70,32 +71,30 @@ public: return; //Wrath - if (Wrath_Timer <= diff) + if (WrathTimer <= diff) { - Unit* target = NULL; - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) DoCast(target, SPELL_WRATH); - Wrath_Timer = 8000; + WrathTimer = 8000; } - else Wrath_Timer -= diff; + else WrathTimer -= diff; //EntanglingRoots - if (EntanglingRoots_Timer <= diff) + if (EntanglingRootsTimer <= diff) { - DoCast(me->getVictim(), SPELL_ENTANGLINGROOTS); - EntanglingRoots_Timer = 20000; + DoCastVictim(SPELL_ENTANGLINGROOTS); + EntanglingRootsTimer = 20000; } - else EntanglingRoots_Timer -= diff; + else EntanglingRootsTimer -= diff; //CorruptForces - if (CorruptForces_Timer <= diff) + if (CorruptForcesTimer <= diff) { me->InterruptNonMeleeSpells(false); DoCast(me, SPELL_CORRUPT_FORCES); - CorruptForces_Timer = 20000; + CorruptForcesTimer = 20000; } - else CorruptForces_Timer -= diff; + else CorruptForcesTimer -= diff; DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp index ea419793ae8..b4128ea80ee 100644 --- a/src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp +++ b/src/server/scripts/Kalimdor/Maraudon/boss_landslide.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Maraudon EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" enum Spells { @@ -46,15 +47,15 @@ public: { boss_landslideAI(Creature* creature) : ScriptedAI(creature) {} - uint32 KnockAway_Timer; - uint32 Trample_Timer; - uint32 Landslide_Timer; + uint32 KnockAwayTimer; + uint32 TrampleTimer; + uint32 LandslideTimer; void Reset() { - KnockAway_Timer = 8000; - Trample_Timer = 2000; - Landslide_Timer = 0; + KnockAwayTimer = 8000; + TrampleTimer = 2000; + LandslideTimer = 0; } void EnterCombat(Unit* /*who*/) @@ -66,32 +67,32 @@ public: if (!UpdateVictim()) return; - //KnockAway_Timer - if (KnockAway_Timer <= diff) + //KnockAwayTimer + if (KnockAwayTimer <= diff) { - DoCast(me->getVictim(), SPELL_KNOCKAWAY); - KnockAway_Timer = 15000; + DoCastVictim(SPELL_KNOCKAWAY); + KnockAwayTimer = 15000; } - else KnockAway_Timer -= diff; + else KnockAwayTimer -= diff; - //Trample_Timer - if (Trample_Timer <= diff) + //TrampleTimer + if (TrampleTimer <= diff) { DoCast(me, SPELL_TRAMPLE); - Trample_Timer = 8000; + TrampleTimer = 8000; } - else Trample_Timer -= diff; + else TrampleTimer -= diff; //Landslide if (HealthBelowPct(50)) { - if (Landslide_Timer <= diff) + if (LandslideTimer <= diff) { me->InterruptNonMeleeSpells(false); DoCast(me, SPELL_LANDSLIDE); - Landslide_Timer = 60000; + LandslideTimer = 60000; } - else Landslide_Timer -= diff; + else LandslideTimer -= diff; } DoMeleeAttackIfReady(); diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp index 18ce7be0f0a..ece3ff83776 100644 --- a/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp +++ b/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp @@ -23,7 +23,9 @@ SDComment: SDCategory: Maraudon EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" + enum Spells { SPELL_TOXICVOLLEY = 21687, @@ -44,24 +46,22 @@ public: { boss_noxxionAI(Creature* creature) : ScriptedAI(creature) {} - uint32 ToxicVolley_Timer; - uint32 Uppercut_Timer; - uint32 Adds_Timer; - uint32 Invisible_Timer; + uint32 ToxicVolleyTimer; + uint32 UppercutTimer; + uint32 AddsTimer; + uint32 InvisibleTimer; bool Invisible; void Reset() { - ToxicVolley_Timer = 7000; - Uppercut_Timer = 16000; - Adds_Timer = 19000; - Invisible_Timer = 15000; //Too much too low? + ToxicVolleyTimer = 7000; + UppercutTimer = 16000; + AddsTimer = 19000; + InvisibleTimer = 15000; //Too much too low? Invisible = false; } - void EnterCombat(Unit* /*who*/) - { - } + void EnterCombat(Unit* /*who*/) {} void SummonAdds(Unit* victim) { @@ -71,7 +71,7 @@ public: void UpdateAI(const uint32 diff) { - if (Invisible && Invisible_Timer <= diff) + if (Invisible && InvisibleTimer <= diff) { //Become visible again me->setFaction(14); @@ -83,7 +83,7 @@ public: } else if (Invisible) { - Invisible_Timer -= diff; + InvisibleTimer -= diff; //Do nothing while invisible return; } @@ -92,24 +92,24 @@ public: if (!UpdateVictim()) return; - //ToxicVolley_Timer - if (ToxicVolley_Timer <= diff) + //ToxicVolleyTimer + if (ToxicVolleyTimer <= diff) { - DoCast(me->getVictim(), SPELL_TOXICVOLLEY); - ToxicVolley_Timer = 9000; + DoCastVictim(SPELL_TOXICVOLLEY); + ToxicVolleyTimer = 9000; } - else ToxicVolley_Timer -= diff; + else ToxicVolleyTimer -= diff; - //Uppercut_Timer - if (Uppercut_Timer <= diff) + //UppercutTimer + if (UppercutTimer <= diff) { - DoCast(me->getVictim(), SPELL_UPPERCUT); - Uppercut_Timer = 12000; + DoCastVictim(SPELL_UPPERCUT); + UppercutTimer = 12000; } - else Uppercut_Timer -= diff; + else UppercutTimer -= diff; - //Adds_Timer - if (!Invisible && Adds_Timer <= diff) + //AddsTimer + if (!Invisible && AddsTimer <= diff) { //Interrupt any spell casting //me->m_canMove = true; @@ -124,11 +124,11 @@ public: SummonAdds(me->getVictim()); SummonAdds(me->getVictim()); Invisible = true; - Invisible_Timer = 15000; + InvisibleTimer = 15000; - Adds_Timer = 40000; + AddsTimer = 40000; } - else Adds_Timer -= diff; + else AddsTimer -= diff; DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp index 039d30071d2..1f887d7ce64 100644 --- a/src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp +++ b/src/server/scripts/Kalimdor/Maraudon/boss_princess_theradras.cpp @@ -23,7 +23,8 @@ SDComment: SDCategory: Maraudon EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" enum Spells { @@ -47,17 +48,17 @@ public: { boss_ptheradrasAI(Creature* creature) : ScriptedAI(creature) {} - uint32 Dustfield_Timer; - uint32 Boulder_Timer; - uint32 Thrash_Timer; - uint32 RepulsiveGaze_Timer; + uint32 DustfieldTimer; + uint32 BoulderTimer; + uint32 ThrashTimer; + uint32 RepulsiveGazeTimer; void Reset() { - Dustfield_Timer = 8000; - Boulder_Timer = 2000; - Thrash_Timer = 5000; - RepulsiveGaze_Timer = 23000; + DustfieldTimer = 8000; + BoulderTimer = 2000; + ThrashTimer = 5000; + RepulsiveGazeTimer = 23000; } void EnterCombat(Unit* /*who*/) {} @@ -72,40 +73,38 @@ public: if (!UpdateVictim()) return; - //Dustfield_Timer - if (Dustfield_Timer <= diff) + //DustfieldTimer + if (DustfieldTimer <= diff) { DoCast(me, SPELL_DUSTFIELD); - Dustfield_Timer = 14000; + DustfieldTimer = 14000; } - else Dustfield_Timer -= diff; + else DustfieldTimer -= diff; - //Boulder_Timer - if (Boulder_Timer <= diff) + //BoulderTimer + if (BoulderTimer <= diff) { - Unit* target = NULL; - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) DoCast(target, SPELL_BOULDER); - Boulder_Timer = 10000; + BoulderTimer = 10000; } - else Boulder_Timer -= diff; + else BoulderTimer -= diff; - //RepulsiveGaze_Timer - if (RepulsiveGaze_Timer <= diff) + //RepulsiveGazeTimer + if (RepulsiveGazeTimer <= diff) { - DoCast(me->getVictim(), SPELL_REPULSIVEGAZE); - RepulsiveGaze_Timer = 20000; + DoCastVictim(SPELL_REPULSIVEGAZE); + RepulsiveGazeTimer = 20000; } - else RepulsiveGaze_Timer -= diff; + else RepulsiveGazeTimer -= diff; - //Thrash_Timer - if (Thrash_Timer <= diff) + //ThrashTimer + if (ThrashTimer <= diff) { DoCast(me, SPELL_THRASH); - Thrash_Timer = 18000; + ThrashTimer = 18000; } - else Thrash_Timer -= diff; + else ThrashTimer -= diff; DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 6e6e089ba02..1fdf941d75c 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -25,10 +25,15 @@ SDComment: <Known bugs> SDCategory: Onyxia's Lair EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" #include "onyxias_lair.h" -enum eYells +enum Yells { SAY_AGGRO = -1249000, SAY_KILL = -1249001, @@ -37,7 +42,7 @@ enum eYells EMOTE_BREATH = -1249004, }; -enum eSpells +enum Spells { // Phase 1 spells SPELL_WING_BUFFET = 18500, @@ -67,15 +72,15 @@ enum eSpells SPELL_BELLOWING_ROAR = 18431, }; -struct sOnyxMove +struct OnyxMove { - uint32 uiLocId; - uint32 uiLocIdEnd; - uint32 uiSpellId; + uint8 LocId; + uint8 LocIdEnd; + uint32 SpellId; float fX, fY, fZ; }; -static sOnyxMove aMoveData[]= +static OnyxMove MoveData[8]= { {0, 1, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -56.9457f}, //west {1, 0, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -55.1278f}, //east @@ -87,11 +92,11 @@ static sOnyxMove aMoveData[]= {7, 6, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -55.0548f}, //north }; -const Position MiddleRoomLocation = {-23.6155f, -215.357f, -55.7344f, 0.0f}; +Position const MiddleRoomLocation = {-23.6155f, -215.357f, -55.7344f, 0.0f}; -const Position Phase2Location = {-80.924f, -214.299f, -82.942f, 0.0f}; +Position const Phase2Location = {-80.924f, -214.299f, -82.942f, 0.0f}; -static Position aSpawnLocations[3]= +Position const SpawnLocations[3]= { //Whelps {-30.127f, -254.463f, -89.440f, 0.0f}, @@ -121,58 +126,58 @@ public: InstanceScript* instance; SummonList Summons; - uint32 m_uiPhase; + uint32 Phase; - uint32 m_uiFlameBreathTimer; - uint32 m_uiCleaveTimer; - uint32 m_uiTailSweepTimer; - uint32 m_uiWingBuffetTimer; + uint32 FlameBreathTimer; + uint32 CleaveTimer; + uint32 TailSweepTimer; + uint32 WingBuffetTimer; - uint32 m_uiMovePoint; - uint32 m_uiMovementTimer; - sOnyxMove* m_pPointData; + uint8 MovePoint; + uint32 MovementTimer; + OnyxMove* PointData; - uint32 m_uiFireballTimer; - uint32 m_uiWhelpTimer; - uint32 m_uiLairGuardTimer; - uint32 m_uiDeepBreathTimer; + uint32 FireballTimer; + uint32 WhelpTimer; + uint32 LairGuardTimer; + uint32 DeepBreathTimer; - uint32 m_uiBellowingRoarTimer; + uint32 BellowingRoarTimer; - uint8 m_uiSummonWhelpCount; - bool m_bIsMoving; + uint8 SummonWhelpCount; + bool IsMoving; void Reset() { if (!IsCombatMovementAllowed()) SetCombatMovement(true); - m_uiPhase = PHASE_START; + Phase = PHASE_START; - m_uiFlameBreathTimer = urand(10000, 20000); - m_uiTailSweepTimer = urand(15000, 20000); - m_uiCleaveTimer = urand(2000, 5000); - m_uiWingBuffetTimer = urand(10000, 20000); + FlameBreathTimer = urand(10000, 20000); + TailSweepTimer = urand(15000, 20000); + CleaveTimer = urand(2000, 5000); + WingBuffetTimer = urand(10000, 20000); - m_uiMovePoint = urand(0, 5); - m_uiMovementTimer = 14000; - m_pPointData = GetMoveData(); + MovePoint = urand(0, 5); + MovementTimer = 14000; + PointData = GetMoveData(); - m_uiFireballTimer = 15000; - m_uiWhelpTimer = 60000; - m_uiLairGuardTimer = 60000; - m_uiDeepBreathTimer = 85000; + FireballTimer = 15000; + WhelpTimer = 60000; + LairGuardTimer = 60000; + DeepBreathTimer = 85000; - m_uiBellowingRoarTimer = 30000; + BellowingRoarTimer = 30000; Summons.DespawnAll(); - m_uiSummonWhelpCount = 0; - m_bIsMoving = false; + SummonWhelpCount = 0; + IsMoving = false; if (instance) { instance->SetData(DATA_ONYXIA, NOT_STARTED); - instance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + instance->SetData(DATA_ONYXIA_PHASE, Phase); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); } } @@ -206,7 +211,7 @@ public: switch (summoned->GetEntry()) { case NPC_WHELP: - ++m_uiSummonWhelpCount; + ++SummonWhelpCount; break; case NPC_LAIRGUARD: summoned->setActive(true); @@ -225,17 +230,17 @@ public: DoScriptText(SAY_KILL, me); } - void SpellHit(Unit* /*pCaster*/, const SpellInfo* pSpell) + void SpellHit(Unit* /*pCaster*/, const SpellInfo* Spell) { - if (pSpell->Id == SPELL_BREATH_EAST_TO_WEST || - pSpell->Id == SPELL_BREATH_WEST_TO_EAST || - pSpell->Id == SPELL_BREATH_SE_TO_NW || - pSpell->Id == SPELL_BREATH_NW_TO_SE || - pSpell->Id == SPELL_BREATH_SW_TO_NE || - pSpell->Id == SPELL_BREATH_NE_TO_SW) + if (Spell->Id == SPELL_BREATH_EAST_TO_WEST || + Spell->Id == SPELL_BREATH_WEST_TO_EAST || + Spell->Id == SPELL_BREATH_SE_TO_NW || + Spell->Id == SPELL_BREATH_NW_TO_SE || + Spell->Id == SPELL_BREATH_SW_TO_NE || + Spell->Id == SPELL_BREATH_NE_TO_SW) { - m_pPointData = GetMoveData(); - m_uiMovePoint = m_pPointData->uiLocIdEnd; + PointData = GetMoveData(); + MovePoint = PointData->LocIdEnd; me->SetSpeed(MOVE_FLIGHT, 1.5f); me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation); @@ -249,16 +254,16 @@ public: switch (id) { case 8: - m_pPointData = GetMoveData(); - if (m_pPointData) + PointData = GetMoveData(); + if (PointData) { me->SetSpeed(MOVE_FLIGHT, 1.0f); - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + me->GetMotionMaster()->MovePoint(PointData->LocId, PointData->fX, PointData->fY, PointData->fZ); } break; case 9: me->GetMotionMaster()->MoveChase(me->getVictim()); - m_uiBellowingRoarTimer = 1000; + BellowingRoarTimer = 1000; break; case 10: me->SetCanFly(true); @@ -266,39 +271,39 @@ public: me->SetSpeed(MOVE_FLIGHT, 1.0f); DoScriptText(SAY_PHASE_2_TRANS, me); if (instance) - instance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); - m_uiWhelpTimer = 5000; - m_uiLairGuardTimer = 15000; + instance->SetData(DATA_ONYXIA_PHASE, Phase); + WhelpTimer = 5000; + LairGuardTimer = 15000; break; case 11: - if (m_pPointData) - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); + if (PointData) + me->GetMotionMaster()->MovePoint(PointData->LocId, PointData->fX, PointData->fY, PointData->fZ); me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MoveIdle(); break; default: - m_bIsMoving = false; + IsMoving = false; break; } } } - void SpellHitTarget(Unit* target, const SpellInfo* pSpell) + void SpellHitTarget(Unit* target, const SpellInfo* Spell) { //Workaround - Couldn't find a way to group this spells (All Eruption) - if (((pSpell->Id >= 17086 && pSpell->Id <= 17095) || - (pSpell->Id == 17097) || - (pSpell->Id >= 18351 && pSpell->Id <= 18361) || - (pSpell->Id >= 18564 && pSpell->Id <= 18576) || - (pSpell->Id >= 18578 && pSpell->Id <= 18607) || - (pSpell->Id == 18609) || - (pSpell->Id >= 18611 && pSpell->Id <= 18628) || - (pSpell->Id >= 21132 && pSpell->Id <= 21133) || - (pSpell->Id >= 21135 && pSpell->Id <= 21139) || - (pSpell->Id >= 22191 && pSpell->Id <= 22202) || - (pSpell->Id >= 22267 && pSpell->Id <= 22268)) && + if (((Spell->Id >= 17086 && Spell->Id <= 17095) || + (Spell->Id == 17097) || + (Spell->Id >= 18351 && Spell->Id <= 18361) || + (Spell->Id >= 18564 && Spell->Id <= 18576) || + (Spell->Id >= 18578 && Spell->Id <= 18607) || + (Spell->Id == 18609) || + (Spell->Id >= 18611 && Spell->Id <= 18628) || + (Spell->Id >= 21132 && Spell->Id <= 21133) || + (Spell->Id >= 21135 && Spell->Id <= 21139) || + (Spell->Id >= 22191 && Spell->Id <= 22202) || + (Spell->Id >= 22267 && Spell->Id <= 22268)) && (target->GetTypeId() == TYPEID_PLAYER)) { if (instance) @@ -308,14 +313,14 @@ public: } } - sOnyxMove* GetMoveData() + OnyxMove* GetMoveData() { - uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); + uint8 MaxCount = sizeof(MoveData)/sizeof(OnyxMove); - for (uint32 i = 0; i < uiMaxCount; ++i) + for (uint8 i = 0; i < MaxCount; ++i) { - if (aMoveData[i].uiLocId == m_uiMovePoint) - return &aMoveData[i]; + if (MoveData[i].LocId == MovePoint) + return &MoveData[i]; } return NULL; @@ -323,84 +328,84 @@ public: void SetNextRandomPoint() { - uint32 uiMaxCount = sizeof(aMoveData)/sizeof(sOnyxMove); + uint8 MaxCount = sizeof(MoveData)/sizeof(OnyxMove); - uint32 iTemp = rand()%(uiMaxCount-1); + uint8 iTemp = urand(0, MaxCount-1); - if (iTemp >= m_uiMovePoint) + if (iTemp >= MovePoint) ++iTemp; - m_uiMovePoint = iTemp; + MovePoint = iTemp; } - void UpdateAI(const uint32 uiDiff) + void UpdateAI(const uint32 Diff) { if (!UpdateVictim()) return; //Common to PHASE_START && PHASE_END - if (m_uiPhase == PHASE_START || m_uiPhase == PHASE_END) + if (Phase == PHASE_START || Phase == PHASE_END) { //Specific to PHASE_START || PHASE_END - if (m_uiPhase == PHASE_START) + if (Phase == PHASE_START) { if (HealthBelowPct(60)) { SetCombatMovement(false); - m_uiPhase = PHASE_BREATH; + Phase = PHASE_BREATH; me->GetMotionMaster()->MovePoint(10, Phase2Location); return; } } else { - if (m_uiBellowingRoarTimer <= uiDiff) + if (BellowingRoarTimer <= Diff) { DoCastVictim(SPELL_BELLOWING_ROAR); // Eruption - GameObject* pFloor = NULL; + GameObject* Floor = NULL; Trinity::GameObjectInRangeCheck check(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 15); - Trinity::GameObjectLastSearcher<Trinity::GameObjectInRangeCheck> searcher(me, pFloor, check); + Trinity::GameObjectLastSearcher<Trinity::GameObjectInRangeCheck> searcher(me, Floor, check); me->VisitNearbyGridObject(30, searcher); - if (instance && pFloor) - instance->SetData64(DATA_FLOOR_ERUPTION_GUID, pFloor->GetGUID()); - m_uiBellowingRoarTimer = 30000; + if (instance && Floor) + instance->SetData64(DATA_FLOOR_ERUPTION_GUID, Floor->GetGUID()); + BellowingRoarTimer = 30000; } else - m_uiBellowingRoarTimer -= uiDiff; + BellowingRoarTimer -= Diff; } - if (m_uiFlameBreathTimer <= uiDiff) + if (FlameBreathTimer <= Diff) { DoCastVictim(SPELL_FLAME_BREATH); - m_uiFlameBreathTimer = urand(10000, 20000); + FlameBreathTimer = urand(10000, 20000); } else - m_uiFlameBreathTimer -= uiDiff; + FlameBreathTimer -= Diff; - if (m_uiTailSweepTimer <= uiDiff) + if (TailSweepTimer <= Diff) { DoCastAOE(SPELL_TAIL_SWEEP); - m_uiTailSweepTimer = urand(15000, 20000); + TailSweepTimer = urand(15000, 20000); } else - m_uiTailSweepTimer -= uiDiff; + TailSweepTimer -= Diff; - if (m_uiCleaveTimer <= uiDiff) + if (CleaveTimer <= Diff) { DoCastVictim(SPELL_CLEAVE); - m_uiCleaveTimer = urand(2000, 5000); + CleaveTimer = urand(2000, 5000); } else - m_uiCleaveTimer -= uiDiff; + CleaveTimer -= Diff; - if (m_uiWingBuffetTimer <= uiDiff) + if (WingBuffetTimer <= Diff) { DoCastVictim(SPELL_WING_BUFFET); - m_uiWingBuffetTimer = urand(15000, 30000); + WingBuffetTimer = urand(15000, 30000); } else - m_uiWingBuffetTimer -= uiDiff; + WingBuffetTimer -= Diff; DoMeleeAttackIfReady(); } @@ -408,86 +413,86 @@ public: { if (HealthBelowPct(40)) { - m_uiPhase = PHASE_END; + Phase = PHASE_END; if (instance) - instance->SetData(DATA_ONYXIA_PHASE, m_uiPhase); + instance->SetData(DATA_ONYXIA_PHASE, Phase); DoScriptText(SAY_PHASE_3_TRANS, me); SetCombatMovement(true); me->SetCanFly(false); - m_bIsMoving = false; + IsMoving = false; me->GetMotionMaster()->MovePoint(9, me->GetHomePosition()); return; } - if (m_uiDeepBreathTimer <= uiDiff) + if (DeepBreathTimer <= Diff) { - if (!m_bIsMoving) + if (!IsMoving) { if (me->IsNonMeleeSpellCasted(false)) me->InterruptNonMeleeSpells(false); DoScriptText(EMOTE_BREATH, me); - DoCast(me, m_pPointData->uiSpellId); - m_uiDeepBreathTimer = 70000; + DoCast(me, PointData->SpellId); + DeepBreathTimer = 70000; } } else - m_uiDeepBreathTimer -= uiDiff; + DeepBreathTimer -= Diff; - if (m_uiMovementTimer <= uiDiff) + if (MovementTimer <= Diff) { - if (!m_bIsMoving) + if (!IsMoving) { SetNextRandomPoint(); - m_pPointData = GetMoveData(); + PointData = GetMoveData(); - if (!m_pPointData) + if (!PointData) return; - me->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ); - m_bIsMoving = true; - m_uiMovementTimer = 25000; + me->GetMotionMaster()->MovePoint(PointData->LocId, PointData->fX, PointData->fY, PointData->fZ); + IsMoving = true; + MovementTimer = 25000; } } else - m_uiMovementTimer -= uiDiff; + MovementTimer -= Diff; - if (m_uiFireballTimer <= uiDiff) + if (FireballTimer <= Diff) { if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) DoCast(target, SPELL_FIREBALL); - m_uiFireballTimer = 8000; + FireballTimer = 8000; } } else - m_uiFireballTimer -= uiDiff; + FireballTimer -= Diff; - if (m_uiLairGuardTimer <= uiDiff) + if (LairGuardTimer <= Diff) { - me->SummonCreature(NPC_LAIRGUARD, aSpawnLocations[2].GetPositionX(), aSpawnLocations[2].GetPositionY(), aSpawnLocations[2].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - m_uiLairGuardTimer = 30000; + me->SummonCreature(NPC_LAIRGUARD, SpawnLocations[2], TEMPSUMMON_CORPSE_DESPAWN); + LairGuardTimer = 30000; } else - m_uiLairGuardTimer -= uiDiff; + LairGuardTimer -= Diff; - if (m_uiWhelpTimer <= uiDiff) + if (WhelpTimer <= Diff) { - me->SummonCreature(NPC_WHELP, aSpawnLocations[0].GetPositionX(), aSpawnLocations[0].GetPositionY(), aSpawnLocations[0].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - me->SummonCreature(NPC_WHELP, aSpawnLocations[1].GetPositionX(), aSpawnLocations[1].GetPositionY(), aSpawnLocations[1].GetPositionZ(), 0.0f, TEMPSUMMON_CORPSE_DESPAWN); - if (m_uiSummonWhelpCount >= RAID_MODE(20, 40)) + me->SummonCreature(NPC_WHELP, SpawnLocations[0], TEMPSUMMON_CORPSE_DESPAWN); + me->SummonCreature(NPC_WHELP, SpawnLocations[1], TEMPSUMMON_CORPSE_DESPAWN); + if (SummonWhelpCount >= RAID_MODE(20, 40)) { - m_uiSummonWhelpCount = 0; - m_uiWhelpTimer = 90000; + SummonWhelpCount = 0; + WhelpTimer = 90000; } else - m_uiWhelpTimer = 500; + WhelpTimer = 500; } else - m_uiWhelpTimer -= uiDiff; + WhelpTimer -= Diff; } } }; diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp index 1c599ce7c6f..0689a8872bb 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp @@ -22,7 +22,12 @@ SDComment: SDCategory: Onyxia's Lair EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "InstanceScript.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" #include "onyxias_lair.h" class instance_onyxias_lair : public InstanceMapScript @@ -44,27 +49,27 @@ public: std::map<uint64, uint32> FloorEruptionGUID[2]; std::queue<uint64> FloorEruptionGUIDQueue; - uint64 m_uiOnyxiasGUID; - uint32 m_uiOnyxiaLiftoffTimer; - uint32 m_uiManyWhelpsCounter; - uint32 m_uiEruptTimer; + uint64 OnyxiasGUID; + uint32 OnyxiaLiftoffTimer; + uint32 ManyWhelpsCounter; + uint32 EruptTimer; - uint8 m_auiEncounter[MAX_ENCOUNTER]; + uint8 Encounter[MAX_ENCOUNTER]; - bool m_bAchievManyWhelpsHandleIt; - bool m_bAchievSheDeepBreathMore; + bool AchievManyWhelpsHandleIt; + bool AchievSheDeepBreathMore; void Initialize() { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + memset(&Encounter, 0, sizeof(Encounter)); - m_uiOnyxiasGUID = 0; - m_uiOnyxiaLiftoffTimer = 0; - m_uiManyWhelpsCounter = 0; - m_bAchievManyWhelpsHandleIt = false; - m_bAchievSheDeepBreathMore = true; + OnyxiasGUID = 0; + OnyxiaLiftoffTimer = 0; + ManyWhelpsCounter = 0; + AchievManyWhelpsHandleIt = false; + AchievSheDeepBreathMore = true; - m_uiEruptTimer = 0; + EruptTimer = 0; } void OnCreatureCreate(Creature* creature) @@ -72,7 +77,7 @@ public: switch (creature->GetEntry()) { case NPC_ONYXIA: - m_uiOnyxiasGUID = creature->GetGUID(); + OnyxiasGUID = creature->GetGUID(); break; } } @@ -93,7 +98,7 @@ public: if (Creature* temp = go->SummonCreature(NPC_WHELP, goPos, TEMPSUMMON_CORPSE_DESPAWN)) { temp->SetInCombatWithZone(); - ++m_uiManyWhelpsCounter; + ++ManyWhelpsCounter; } break; } @@ -139,88 +144,88 @@ public: FloorEruptionGUID[1].erase(floorEruptedGUID); } - void SetData(uint32 uiType, uint32 uiData) + void SetData(uint32 Type, uint32 Data) { - switch (uiType) + switch (Type) { case DATA_ONYXIA: - m_auiEncounter[0] = uiData; - if (uiData == IN_PROGRESS) + Encounter[0] = Data; + if (Data == IN_PROGRESS) SetData(DATA_SHE_DEEP_BREATH_MORE, IN_PROGRESS); break; case DATA_ONYXIA_PHASE: - if (uiData == PHASE_BREATH) //Used to mark the liftoff phase + if (Data == PHASE_BREATH) //Used to mark the liftoff phase { - m_bAchievManyWhelpsHandleIt = false; - m_uiManyWhelpsCounter = 0; - m_uiOnyxiaLiftoffTimer = 10*IN_MILLISECONDS; + AchievManyWhelpsHandleIt = false; + ManyWhelpsCounter = 0; + OnyxiaLiftoffTimer = 10*IN_MILLISECONDS; } break; case DATA_SHE_DEEP_BREATH_MORE: - if (uiData == IN_PROGRESS) + if (Data == IN_PROGRESS) { - m_bAchievSheDeepBreathMore = true; + AchievSheDeepBreathMore = true; } - else if (uiData == FAIL) + else if (Data == FAIL) { - m_bAchievSheDeepBreathMore = false; + AchievSheDeepBreathMore = false; } break; } - if (uiType < MAX_ENCOUNTER && uiData == DONE) + if (Type < MAX_ENCOUNTER && Data == DONE) SaveToDB(); } - void SetData64(uint32 uiType, uint64 uiData) + void SetData64(uint32 Type, uint64 Data) { - switch (uiType) + switch (Type) { case DATA_FLOOR_ERUPTION_GUID: FloorEruptionGUID[1] = FloorEruptionGUID[0]; - FloorEruptionGUIDQueue.push(uiData); - m_uiEruptTimer = 2500; + FloorEruptionGUIDQueue.push(Data); + EruptTimer = 2500; break; } } - uint32 GetData(uint32 uiType) + uint32 GetData(uint32 Type) { - switch (uiType) + switch (Type) { case DATA_ONYXIA: - return m_auiEncounter[0]; + return Encounter[0]; } return 0; } - uint64 GetData64(uint32 uiData) + uint64 GetData64(uint32 Data) { - switch (uiData) + switch (Data) { case DATA_ONYXIA_GUID: - return m_uiOnyxiasGUID; + return OnyxiasGUID; } return 0; } - void Update(uint32 uiDiff) + void Update(uint32 Diff) { if (GetData(DATA_ONYXIA) == IN_PROGRESS) { - if (m_uiOnyxiaLiftoffTimer && m_uiOnyxiaLiftoffTimer <= uiDiff) + if (OnyxiaLiftoffTimer && OnyxiaLiftoffTimer <= Diff) { - m_uiOnyxiaLiftoffTimer = 0; - if (m_uiManyWhelpsCounter >= 50) - m_bAchievManyWhelpsHandleIt = true; - } else m_uiOnyxiaLiftoffTimer -= uiDiff; + OnyxiaLiftoffTimer = 0; + if (ManyWhelpsCounter >= 50) + AchievManyWhelpsHandleIt = true; + } else OnyxiaLiftoffTimer -= Diff; } if (!FloorEruptionGUIDQueue.empty()) { - if (m_uiEruptTimer <= uiDiff) + if (EruptTimer <= Diff) { uint32 treeHeight = 0; do @@ -229,10 +234,10 @@ public: FloorEruption(FloorEruptionGUIDQueue.front()); FloorEruptionGUIDQueue.pop(); } while (!FloorEruptionGUIDQueue.empty() && (*FloorEruptionGUID[1].find(FloorEruptionGUIDQueue.front())).second == treeHeight); - m_uiEruptTimer = 1000; + EruptTimer = 1000; } else - m_uiEruptTimer -= uiDiff; + EruptTimer -= Diff; } } @@ -242,10 +247,10 @@ public: { case ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER: // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s case ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER: // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s - return m_bAchievManyWhelpsHandleIt; + return AchievManyWhelpsHandleIt; case ACHIEV_CRITERIA_DEEP_BREATH_10_PLAYER: // Criteria for achievement 4404: She Deep Breaths More (10 player) Everybody evade Deep Breath case ACHIEV_CRITERIA_DEEP_BREATH_25_PLAYER: // Criteria for achievement 4407: She Deep Breaths More (25 player) Everybody evade Deep Breath - return m_bAchievSheDeepBreathMore; + return AchievSheDeepBreathMore; } return false; } diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h b/src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h index eaf6cac43af..26fd9284ea2 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h +++ b/src/server/scripts/Kalimdor/OnyxiasLair/onyxias_lair.h @@ -18,13 +18,13 @@ #ifndef DEF_ONYXIAS_LAIR_H #define DEF_ONYXIAS_LAIR_H -enum eData64 +enum Data64 { DATA_ONYXIA_GUID, DATA_FLOOR_ERUPTION_GUID }; -enum eInstanceData +enum InstanceData { DATA_ONYXIA, MAX_ENCOUNTER, @@ -34,7 +34,7 @@ enum eInstanceData DATA_MANY_WHELPS_COUNT }; -enum eCreatures +enum Creatures { NPC_WHELP = 11262, NPC_LAIRGUARD = 36561, @@ -42,20 +42,20 @@ enum eCreatures NPC_ONYXIA = 10184 }; -enum eOnyxiaPhases +enum OnyxiaPhases { PHASE_START = 1, PHASE_BREATH = 2, PHASE_END = 3 }; -enum eGameObjects +enum GameObjects { GO_WHELP_SPAWNER = 176510, GO_WHELP_EGG = 176511 }; -enum eAchievementData +enum AchievementData { ACHIEV_CRITERIA_MANY_WHELPS_10_PLAYER = 12565, // Criteria for achievement 4403: Many Whelps! Handle It! (10 player) Hatch 50 eggs in 10s ACHIEV_CRITERIA_MANY_WHELPS_25_PLAYER = 12568, // Criteria for achievement 4406: Many Whelps! Handle It! (25 player) Hatch 50 eggs in 10s diff --git a/src/server/scripts/Kalimdor/ashenvale.cpp b/src/server/scripts/Kalimdor/ashenvale.cpp index e28665c038e..9e8cdaa8b92 100644 --- a/src/server/scripts/Kalimdor/ashenvale.cpp +++ b/src/server/scripts/Kalimdor/ashenvale.cpp @@ -169,15 +169,15 @@ class npc_torek : public CreatureScript # npc_ruul_snowhoof ####*/ -enum RuulSnowhoof -{ +enum RuulSnowhoof +{ NPC_THISTLEFUR_URSA = 3921, NPC_THISTLEFUR_TOTEMIC = 3922, NPC_THISTLEFUR_PATHFINDER = 3926, QUEST_FREEDOM_TO_RUUL = 6482, - GO_CAGE = 178147 + GO_CAGE = 178147 }; Position const RuulSnowhoofSummonsCoord[6] = diff --git a/src/server/scripts/Kalimdor/dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/dustwallow_marsh.cpp index 45e1c1808c1..5800a6a58a0 100644 --- a/src/server/scripts/Kalimdor/dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/dustwallow_marsh.cpp @@ -25,7 +25,6 @@ EndScriptData */ /* ContentData mobs_risen_husk_spirit -npc_deserter_agitator npc_lady_jaina_proudmoore npc_nat_pagle npc_private_hendel @@ -132,93 +131,7 @@ class mobs_risen_husk_spirit : public CreatureScript }; /*###### -## npc_deserter_agitator -######*/ - -enum Deserter -{ - QUEST_TRAITORS_AMONG_US = 11126, - NPC_THERAMORE_DESERTER = 23602, -}; - -const Position DeserterDisappearPos = {-3609.03f, -4332.91f, 9.39354f, 3.73862f}; - -#define GOSSIP_ITEM_DESERTER "Your propaganda wont`t work on me. Spout your treasonous filth elsewhere traitor!" - -class npc_deserter_agitator : public CreatureScript -{ -public: - npc_deserter_agitator() : CreatureScript("npc_deserter_agitator") { } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (player->GetQuestStatus(QUEST_TRAITORS_AMONG_US) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DESERTER, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - - if (action == GOSSIP_SENDER_INFO) - { - player->CLOSE_GOSSIP_MENU(); - switch (urand(0, 1)) - { - case 0: - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - creature->setFaction(14); - creature->AI()->AttackStart(player); - break; - case 1: - player->KilledMonsterCredit(NPC_THERAMORE_DESERTER, 0); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - creature->SetSpeed(MOVE_RUN, creature->GetSpeedRate(MOVE_RUN), true); - creature->setFaction(35); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); - creature->SetReactState(REACT_PASSIVE); - creature->GetMotionMaster()->MovePoint(1, DeserterDisappearPos); - break; - } - } - - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_deserter_agitatorAI(creature); - } - - struct npc_deserter_agitatorAI : public ScriptedAI - { - npc_deserter_agitatorAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() - { - me->RestoreFaction(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_AGGRESSIVE); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - void MovementInform(uint32 Type, uint32 Id) - { - if (Type != POINT_MOTION_TYPE) - return; - - if (Id == 1) - me->DisappearAndDie(); - } - }; -}; - -/*###### -## npc_deserter_agitator +## npc_theramor_guard ######*/ enum TheramoreGuard @@ -794,16 +707,16 @@ class spell_energize_aoe : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end();) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { if ((*itr)->GetTypeId() == TYPEID_PLAYER && (*itr)->ToPlayer()->GetQuestStatus(GetSpellInfo()->Effects[EFFECT_1].CalcValue()) == QUEST_STATUS_INCOMPLETE) ++itr; else - unitList.erase(itr++); + targets.erase(itr++); } - unitList.push_back(GetCaster()); + targets.push_back(GetCaster()); } void HandleScript(SpellEffIndex effIndex) @@ -815,8 +728,8 @@ class spell_energize_aoe : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_energize_aoe_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - OnUnitTargetSelect += SpellUnitTargetFn(spell_energize_aoe_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_energize_aoe_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_energize_aoe_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_energize_aoe_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENTRY); } }; @@ -865,7 +778,6 @@ void AddSC_dustwallow_marsh() new npc_zelfrax(); new npc_stinky(); new npc_theramore_guard(); - new npc_deserter_agitator(); new spell_ooze_zap(); new spell_ooze_zap_channel_end(); new spell_energize_aoe(); diff --git a/src/server/scripts/Kalimdor/winterspring.cpp b/src/server/scripts/Kalimdor/winterspring.cpp index a02156ee110..2c4da0fdf7c 100644 --- a/src/server/scripts/Kalimdor/winterspring.cpp +++ b/src/server/scripts/Kalimdor/winterspring.cpp @@ -18,15 +18,13 @@ /* ScriptData SDName: Winterspring -SD%Complete: 90 -SDComment: Quest support: 5126 (Loraxs' tale missing proper gossip items text). Vendor Rivern Frostwind. Obtain Cache of Mau'ari +SD%Complete: Almost Completely Emptied +SDComment: Vendor Rivern Frostwind. SDCategory: Winterspring EndScriptData */ /* ContentData -npc_lorax npc_rivern_frostwind -npc_witch_doctor_mauari EndContentData */ #include "ScriptMgr.h" @@ -34,71 +32,6 @@ EndContentData */ #include "ScriptedGossip.h" /*###### -## npc_lorax -######*/ - -#define GOSSIP_HL "Talk to me" - -#define GOSSIP_SL1 "What do you do here?" -#define GOSSIP_SL2 "I can help you" -#define GOSSIP_SL3 "What deal?" -#define GOSSIP_SL4 "Then what happened?" -#define GOSSIP_SL5 "He is not safe, i'll make sure of that." - -class npc_lorax : public CreatureScript -{ -public: - npc_lorax() : CreatureScript("npc_lorax") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(3759, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(3760, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(3761, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->SEND_GOSSIP_MENU(3762, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(3763, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(5126); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(5126) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } - -}; - -/*###### ## npc_rivern_frostwind ######*/ @@ -131,49 +64,7 @@ public: }; -/*###### -## npc_witch_doctor_mauari -######*/ - -#define GOSSIP_HWDM "I'd like you to make me a new Cache of Mau'ari please." - -class npc_witch_doctor_mauari : public CreatureScript -{ -public: - npc_witch_doctor_mauari() : CreatureScript("npc_witch_doctor_mauari") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - player->CLOSE_GOSSIP_MENU(); - creature->CastSpell(player, 16351, false); - } - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestRewardStatus(975)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HWDM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(3377, creature->GetGUID()); - } - else - player->SEND_GOSSIP_MENU(3375, creature->GetGUID()); - - return true; - } -}; - void AddSC_winterspring() { - new npc_lorax(); new npc_rivern_frostwind(); - new npc_witch_doctor_mauari(); } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp index 4e5e01cc745..5a7809dbe70 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp @@ -186,7 +186,7 @@ class ConflagrationTargetSelector public: ConflagrationTargetSelector() { } - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) const { return unit->GetTypeId() != TYPEID_PLAYER; } @@ -201,12 +201,12 @@ class spell_saviana_conflagration_init : public SpellScriptLoader { PrepareSpellScript(spell_saviana_conflagration_init_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if (ConflagrationTargetSelector()); + targets.remove_if(ConflagrationTargetSelector()); uint8 maxSize = uint8(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 6 : 3); - if (unitList.size() > maxSize) - Trinity::Containers::RandomResizeList(unitList, maxSize); + if (targets.size() > maxSize) + Trinity::Containers::RandomResizeList(targets, maxSize); } void HandleDummy(SpellEffIndex effIndex) @@ -218,7 +218,7 @@ class spell_saviana_conflagration_init : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_saviana_conflagration_init_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_saviana_conflagration_init_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_saviana_conflagration_init_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp index 305266ee628..e96408acc09 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp @@ -60,9 +60,9 @@ class OrientationCheck : public std::unary_function<Unit*, bool> { public: explicit OrientationCheck(Unit* _caster) : caster(_caster) { } - bool operator() (Unit* unit) + bool operator()(WorldObject* object) { - return !unit->isInFront(caster, 2.5f) || !unit->IsWithinDist(caster, 40.0f); + return !object->isInFront(caster, 2.5f) || !object->IsWithinDist(caster, 40.0f); } private: @@ -76,15 +76,16 @@ class spell_eadric_radiance : public SpellScriptLoader class spell_eadric_radiance_SpellScript : public SpellScript { PrepareSpellScript(spell_eadric_radiance_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (OrientationCheck(GetCaster())); + unitList.remove_if(OrientationCheck(GetCaster())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_eadric_radiance_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index 79bbb470edf..3b0aeb958cb 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -27,7 +27,10 @@ EndScriptData */ // All - untested // Pets aren't being summoned by their masters -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "trial_of_the_crusader.h" enum eYell @@ -945,18 +948,18 @@ public: }; -enum eWarlockSpells +enum WarlockSpells { - SPELL_HELLFIRE = 65816, - SPELL_CORRUPTION = 65810, - SPELL_CURSE_OF_AGONY = 65814, - SPELL_CURSE_OF_EXHAUSTION = 65815, - SPELL_FEAR = 65809, //8s - SPELL_SEARING_PAIN = 65819, - SPELL_SHADOW_BOLT = 65821, - SPELL_UNSTABLE_AFFLICTION = 65812, - SPELL_SUMMON_FELHUNTER = 67514, - H_SPELL_UNSTABLE_AFFLICTION = 68155, //15s + SPELL_HELLFIRE = 65816, + SPELL_CORRUPTION = 65810, + SPELL_CURSE_OF_AGONY = 65814, + SPELL_CURSE_OF_EXHAUSTION = 65815, + SPELL_FEAR = 65809, // 8s + SPELL_SEARING_PAIN = 65819, + SPELL_SHADOW_BOLT = 65821, + SPELL_UNSTABLE_AFFLICTION = 65812, // 15s + SPELL_UNSTABLE_AFFLICTION_DISPEL = 65813, + SPELL_SUMMON_FELHUNTER = 67514, }; class mob_toc_warlock : public CreatureScript @@ -2030,6 +2033,40 @@ public: }; }; +class spell_faction_champion_warl_unstable_affliction : public SpellScriptLoader +{ + public: + spell_faction_champion_warl_unstable_affliction() : SpellScriptLoader("spell_faction_champion_warl_unstable_affliction") { } + + class spell_faction_champion_warl_unstable_affliction_AuraScript : public AuraScript + { + PrepareAuraScript(spell_faction_champion_warl_unstable_affliction_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_UNSTABLE_AFFLICTION_DISPEL)) + return false; + return true; + } + + void HandleDispel(DispelInfo* dispelInfo) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(dispelInfo->GetDispeller(), SPELL_UNSTABLE_AFFLICTION_DISPEL, true, NULL, GetEffect(EFFECT_0)); + } + + void Register() + { + AfterDispel += AuraDispelFn(spell_faction_champion_warl_unstable_affliction_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_faction_champion_warl_unstable_affliction_AuraScript(); + } +}; + void AddSC_boss_faction_champions() { new boss_toc_champion_controller(); @@ -2049,4 +2086,5 @@ void AddSC_boss_faction_champions() new mob_toc_retro_paladin(); new mob_toc_pet_warlock(); new mob_toc_pet_hunter(); + new spell_faction_champion_warl_unstable_affliction(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp index 4a28ebe6495..5b6bf14c29e 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp @@ -359,7 +359,7 @@ class DistanceCheck public: explicit DistanceCheck(Unit* _caster) : caster(_caster) { } - bool operator() (Unit* unit) + bool operator() (WorldObject* unit) const { if (caster->GetExactDist2d(unit) <= 10.0f) return true; @@ -378,25 +378,25 @@ class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader { PrepareSpellScript(spell_bronjahm_soulstorm_targeting_SpellScript); - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& targets) { - unitList.remove_if (DistanceCheck(GetCaster())); - sharedUnitList = unitList; + targets.remove_if(DistanceCheck(GetCaster())); + sharedTargets = targets; } // use the same target for first and second effect - void FilterTargetsSubsequent(std::list<Unit*>& unitList) + void FilterTargetsSubsequent(std::list<WorldObject*>& targets) { - unitList = sharedUnitList; + targets = sharedTargets; } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsInitial, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsInitial, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY); } - std::list<Unit*> sharedUnitList; + std::list<WorldObject*> sharedTargets; }; SpellScript* GetSpellScript() const diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index ee966256e2b..0d092ec86b2 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -631,9 +631,9 @@ class BloodboltHitCheck public: explicit BloodboltHitCheck(LanaThelAI* ai) : _ai(ai) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - return _ai->WasBloodbolted(unit->GetGUID()); + return _ai->WasBloodbolted(object->GetGUID()); } private: @@ -661,13 +661,13 @@ class spell_blood_queen_bloodbolt : public SpellScriptLoader return GetCaster()->GetEntry() == NPC_BLOOD_QUEEN_LANA_THEL; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { uint32 targetCount = (targets.size() + 2) / 3; - targets.remove_if (BloodboltHitCheck(static_cast<LanaThelAI*>(GetCaster()->GetAI()))); + targets.remove_if(BloodboltHitCheck(static_cast<LanaThelAI*>(GetCaster()->GetAI()))); Trinity::Containers::RandomResizeList(targets, targetCount); // mark targets now, effect hook has missile travel time delay (might cast next in that time) - for (std::list<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) GetCaster()->GetAI()->SetGUID((*itr)->GetGUID(), GUID_BLOODBOLT); } @@ -679,7 +679,7 @@ class spell_blood_queen_bloodbolt : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_blood_queen_bloodbolt_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_queen_bloodbolt_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_blood_queen_bloodbolt_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); } }; @@ -699,19 +699,19 @@ class spell_blood_queen_pact_of_the_darkfallen : public SpellScriptLoader { PrepareSpellScript(spell_blood_queen_pact_of_the_darkfallen_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if (Trinity::UnitAuraCheck(false, SPELL_PACT_OF_THE_DARKFALLEN)); + targets.remove_if(Trinity::UnitAuraCheck(false, SPELL_PACT_OF_THE_DARKFALLEN)); bool remove = true; - std::list<Unit*>::const_iterator itrEnd = unitList.end(), itr, itr2; + std::list<WorldObject*>::const_iterator itrEnd = targets.end(), itr, itr2; // we can do this, unitList is MAX 4 in size - for (itr = unitList.begin(); itr != itrEnd && remove; ++itr) + for (itr = targets.begin(); itr != itrEnd && remove; ++itr) { if (!GetCaster()->IsWithinDist(*itr, 5.0f, false)) remove = false; - for (itr2 = unitList.begin(); itr2 != itrEnd && remove; ++itr2) + for (itr2 = targets.begin(); itr2 != itrEnd && remove; ++itr2) if (itr != itr2 && !(*itr2)->IsWithinDist(*itr, 5.0f, false)) remove = false; } @@ -721,14 +721,14 @@ class spell_blood_queen_pact_of_the_darkfallen : public SpellScriptLoader if (InstanceScript* instance = GetCaster()->GetInstanceScript()) { instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN); - unitList.clear(); + targets.clear(); } } } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_blood_queen_pact_of_the_darkfallen_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_queen_pact_of_the_darkfallen_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; @@ -785,15 +785,15 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg_target : public SpellScriptLo { PrepareSpellScript(spell_blood_queen_pact_of_the_darkfallen_dmg_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (Trinity::UnitAuraCheck(true, SPELL_PACT_OF_THE_DARKFALLEN)); + unitList.remove_if(Trinity::UnitAuraCheck(true, SPELL_PACT_OF_THE_DARKFALLEN)); unitList.push_back(GetCaster()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_blood_queen_pact_of_the_darkfallen_dmg_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_blood_queen_pact_of_the_darkfallen_dmg_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 494be259baa..9017509781f 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -1198,34 +1198,34 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader return true; } - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& targets) { - if (unitList.empty()) + if (targets.empty()) return; // select one random target, with preference of ranged targets uint32 targetsAtRange = 0; uint32 const minTargets = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 10 : 4); - unitList.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); // get target count at range - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr, ++targetsAtRange) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr, ++targetsAtRange) if ((*itr)->GetDistance(GetCaster()) < 12.0f) break; // set the upper cap if (targetsAtRange < minTargets) - targetsAtRange = std::min<uint32>(unitList.size() - 1, minTargets); + targetsAtRange = std::min<uint32>(targets.size() - 1, minTargets); - std::list<Unit*>::const_iterator itr = unitList.begin(); + std::list<WorldObject*>::const_iterator itr = targets.begin(); std::advance(itr, urand(0, targetsAtRange)); target = *itr; - unitList.clear(); - unitList.push_back(target); + targets.clear(); + targets.push_back(target); } // use the same target for first and second effect - void FilterTargetsSubsequent(std::list<Unit*>& unitList) + void FilterTargetsSubsequent(std::list<WorldObject*>& unitList) { if (!target) return; @@ -1241,12 +1241,13 @@ class spell_deathbringer_blood_nova_targeting : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_deathbringer_blood_nova_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_deathbringer_blood_nova_targeting_SpellScript::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); OnEffectHitTarget += SpellEffectFn(spell_deathbringer_blood_nova_targeting_SpellScript::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); } - Unit* target; + WorldObject* target; }; SpellScript* GetSpellScript() const @@ -1269,20 +1270,20 @@ class spell_deathbringer_boiling_blood : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove(GetCaster()->getVictim()); - if (unitList.empty()) + targets.remove(GetCaster()->getVictim()); + if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_deathbringer_boiling_blood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_deathbringer_boiling_blood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 1672d8b2d87..0c5cb0aba52 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -416,7 +416,7 @@ class spell_marrowgar_coldflame : public SpellScriptLoader { PrepareSpellScript(spell_marrowgar_coldflame_SpellScript); - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { targets.clear(); // select any unit but not the tank (by owners threatlist) @@ -438,7 +438,7 @@ class spell_marrowgar_coldflame : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_marrowgar_coldflame_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_marrowgar_coldflame_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_marrowgar_coldflame_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index a0fca522f61..a9ba0baa86f 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -296,6 +296,7 @@ class boss_professor_putricide : public CreatureScript summon->ModifyAuraState(AURA_STATE_UNKNOWN22, true); summon->CastSpell(summon, SPELL_GASEOUS_BLOAT_PROC, true); summon->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, summon, false); + summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); return; case NPC_VOLATILE_OOZE: @@ -303,6 +304,7 @@ class boss_professor_putricide : public CreatureScript summon->ModifyAuraState(AURA_STATE_UNKNOWN19, true); summon->CastSpell(summon, SPELL_OOZE_ERUPTION_SEARCH_PERIODIC, true); summon->CastSpell(summon, SPELL_VOLATILE_OOZE_ADHESIVE, false); + summon->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); summon->SetReactState(REACT_PASSIVE); return; case NPC_CHOKING_GAS_BOMB: @@ -868,26 +870,26 @@ class spell_putricide_ooze_channel : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void SelectTarget(std::list<Unit*>& targetList) + void SelectTarget(std::list<WorldObject*>& targets) { - if (targetList.empty()) + if (targets.empty()) { FinishCast(SPELL_FAILED_NO_VALID_TARGETS); GetCaster()->ToCreature()->DespawnOrUnsummon(1); // despawn next update return; } - Unit* target = Trinity::Containers::SelectRandomContainerElement(targetList); - targetList.clear(); - targetList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); _target = target; } - void SetTarget(std::list<Unit*>& targetList) + void SetTarget(std::list<WorldObject*>& targets) { - targetList.clear(); + targets.clear(); if (_target) - targetList.push_back(_target); + targets.push_back(_target); } void StartAttack() @@ -910,14 +912,14 @@ class spell_putricide_ooze_channel : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_ooze_channel_SpellScript::SetTarget, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); AfterHit += SpellHitFn(spell_putricide_ooze_channel_SpellScript::StartAttack); OnCast += SpellCastFn(spell_putricide_ooze_channel_SpellScript::CheckTarget); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -931,7 +933,7 @@ class ExactDistanceCheck public: ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) const { return _source->GetExactDist2d(unit) > _dist; } @@ -950,15 +952,15 @@ class spell_putricide_slime_puddle : public SpellScriptLoader { PrepareSpellScript(spell_putricide_slime_puddle_SpellScript); - void ScaleRange(std::list<Unit*>& targets) + void ScaleRange(std::list<WorldObject*>& targets) { targets.remove_if(ExactDistanceCheck(GetCaster(), 2.5f * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X))); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_slime_puddle_SpellScript::ScaleRange, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); } }; @@ -1176,13 +1178,13 @@ class spell_putricide_eat_ooze : public SpellScriptLoader { PrepareSpellScript(spell_putricide_eat_ooze_SpellScript); - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { if (targets.empty()) return; targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); - Unit* target = targets.front(); + WorldObject* target = targets.front(); targets.clear(); targets.push_back(target); } @@ -1209,7 +1211,7 @@ class spell_putricide_eat_ooze : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_putricide_eat_ooze_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_eat_ooze_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_eat_ooze_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); } }; @@ -1456,15 +1458,15 @@ class spell_putricide_mutated_transformation_dmg : public SpellScriptLoader { PrepareSpellScript(spell_putricide_mutated_transformation_dmg_SpellScript); - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& targets) { if (Unit* owner = ObjectAccessor::GetUnit(*GetCaster(), GetCaster()->GetCreatorGUID())) - unitList.remove(owner); + targets.remove(owner); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_putricide_mutated_transformation_dmg_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_putricide_mutated_transformation_dmg_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index a4ab13f6ada..5a0560293da 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -449,23 +449,23 @@ class spell_rotface_ooze_flood : public SpellScriptLoader GetHitUnit()->CastSpell(triggers.back(), uint32(GetEffectValue()), false, NULL, NULL, GetOriginalCaster() ? GetOriginalCaster()->GetGUID() : 0); } - void FilterTargets(std::list<Unit*>& targetList) + void FilterTargets(std::list<WorldObject*>& targets) { // get 2 targets except 2 nearest - targetList.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); // .resize() runs pop_back(); - if (targetList.size() > 4) - targetList.resize(4); + if (targets.size() > 4) + targets.resize(4); - while (targetList.size() > 2) - targetList.pop_front(); + while (targets.size() > 2) + targets.pop_front(); } void Register() { OnEffectHitTarget += SpellEffectFn(spell_rotface_ooze_flood_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_ooze_flood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_ooze_flood_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); } }; @@ -490,21 +490,21 @@ class spell_rotface_mutated_infection : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { // remove targets with this aura already // tank is not on this list - targets.remove_if (Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(targets); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); targets.clear(); targets.push_back(target); _target = target; } - void ReplaceTargets(std::list<Unit*>& targets) + void ReplaceTargets(std::list<WorldObject*>& targets) { targets.clear(); if (_target) @@ -520,13 +520,13 @@ class spell_rotface_mutated_infection : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_mutated_infection_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); AfterHit += SpellHitFn(spell_rotface_mutated_infection_SpellScript::NotifyTargets); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 6039ace44ab..e3c0f2260df 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -19,6 +19,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellAuraEffects.h" +#include "GridNotifiers.h" #include "icecrown_citadel.h" enum Texts @@ -167,7 +168,7 @@ class FrostwyrmLandEvent : public BasicEvent bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) { - _owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest, 8.247422f); + _owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest); return true; } @@ -183,7 +184,7 @@ class FrostBombExplosion : public BasicEvent bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) { - _owner->CastSpell((Unit*)NULL, SPELL_FROST_BOMB, true, NULL, NULL, _sindragosaGUID); + _owner->CastSpell((Unit*)NULL, SPELL_FROST_BOMB, false, NULL, NULL, _sindragosaGUID); _owner->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL); return true; } @@ -200,7 +201,7 @@ class boss_sindragosa : public CreatureScript struct boss_sindragosaAI : public BossAI { - boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA) + boss_sindragosaAI(Creature* creature) : BossAI(creature, DATA_SINDRAGOSA), _summoned(false) { } @@ -220,7 +221,7 @@ class boss_sindragosa : public CreatureScript _isInAirPhase = false; _isThirdPhase = false; - if (instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) != 255) + if (!_summoned) { me->SetCanFly(true); me->SetDisableGravity(true); @@ -266,10 +267,13 @@ class boss_sindragosa : public CreatureScript { if (action == ACTION_START_FROSTWYRM) { + if (_summoned) + return; + + _summoned = true; if (TempSummon* summon = me->ToTempSummon()) summon->SetTempSummonType(TEMPSUMMON_DEAD_DESPAWN); - instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 255); if (me->isDead()) return; @@ -481,7 +485,7 @@ class boss_sindragosa : public CreatureScript Position pos; pos.Relocate(me); pos.m_positionZ += 17.0f; - me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos, 8.30078125f); + me->GetMotionMaster()->MoveTakeoff(POINT_TAKEOFF, pos); events.CancelEventGroup(EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_AIR_PHASE, 110000); break; @@ -523,7 +527,7 @@ class boss_sindragosa : public CreatureScript events.ScheduleEvent(EVENT_FROST_BREATH, urand(10000, 15000), EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_UNCHAINED_MAGIC, urand(12000, 17000), EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_ICY_GRIP, urand(35000, 40000), EVENT_GROUP_LAND_PHASE); - me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos, 0.0f); + me->GetMotionMaster()->MoveLand(POINT_LAND_GROUND, SindragosaLandPos); break; case EVENT_THIRD_PHASE_CHECK: { @@ -550,6 +554,7 @@ class boss_sindragosa : public CreatureScript uint8 _mysticBuffetStack; bool _isInAirPhase; bool _isThirdPhase; + bool _summoned; }; CreatureAI* GetAI(Creature* creature) const @@ -642,7 +647,7 @@ class npc_spinestalker : public CreatureScript struct npc_spinestalkerAI : public ScriptedAI { - npc_spinestalkerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + npc_spinestalkerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) { } @@ -651,7 +656,7 @@ class npc_spinestalker : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -664,7 +669,7 @@ class npc_spinestalker : public CreatureScript _events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(8000, 12000)); me->SetReactState(REACT_DEFENSIVE); - if (_instance->GetData(DATA_SPINESTALKER) != 255) + if (!_summoned) { me->SetCanFly(true); me->SetDisableGravity(true); @@ -674,20 +679,22 @@ class npc_spinestalker : public CreatureScript void JustRespawned() { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) { _events.Reset(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0); } void DoAction(int32 const action) { if (action == ACTION_START_FROSTWYRM) { - _instance->SetData(DATA_SPINESTALKER, 255); + if (_summoned) + return; + + _summoned = true; if (me->isDead()) return; @@ -754,6 +761,7 @@ class npc_spinestalker : public CreatureScript private: EventMap _events; InstanceScript* _instance; + bool _summoned; }; CreatureAI* GetAI(Creature* creature) const @@ -769,7 +777,7 @@ class npc_rimefang : public CreatureScript struct npc_rimefangAI : public ScriptedAI { - npc_rimefangAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) + npc_rimefangAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summoned(false) { } @@ -778,7 +786,7 @@ class npc_rimefang : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -791,7 +799,7 @@ class npc_rimefang : public CreatureScript me->SetReactState(REACT_DEFENSIVE); _icyBlastCounter = 0; - if (_instance->GetData(DATA_RIMEFANG) != 255) + if (!_summoned) { me->SetCanFly(true); me->SetDisableGravity(true); @@ -801,20 +809,22 @@ class npc_rimefang : public CreatureScript void JustRespawned() { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 1); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) { _events.Reset(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, 0); } void DoAction(int32 const action) { if (action == ACTION_START_FROSTWYRM) { - _instance->SetData(DATA_RIMEFANG, 255); + if (_summoned) + return; + + _summoned = true; if (me->isDead()) return; @@ -908,6 +918,7 @@ class npc_rimefang : public CreatureScript EventMap _events; InstanceScript* _instance; uint8 _icyBlastCounter; + bool _summoned; }; CreatureAI* GetAI(Creature* creature) const @@ -934,7 +945,8 @@ class npc_sindragosa_trash : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(_frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetData(_frostwyrmId, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -956,13 +968,8 @@ class npc_sindragosa_trash : public CreatureScript ScriptedAI::JustRespawned(); // Increase add count - _instance->SetData(_frostwyrmId, 1); // this cannot be in Reset because reset also happens on evade - } - - void JustDied(Unit* /*killer*/) - { - // Decrease add count - _instance->SetData(_frostwyrmId, 0); + if (me->GetEntry() == NPC_FROSTWING_WHELP) + _instance->SetData(_frostwyrmId, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade } void SetData(uint32 type, uint32 data) @@ -1035,12 +1042,31 @@ class spell_sindragosa_s_fury : public SpellScriptLoader bool Load() { _targetCount = 0; - return true; + + // This script should execute only in Icecrown Citadel + if (InstanceMap* instance = GetCaster()->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + if (instance->GetScriptId() == sObjectMgr->GetScriptId(ICCScriptName)) + return true; + + return false; + } + + void SelectDest() + { + if (Position* dest = const_cast<WorldLocation*>(GetExplTargetDest())) + { + float destX = float(rand_norm()) * 75.0f + 4350.0f; + float destY = float(rand_norm()) * 75.0f + 2450.0f; + float destZ = 205.0f; // random number close to ground, get exact in next call + GetCaster()->UpdateGroundPositionZ(destX, destY, destZ); + dest->Relocate(destX, destY, destZ); + } } - void CountTargets(std::list<Unit*>& unitList) + void CountTargets(std::list<WorldObject*>& targets) { - _targetCount = unitList.size(); + _targetCount = targets.size(); } void HandleDummy(SpellEffIndex effIndex) @@ -1051,10 +1077,10 @@ class spell_sindragosa_s_fury : public SpellScriptLoader return; float resistance = float(GetHitUnit()->GetResistance(SpellSchoolMask(GetSpellInfo()->SchoolMask))); - uint32 minResistFactor = uint32((resistance / (resistance + 510.0f))* 10.0f) * 2; - uint32 randomResist = urand(0, (9 - minResistFactor) * 100)/100 + minResistFactor; + uint32 minResistFactor = uint32((resistance / (resistance + 510.0f)) * 10.0f) * 2; + uint32 randomResist = urand(0, (9 - minResistFactor) * 100) / 100 + minResistFactor; - uint32 damage = (uint32(GetEffectValue()/_targetCount) * randomResist) / 10; + uint32 damage = (uint32(GetEffectValue() / _targetCount) * randomResist) / 10; SpellNonMeleeDamage damageInfo(GetCaster(), GetHitUnit(), GetSpellInfo()->Id, GetSpellInfo()->SchoolMask); damageInfo.damage = damage; @@ -1064,8 +1090,9 @@ class spell_sindragosa_s_fury : public SpellScriptLoader void Register() { + BeforeCast += SpellCastFn(spell_sindragosa_s_fury_SpellScript::SelectDest); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_s_fury_SpellScript::CountTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); OnEffectHitTarget += SpellEffectFn(spell_sindragosa_s_fury_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_s_fury_SpellScript::CountTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY); } uint32 _targetCount; @@ -1082,9 +1109,11 @@ class UnchainedMagicTargetSelector public: UnchainedMagicTargetSelector() { } - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - return unit->getPowerType() != POWER_MANA; + if (Unit* unit = object->ToUnit()) + return unit->getPowerType() != POWER_MANA; + return true; } }; @@ -1097,7 +1126,7 @@ class spell_sindragosa_unchained_magic : public SpellScriptLoader { PrepareSpellScript(spell_sindragosa_unchained_magic_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { unitList.remove_if(UnchainedMagicTargetSelector()); uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 6 : 2); @@ -1107,7 +1136,7 @@ class spell_sindragosa_unchained_magic : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -1290,7 +1319,7 @@ class MysticBuffetTargetFilter public: explicit MysticBuffetTargetFilter(Unit* caster) : _caster(caster) { } - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) const { return !unit->IsWithinLOSInMap(_caster); } @@ -1308,14 +1337,14 @@ class spell_sindragosa_mystic_buffet : public SpellScriptLoader { PrepareSpellScript(spell_sindragosa_mystic_buffet_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if(MysticBuffetTargetFilter(GetCaster())); + targets.remove_if(MysticBuffetTargetFilter(GetCaster())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_sindragosa_mystic_buffet_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_mystic_buffet_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -1393,22 +1422,15 @@ class spell_frostwarden_handler_order_whelp : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end();) - { - if ((*itr)->GetTypeId() != TYPEID_PLAYER) - unitList.erase(itr++); - else - ++itr; - } - - if (unitList.empty()) + targets.remove_if(Trinity::ObjectTypeIdCheck(TYPEID_PLAYER, false)); + if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); } void HandleForcedCast(SpellEffIndex effIndex) @@ -1429,7 +1451,7 @@ class spell_frostwarden_handler_order_whelp : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_frostwarden_handler_order_whelp_SpellScript::HandleForcedCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); - OnUnitTargetSelect += SpellUnitTargetFn(spell_frostwarden_handler_order_whelp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frostwarden_handler_order_whelp_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; @@ -1509,7 +1531,7 @@ class at_sindragosa_lair : public AreaTriggerScript if (Creature* rimefang = ObjectAccessor::GetCreature(*player, instance->GetData64(DATA_RIMEFANG))) rimefang->AI()->DoAction(ACTION_START_FROSTWYRM); - if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && instance->GetBossState(DATA_SINDRAGOSA) != DONE) + if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && !instance->GetData64(DATA_SINDRAGOSA) && instance->GetBossState(DATA_SINDRAGOSA) != DONE) { if (player->GetMap()->IsHeroic() && !instance->GetData(DATA_HEROIC_ATTEMPTS)) return true; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 4dab215d1da..a8657925131 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -138,7 +138,7 @@ enum Spells SPELL_IN_FROSTMOURNE_ROOM = 74276, SPELL_KILL_FROSTMOURNE_PLAYERS = 75127, SPELL_HARVESTED_SOUL = 72679, - SPELL_TRIGGER_VILE_SPIRIT_HEROIC = 73582, + SPELL_TRIGGER_VILE_SPIRIT_HEROIC = 73582, // TODO: Cast every 3 seconds during Frostmourne phase, targets a Wicked Spirit amd activates it // Frostmourne SPELL_LIGHTS_FAVOR = 69382, @@ -152,6 +152,7 @@ enum Spells SPELL_SUMMON_SPIRIT_BOMB_1 = 73581, // (Heroic) SPELL_SUMMON_SPIRIT_BOMB_2 = 74299, // (Heroic) SPELL_EXPLOSION = 73576, // Spirit Bomb (Heroic) + SPELL_HARVEST_SOUL_DAMAGE_AURA = 73655, // Outro SPELL_FURY_OF_FROSTMOURNE = 72350, @@ -221,7 +222,7 @@ enum Events EVENT_QUAKE_2 = 27, EVENT_VILE_SPIRITS = 28, EVENT_HARVEST_SOULS = 29, // heroic only - EVENT_WICKED_SPIRITS = 30, + EVENT_BERSERK = 30, EVENT_SOUL_RIP = 31, EVENT_DESTROY_SOUL = 32, EVENT_FROSTMOURNE_TALK_1 = 33, @@ -249,19 +250,18 @@ enum Events EVENT_OUTRO_TERENAS_TALK_2 = 55, EVENT_OUTRO_TALK_7 = 56, EVENT_OUTRO_TALK_8 = 57, - EVENT_BERSERK = 58, // Shambling Horror - EVENT_SHOCKWAVE = 59, - EVENT_ENRAGE = 60, + EVENT_SHOCKWAVE = 58, + EVENT_ENRAGE = 59, // Raging Spirit - EVENT_SOUL_SHRIEK = 61, + EVENT_SOUL_SHRIEK = 60, // Strangulate Vehicle (Harvest Soul) - EVENT_TELEPORT = 62, - EVENT_MOVE_TO_LICH_KING = 63, - EVENT_DESPAWN_SELF = 64, + EVENT_TELEPORT = 61, + EVENT_MOVE_TO_LICH_KING = 62, + EVENT_DESPAWN_SELF = 63, }; enum EventGroups @@ -391,7 +391,7 @@ class HeightDifferenceCheck { } - bool operator()(Unit* unit) const + bool operator()(WorldObject* unit) const { return (unit->GetPositionZ() - _baseObject->GetPositionZ() > _difference) != _reverse; } @@ -475,6 +475,32 @@ class VileSpiritActivateEvent : public BasicEvent Creature* _owner; }; +class TriggerWickedSpirit : public BasicEvent +{ + public: + explicit TriggerWickedSpirit(Creature* owner) + : _owner(owner), _counter(13) + { + } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) + { + _owner->CastCustomSpell(SPELL_TRIGGER_VILE_SPIRIT_HEROIC, SPELLVALUE_MAX_TARGETS, 1, NULL, true); + + if (--_counter) + { + _owner->m_Events.AddEvent(this, _owner->m_Events.CalculateTime(3000)); + return false; + } + + return true; + } + + private: + Creature* _owner; + uint32 _counter; +}; + class boss_the_lich_king : public CreatureScript { public: @@ -503,6 +529,8 @@ class boss_the_lich_king : public CreatureScript me->SetDisableGravity(false); me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->GetMotionMaster()->MoveFall(); + if (Creature* frostmourne = me->FindNearestCreature(NPC_FROSTMOURNE_TRIGGER, 50.0f)) + frostmourne->DespawnOrUnsummon(); } void EnterCombat(Unit* target) @@ -601,8 +629,6 @@ class boss_the_lich_king : public CreatureScript summons.DoAction(ACTION_TELEPORT_BACK, pred); if (!IsHeroic()) Talk(SAY_LK_FROSTMOURNE_ESCAPE); - else - DoCastAOE(SPELL_TRIGGER_VILE_SPIRIT_HEROIC); break; } default: @@ -645,6 +671,8 @@ class boss_the_lich_king : public CreatureScript if (events.GetPhaseMask() & PHASE_MASK_ONE && !HealthAbovePct(70)) { events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); me->GetMotionMaster()->MovePoint(POINT_CENTER_1, CenterPosition); return; } @@ -652,6 +680,8 @@ class boss_the_lich_king : public CreatureScript if (events.GetPhaseMask() & PHASE_MASK_TWO && !HealthAbovePct(40)) { events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); me->GetMotionMaster()->MovePoint(POINT_CENTER_2, CenterPosition); return; } @@ -664,7 +694,8 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_OUTRO); summons.DespawnAll(); SendMusicToPlayers(MUSIC_FURY_OF_FROSTMOURNE); - DoCastAOE(SPELL_FURY_OF_FROSTMOURNE); + me->InterruptNonMeleeSpells(true); + me->CastSpell((Unit*)NULL, SPELL_FURY_OF_FROSTMOURNE, TRIGGERED_NONE); me->SetWalk(true); events.ScheduleEvent(EVENT_OUTRO_TALK_1, 2600, 0, PHASE_OUTRO); events.ScheduleEvent(EVENT_OUTRO_EMOTE_TALK, 6600, 0, PHASE_OUTRO); @@ -712,7 +743,6 @@ class boss_the_lich_king : public CreatureScript break; case NPC_FROSTMOURNE_TRIGGER: { - summons.Summon(summon); summon->CastSpell((Unit*)NULL, SPELL_BROKEN_FROSTMOURNE, true); SendLightOverride(LIGHT_SOULSTORM, 10000); @@ -724,16 +754,11 @@ class boss_the_lich_king : public CreatureScript case NPC_VILE_SPIRIT: { summons.Summon(summon); - if (events.GetPhaseMask() & PHASE_MASK_FROSTMOURNE) - { - TeleportSpirit(summon); - return; - } - summon->SetReactState(REACT_PASSIVE); summon->SetSpeed(MOVE_FLIGHT, 0.5f); summon->GetMotionMaster()->MoveRandom(10.0f); - summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000)); + if (!(events.GetPhaseMask() & PHASE_MASK_FROSTMOURNE)) + summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000)); return; } case NPC_STRANGULATE_VEHICLE: @@ -756,7 +781,6 @@ class boss_the_lich_king : public CreatureScript case NPC_VALKYR_SHADOWGUARD: case NPC_RAGING_SPIRIT: case NPC_VILE_SPIRIT: - case NPC_WICKED_SPIRIT: summon->ToTempSummon()->SetTempSummonType(TEMPSUMMON_CORPSE_DESPAWN); break; default: @@ -802,8 +826,6 @@ class boss_the_lich_king : public CreatureScript me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); SendMusicToPlayers(MUSIC_SPECIAL); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); DoCast(me, SPELL_REMORSELESS_WINTER_1); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions events.ScheduleEvent(EVENT_QUAKE, 62500, 0, PHASE_TRANSITION); @@ -819,8 +841,6 @@ class boss_the_lich_king : public CreatureScript me->SetFacingTo(0.0f); Talk(SAY_LK_REMORSELESS_WINTER); SendMusicToPlayers(MUSIC_SPECIAL); - me->SetReactState(REACT_PASSIVE); - me->AttackStop(); DoCast(me, SPELL_REMORSELESS_WINTER_2); summons.DespawnEntry(NPC_VALKYR_SHADOWGUARD); events.DelayEvents(62500, EVENT_GROUP_BERSERK); // delay berserk timer, its not ticking during phase transitions @@ -992,10 +1012,6 @@ class boss_the_lich_king : public CreatureScript DoCastAOE(SPELL_VILE_SPIRITS); events.ScheduleEvent(EVENT_VILE_SPIRITS, urand(35000, 40000), EVENT_GROUP_VILE_SPIRITS, PHASE_THREE); break; - case EVENT_WICKED_SPIRITS: - DoCastAOE(SPELL_VILE_SPIRITS); - events.ScheduleEvent(EVENT_WICKED_SPIRITS, urand(35000, 40000), 0, PHASE_FROSTMOURNE); - break; case EVENT_HARVEST_SOULS: Talk(SAY_LK_HARVEST_SOUL); DoCastAOE(SPELL_HARVEST_SOULS); @@ -1003,7 +1019,6 @@ class boss_the_lich_king : public CreatureScript events.SetPhase(PHASE_FROSTMOURNE); // will stop running UpdateVictim (no evading) me->SetReactState(REACT_PASSIVE); me->AttackStop(); - events.ScheduleEvent(EVENT_WICKED_SPIRITS, events.GetNextEventTime(EVENT_VILE_SPIRITS) - events.GetTimer(), 0, PHASE_FROSTMOURNE); events.DelayEvents(50000, EVENT_GROUP_VILE_SPIRITS); events.RescheduleEvent(EVENT_DEFILE, 50000, 0, PHASE_THREE); events.RescheduleEvent(EVENT_SOUL_REAPER, urand(57000, 62000), 0, PHASE_THREE); @@ -1019,16 +1034,22 @@ class boss_the_lich_king : public CreatureScript if (!triggers.empty()) { triggers.sort(Trinity::ObjectDistanceOrderPred(terenas, true)); - Unit* spawner = triggers.front(); + Creature* spawner = triggers.front(); spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_1, true); // summons bombs randomly spawner->CastSpell(spawner, SPELL_SUMMON_SPIRIT_BOMB_2, true); // summons bombs on players + spawner->m_Events.AddEvent(new TriggerWickedSpirit(spawner), spawner->m_Events.CalculateTime(3000)); } for (SummonList::iterator i = summons.begin(); i != summons.end(); ++i) { Creature* summon = ObjectAccessor::GetCreature(*me, *i); if (summon && summon->GetEntry() == NPC_VILE_SPIRIT) - TeleportSpirit(summon); + { + summon->m_Events.KillAllEvents(true); + summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(50000)); + summon->GetMotionMaster()->MoveRandom(10.0f); + summon->SetReactState(REACT_PASSIVE); + } } } break; @@ -1099,22 +1120,6 @@ class boss_the_lich_king : public CreatureScript } private: - - void TeleportSpirit(Creature* summon) - { - float dist = me->GetObjectSize() + (15.0f - me->GetObjectSize()) * float(rand_norm()); - float angle = float(rand_norm()) * float(2.0f * M_PI); - Position dest = TerenasSpawnHeroic; - me->MovePosition(dest, dist, angle); - dest.m_positionZ += 15.0f; - summon->UpdateEntry(NPC_WICKED_SPIRIT); - summon->SetReactState(REACT_PASSIVE); - summon->NearTeleportTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.GetOrientation()); - summon->SetSpeed(MOVE_FLIGHT, 0.5f); - summon->m_Events.KillAllEvents(true); - summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(1000)); - } - void SendMusicToPlayers(uint32 musicId) const { WorldPacket data(SMSG_PLAY_MUSIC, 4); @@ -1635,8 +1640,13 @@ class npc_strangulate_vehicle : public CreatureScript return; if (TempSummon* summ = me->ToTempSummon()) + { if (Unit* summoner = summ->GetSummoner()) + { DoCast(summoner, SPELL_HARVEST_SOUL_TELEPORT_BACK); + summoner->RemoveAurasDueToSpell(SPELL_HARVEST_SOUL_DAMAGE_AURA); + } + } if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_THE_LICH_KING))) lichKing->AI()->SummonedCreatureDespawn(me); @@ -1993,6 +2003,10 @@ class npc_broken_frostmourne : public CreatureScript _events.ScheduleEvent(EVENT_OUTRO_SUMMON_TERENAS, 6000, 0, PHASE_OUTRO); } + void EnterEvadeMode() + { + } + void UpdateAI(uint32 const diff) { UpdateVictim(); @@ -2274,7 +2288,7 @@ class spell_the_lich_king_shadow_trap_periodic : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_shadow_trap_periodic_SpellScript); - void CheckTargetCount(std::list<Unit*>& targets) + void CheckTargetCount(std::list<WorldObject*>& targets) { if (targets.empty()) return; @@ -2284,7 +2298,7 @@ class spell_the_lich_king_shadow_trap_periodic : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_shadow_trap_periodic_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_shadow_trap_periodic_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -2308,10 +2322,10 @@ class spell_the_lich_king_quake : public SpellScriptLoader return GetCaster()->GetInstanceScript() != NULL; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { if (GameObject* platform = ObjectAccessor::GetGameObject(*GetCaster(), GetCaster()->GetInstanceScript()->GetData64(DATA_ARTHAS_PLATFORM))) - unitList.remove_if(HeightDifferenceCheck(platform, 5.0f, false)); + targets.remove_if(HeightDifferenceCheck(platform, 5.0f, false)); } void HandleSendEvent(SpellEffIndex /*effIndex*/) @@ -2322,7 +2336,7 @@ class spell_the_lich_king_quake : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); OnEffectHit += SpellEffectFn(spell_the_lich_king_quake_SpellScript::HandleSendEvent, EFFECT_1, SPELL_EFFECT_SEND_EVENT); } }; @@ -2349,7 +2363,7 @@ class spell_the_lich_king_ice_burst_target_search : public SpellScriptLoader return true; } - void CheckTargetCount(std::list<Unit*>& unitList) + void CheckTargetCount(std::list<WorldObject*>& unitList) { if (unitList.empty()) return; @@ -2357,12 +2371,16 @@ class spell_the_lich_king_ice_burst_target_search : public SpellScriptLoader // if there is at least one affected target cast the explosion GetCaster()->CastSpell(GetCaster(), SPELL_ICE_BURST, true); if (GetCaster()->GetTypeId() == TYPEID_UNIT) + { + GetCaster()->ToCreature()->SetReactState(REACT_PASSIVE); + GetCaster()->AttackStop(); GetCaster()->ToCreature()->DespawnOrUnsummon(500); + } } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_ice_burst_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_ice_burst_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -2411,7 +2429,7 @@ class ExactDistanceCheck public: ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* unit) { return _source->GetExactDist2d(unit) > _dist; } @@ -2430,7 +2448,7 @@ class spell_the_lich_king_defile : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_defile_SpellScript); - void CorrectRange(std::list<Unit*>& targets) + void CorrectRange(std::list<WorldObject*>& targets) { targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X))); } @@ -2446,8 +2464,8 @@ class spell_the_lich_king_defile : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_defile_SpellScript::CorrectRange, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnHit += SpellHitFn(spell_the_lich_king_defile_SpellScript::ChangeDamageAndGrow); } }; @@ -2472,14 +2490,18 @@ class spell_the_lich_king_summon_into_air : public SpellScriptLoader static Position const offset = {0.0f, 0.0f, 15.0f, 0.0f}; WorldLocation* dest = const_cast<WorldLocation*>(GetExplTargetDest()); dest->RelocateOffset(offset); + GetHitDest()->RelocateOffset(offset); // spirit bombs get higher if (GetSpellInfo()->Effects[effIndex].MiscValue == NPC_SPIRIT_BOMB) + { dest->RelocateOffset(offset); + GetHitDest()->RelocateOffset(offset); + } } void Register() { - OnEffectLaunch += SpellEffectFn(spell_the_lich_king_summon_into_air_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); + OnEffectHit += SpellEffectFn(spell_the_lich_king_summon_into_air_SpellScript::ModDestHeight, EFFECT_0, SPELL_EFFECT_SUMMON); } }; @@ -2545,26 +2567,26 @@ class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader return true; } - void SelectTarget(std::list<Unit*>& unitList) + void SelectTarget(std::list<WorldObject*>& targets) { - if (unitList.empty()) + if (targets.empty()) return; - unitList.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); - if (unitList.empty()) + targets.remove_if(Trinity::UnitAuraCheck(true, GetSpellInfo()->Id)); + if (targets.empty()) return; - _target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(_target); + _target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(_target); GetCaster()->GetAI()->SetGUID(_target->GetGUID()); } - void ReplaceTarget(std::list<Unit*>& unitList) + void ReplaceTarget(std::list<WorldObject*>& targets) { - unitList.clear(); + targets.clear(); if (_target) - unitList.push_back(_target); + targets.push_back(_target); } void HandleScript(SpellEffIndex effIndex) @@ -2575,12 +2597,12 @@ class spell_the_lich_king_valkyr_target_search : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_valkyr_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_valkyr_target_search_SpellScript::ReplaceTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_valkyr_target_search_SpellScript::ReplaceTarget, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_valkyr_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -2757,7 +2779,7 @@ class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoa return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { if (targets.empty()) return; @@ -2778,11 +2800,11 @@ class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoa void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_the_lich_king_vile_spirit_move_target_search_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const @@ -2805,7 +2827,7 @@ class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScriptL return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void CheckTargetCount(std::list<Unit*>& targets) + void CheckTargetCount(std::list<WorldObject*>& targets) { if (targets.empty()) return; @@ -2822,7 +2844,7 @@ class spell_the_lich_king_vile_spirit_damage_target_search : public SpellScriptL void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_the_lich_king_vile_spirit_damage_target_search_SpellScript::CheckTargetCount, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } Unit* _target; @@ -2954,6 +2976,15 @@ class spell_the_lich_king_restore_soul : public SpellScriptLoader lichKing->AI()->DoAction(ACTION_TELEPORT_BACK); if (Creature* spawner = GetCaster()->FindNearestCreature(NPC_WORLD_TRIGGER_INFINITE_AOI, 50.0f)) spawner->RemoveAllAuras(); + + std::list<Creature*> spirits; + GetCaster()->GetCreatureListWithEntryInGrid(spirits, NPC_WICKED_SPIRIT, 200.0f); + for (std::list<Creature*>::iterator itr = spirits.begin(); itr != spirits.end(); ++itr) + { + (*itr)->m_Events.KillAllEvents(true); + (*itr)->SetReactState(REACT_PASSIVE); + (*itr)->AI()->EnterEvadeMode(); + } } void RemoveAura() @@ -3046,23 +3077,18 @@ class spell_the_lich_king_trigger_vile_spirit : public SpellScriptLoader { PrepareSpellScript(spell_the_lich_king_trigger_vile_spirit_SpellScript); - void TeleportOutside() + void ActivateSpirit() { Creature* target = GetHitCreature(); if (!target) return; - Position dest; - Position offset; - TerenasSpawnHeroic.GetPositionOffsetTo(*target, offset); - GetCaster()->GetPosition(&dest); - dest.RelocateOffset(offset); - target->NearTeleportTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), dest.GetOrientation()); + VileSpiritActivateEvent(target).Execute(0, 0); } void Register() { - OnHit += SpellHitFn(spell_the_lich_king_trigger_vile_spirit_SpellScript::TeleportOutside); + OnHit += SpellHitFn(spell_the_lich_king_trigger_vile_spirit_SpellScript::ActivateSpirit); } }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index c40a521c794..826c62a4390 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -1013,11 +1013,8 @@ class npc_dream_portal : public CreatureScript { } - void DoAction(int32 const action) + void OnSpellClick(Unit* /*clicker*/) { - if (action != EVENT_SPELLCLICK) - return; - _used = true; me->DespawnOrUnsummon(); } @@ -1190,13 +1187,13 @@ class spell_dreamwalker_summoner : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { - targets.remove_if (Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); + targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); if (targets.empty()) return; - Unit* target = Trinity::Containers::SelectRandomContainerElement(targets); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); targets.clear(); targets.push_back(target); } @@ -1212,7 +1209,7 @@ class spell_dreamwalker_summoner : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_dreamwalker_summoner_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dreamwalker_summoner_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); OnEffectHitTarget += SpellEffectFn(spell_dreamwalker_summoner_SpellScript::HandleForceCast, EFFECT_0, SPELL_EFFECT_FORCE_CAST); } }; @@ -1241,7 +1238,7 @@ class spell_dreamwalker_summon_suppresser : public SpellScriptLoader std::list<Creature*> summoners; GetCreatureListWithEntryInGrid(summoners, caster, NPC_WORLD_TRIGGER, 100.0f); - summoners.remove_if (Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); + summoners.remove_if(Trinity::UnitAuraCheck(true, SPELL_RECENTLY_SPAWNED)); Trinity::Containers::RandomResizeList(summoners, 2); if (summoners.empty()) return; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index fab9a5f0740..17e33912a86 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -19,6 +19,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" +#include "PassiveAI.h" #include "Cell.h" #include "CellImpl.h" #include "GridNotifiers.h" @@ -158,6 +159,9 @@ enum Spells SPELL_FEL_IRON_BOMB_UNDEAD = 71787, SPELL_MACHINE_GUN_UNDEAD = 71788, SPELL_ROCKET_LAUNCH_UNDEAD = 71786, + + // Invisible Stalker (Float, Uninteractible, LargeAOI) + SPELL_SOUL_MISSILE = 72585, }; // Helper defines @@ -248,6 +252,9 @@ enum EventTypes EVENT_RUPERT_FEL_IRON_BOMB = 52, EVENT_RUPERT_MACHINE_GUN = 53, EVENT_RUPERT_ROCKET_LAUNCH = 54, + + // Invisible Stalker (Float, Uninteractible, LargeAOI) + EVENT_SOUL_MISSILE = 55, }; enum DataTypesICC @@ -1668,6 +1675,56 @@ class npc_impaling_spear : public CreatureScript } }; +class npc_arthas_teleport_visual : public CreatureScript +{ + public: + npc_arthas_teleport_visual() : CreatureScript("npc_arthas_teleport_visual") { } + + struct npc_arthas_teleport_visualAI : public NullCreatureAI + { + npc_arthas_teleport_visualAI(Creature* creature) : NullCreatureAI(creature), _instance(creature->GetInstanceScript()) + { + } + + void Reset() + { + _events.Reset(); + if (_instance->GetBossState(DATA_PROFESSOR_PUTRICIDE) == DONE && + _instance->GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == DONE && + _instance->GetBossState(DATA_SINDRAGOSA) == DONE) + _events.ScheduleEvent(EVENT_SOUL_MISSILE, urand(1000, 6000)); + } + + void UpdateAI(uint32 const diff) + { + if (_events.Empty()) + return; + + _events.Update(diff); + + if (_events.ExecuteEvent() == EVENT_SOUL_MISSILE) + { + DoCastAOE(SPELL_SOUL_MISSILE); + _events.ScheduleEvent(EVENT_SOUL_MISSILE, urand(5000, 7000)); + } + } + + private: + InstanceScript* _instance; + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + // Distance from the center of the spire + if (creature->GetExactDist2d(4357.052f, 2769.421f) < 100.0f && creature->GetHomePosition().GetPositionZ() < 315.0f) + return GetIcecrownCitadelAI<npc_arthas_teleport_visualAI>(creature); + + // Default to no script + return NULL; + } +}; + class spell_icc_stoneform : public SpellScriptLoader { public: @@ -1777,15 +1834,15 @@ class DeathPlagueTargetSelector public: explicit DeathPlagueTargetSelector(Unit* caster) : _caster(caster) {} - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - if (unit == _caster) + if (object == _caster) return true; - if (unit->GetTypeId() != TYPEID_PLAYER) + if (object->GetTypeId() != TYPEID_PLAYER) return true; - if (unit->HasAura(SPELL_RECENTLY_INFECTED) || unit->HasAura(SPELL_DEATH_PLAGUE_AURA)) + if (object->ToUnit()->HasAura(SPELL_RECENTLY_INFECTED) || object->ToUnit()->HasAura(SPELL_DEATH_PLAGUE_AURA)) return true; return false; @@ -1811,25 +1868,25 @@ class spell_frost_giant_death_plague : public SpellScriptLoader } // First effect - void CountTargets(std::list<Unit*>& unitList) + void CountTargets(std::list<WorldObject*>& targets) { - unitList.remove(GetCaster()); - _failed = unitList.empty(); + targets.remove(GetCaster()); + _failed = targets.empty(); } // Second effect - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { // Select valid targets for jump - unitList.remove_if (DeathPlagueTargetSelector(GetCaster())); - if (!unitList.empty()) + targets.remove_if(DeathPlagueTargetSelector(GetCaster())); + if (!targets.empty()) { - Unit* target = Trinity::Containers::SelectRandomContainerElement(unitList); - unitList.clear(); - unitList.push_back(target); + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); } - unitList.push_back(GetCaster()); + targets.push_back(GetCaster()); } void HandleScript(SpellEffIndex effIndex) @@ -1843,8 +1900,8 @@ class spell_frost_giant_death_plague : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_frost_giant_death_plague_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_frost_giant_death_plague_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frost_giant_death_plague_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_frost_giant_death_plague_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ALLY); OnEffectHitTarget += SpellEffectFn(spell_frost_giant_death_plague_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); } @@ -1893,9 +1950,11 @@ class spell_icc_harvest_blight_specimen : public SpellScriptLoader class AliveCheck { public: - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - return unit->isAlive(); + if (Unit* unit = object->ToUnit()) + return unit->isAlive(); + return true; } }; @@ -1908,10 +1967,10 @@ class spell_svalna_revive_champion : public SpellScriptLoader { PrepareSpellScript(spell_svalna_revive_champion_SpellScript); - void RemoveAliveTarget(std::list<Unit*>& unitList) + void RemoveAliveTarget(std::list<WorldObject*>& targets) { - unitList.remove_if(AliveCheck()); - Trinity::Containers::RandomResizeList(unitList, 2); + targets.remove_if(AliveCheck()); + Trinity::Containers::RandomResizeList(targets, 2); } void Land(SpellEffIndex /*effIndex*/) @@ -1926,12 +1985,12 @@ class spell_svalna_revive_champion : public SpellScriptLoader //pos.m_positionZ = caster->GetBaseMap()->GetHeight(caster->GetPhaseMask(), pos.GetPositionX(), pos.GetPositionY(), caster->GetPositionZ(), true, 50.0f); //pos.m_positionZ += 0.05f; caster->SetHomePosition(pos); - caster->GetMotionMaster()->MoveLand(POINT_LAND, pos, caster->GetSpeed(MOVE_FLIGHT)); + caster->GetMotionMaster()->MoveLand(POINT_LAND, pos); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_svalna_revive_champion_SpellScript::RemoveAliveTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_svalna_revive_champion_SpellScript::RemoveAliveTarget, EFFECT_0, TARGET_UNIT_DEST_AREA_ENTRY); OnEffectHit += SpellEffectFn(spell_svalna_revive_champion_SpellScript::Land, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); } }; @@ -1974,6 +2033,33 @@ class spell_svalna_remove_spear : public SpellScriptLoader } }; +class spell_icc_soul_missile : public SpellScriptLoader +{ + public: + spell_icc_soul_missile() : SpellScriptLoader("spell_icc_soul_missile") { } + + class spell_icc_soul_missile_SpellScript : public SpellScript + { + PrepareSpellScript(spell_icc_soul_missile_SpellScript); + + void RelocateDest() + { + static Position const offset = {0.0f, 0.0f, 200.0f, 0.0f}; + const_cast<WorldLocation*>(GetExplTargetDest())->RelocateOffset(offset); + } + + void Register() + { + OnCast += SpellCastFn(spell_icc_soul_missile_SpellScript::RelocateDest); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_icc_soul_missile_SpellScript(); + } +}; + class at_icc_saurfang_portal : public AreaTriggerScript { public: @@ -2063,6 +2149,7 @@ void AddSC_icecrown_citadel() new npc_captain_rupert(); new npc_frostwing_vrykul(); new npc_impaling_spear(); + new npc_arthas_teleport_visual(); new spell_icc_stoneform(); new spell_icc_sprit_alarm(); new spell_frost_giant_death_plague(); @@ -2070,6 +2157,7 @@ void AddSC_icecrown_citadel() new spell_trigger_spell_from_caster("spell_svalna_caress_of_death", SPELL_IMPALING_SPEAR_KILL); new spell_svalna_revive_champion(); new spell_svalna_remove_spear(); + new spell_icc_soul_missile(); new at_icc_saurfang_portal(); new at_icc_shutdown_traps(); new at_icc_start_blood_quickening(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 224777c3db7..31639a698ef 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -51,6 +51,7 @@ enum SharedSpells SPELL_GREEN_BLIGHT_RESIDUE = 72145, // The Lich King + SPELL_ARTHAS_TELEPORTER_CEREMONY = 72915, SPELL_FROSTMOURNE_TELEPORT_VISUAL = 73078, }; @@ -275,6 +276,9 @@ enum CreaturesIds NPC_WORLD_TRIGGER_INFINITE_AOI = 36171, NPC_SPIRIT_BOMB = 39189, NPC_FROSTMOURNE_TRIGGER = 38584, + + // Generic + NPC_INVISIBLE_STALKER = 30298, }; enum GameObjectsIds @@ -345,6 +349,7 @@ enum GameObjectsIds GO_SIGIL_OF_THE_FROSTWING = 202181, // The Lich King + GO_SCOURGE_TRANSPORTER_LK = 202223, GO_ARTHAS_PLATFORM = 202161, GO_ARTHAS_PRECIPICE = 202078, GO_DOODAD_ICECROWN_THRONEFROSTYWIND01 = 202188, diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index cb83efc748f..650f426d29c 100755 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -130,6 +130,7 @@ class instance_icecrown_citadel : public InstanceMapScript SindragosaGUID = 0; SpinestalkerGUID = 0; RimefangGUID = 0; + TheLichKingTeleportGUID = 0; TheLichKingGUID = 0; HighlordTirionFordringGUID = 0; TerenasMenethilGUID = 0; @@ -138,9 +139,6 @@ class instance_icecrown_citadel : public InstanceMapScript FrozenThroneEdgeGUID = 0; FrozenThroneWindGUID = 0; FrozenThroneWarningGUID = 0; - FrostwyrmCount = 0; - SpinestalkerTrashCount = 0; - RimefangTrashCount = 0; IsBonedEligible = true; IsOozeDanceEligible = true; IsNauseaEligible = true; @@ -283,6 +281,11 @@ class instance_icecrown_citadel : public InstanceMapScript case NPC_RIMEFANG: RimefangGUID = creature->GetGUID(); break; + case NPC_INVISIBLE_STALKER: + // Teleporter visual at center + if (creature->GetExactDist2d(4357.052f, 2769.421f) < 10.0f) + creature->CastSpell(creature, SPELL_ARTHAS_TELEPORTER_CEREMONY, false); + break; case NPC_THE_LICH_KING: TheLichKingGUID = creature->GetGUID(); break; @@ -293,11 +296,22 @@ class instance_icecrown_citadel : public InstanceMapScript case NPC_TERENAS_MENETHIL_FROSTMOURNE_H: TerenasMenethilGUID = creature->GetGUID(); break; + case NPC_WICKED_SPIRIT: + // Remove corpse as soon as it dies (and respawn 10 seconds later) + creature->SetCorpseDelay(0); + creature->SetReactState(REACT_PASSIVE); + break; default: break; } } + void OnCreatureRemove(Creature* creature) + { + if (creature->GetEntry() == NPC_SINDRAGOSA) + SindragosaGUID = 0; + } + // Weekly quest spawn prevention uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) { @@ -347,6 +361,43 @@ class instance_icecrown_citadel : public InstanceMapScript if (Creature* crok = instance->GetCreature(CrokScourgebaneGUID)) crok->AI()->SetGUID(creature->GetGUID(), ACTION_VRYKUL_DEATH); break; + case NPC_FROSTWING_WHELP: + if (FrostwyrmGUIDs.empty()) + return; + + if (creature->AI()->GetData(1/*DATA_FROSTWYRM_OWNER*/) == DATA_SPINESTALKER) + { + SpinestalkerTrash.erase(creature->GetDBTableGUIDLow()); + if (SpinestalkerTrash.empty()) + if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) + spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); + } + else + { + RimefangTrash.erase(creature->GetDBTableGUIDLow()); + if (RimefangTrash.empty()) + if (Creature* spinestalk = instance->GetCreature(RimefangGUID)) + spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); + } + break; + case NPC_RIMEFANG: + case NPC_SPINESTALKER: + { + if (instance->IsHeroic() && !HeroicAttempts) + return; + + if (GetBossState(DATA_SINDRAGOSA) == DONE) + return; + + FrostwyrmGUIDs.erase(creature->GetDBTableGUIDLow()); + if (FrostwyrmGUIDs.empty()) + { + instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); + if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) + boss->AI()->DoAction(ACTION_START_FROSTWYRM); + } + break; + } default: break; } @@ -460,6 +511,11 @@ class instance_icecrown_citadel : public InstanceMapScript go->SetLootRecipient(valithria->GetLootRecipient()); go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE | GO_FLAG_NODESPAWN); break; + case GO_SCOURGE_TRANSPORTER_LK: + TheLichKingTeleportGUID = go->GetGUID(); + if (GetBossState(DATA_PROFESSOR_PUTRICIDE) == DONE && GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == DONE && GetBossState(DATA_SINDRAGOSA) == DONE) + go->SetGoState(GO_STATE_ACTIVE); + break; case GO_ARTHAS_PLATFORM: // this enables movement at The Frozen Throne, when printed this value is 0.000000f // however, when represented as integer client will accept only this value @@ -538,11 +594,11 @@ class instance_icecrown_citadel : public InstanceMapScript switch (type) { case DATA_SINDRAGOSA_FROSTWYRMS: - return FrostwyrmCount; + return FrostwyrmGUIDs.size(); case DATA_SPINESTALKER: - return SpinestalkerTrashCount; + return SpinestalkerTrash.size(); case DATA_RIMEFANG: - return RimefangTrashCount; + return RimefangTrash.size(); case DATA_COLDFLAME_JETS: return ColdflameJetsState; case DATA_TEAM_IN_INSTANCE: @@ -698,6 +754,8 @@ class instance_icecrown_citadel : public InstanceMapScript break; case DATA_PROFESSOR_PUTRICIDE: HandleGameObject(PlagueSigilGUID, state != DONE); + if (state == DONE) + CheckLichKingAvailability(); if (instance->IsHeroic()) { if (state == FAIL && HeroicAttempts) @@ -712,6 +770,8 @@ class instance_icecrown_citadel : public InstanceMapScript break; case DATA_BLOOD_QUEEN_LANA_THEL: HandleGameObject(BloodwingSigilGUID, state != DONE); + if (state == DONE) + CheckLichKingAvailability(); if (instance->IsHeroic()) { if (state == FAIL && HeroicAttempts) @@ -730,6 +790,8 @@ class instance_icecrown_citadel : public InstanceMapScript break; case DATA_SINDRAGOSA: HandleGameObject(FrostwingSigilGUID, state != DONE); + if (state == DONE) + CheckLichKingAvailability(); if (instance->IsHeroic()) { if (state == FAIL && HeroicAttempts) @@ -798,89 +860,14 @@ class instance_icecrown_citadel : public InstanceMapScript IsOrbWhispererEligible = data ? true : false; break; case DATA_SINDRAGOSA_FROSTWYRMS: - { - if (FrostwyrmCount == 255) - return; - - if (instance->IsHeroic() && !HeroicAttempts) - return; - - if (GetBossState(DATA_SINDRAGOSA) == DONE) - return; - - switch (data) - { - case 0: - if (FrostwyrmCount) - { - --FrostwyrmCount; - if (!FrostwyrmCount) - { - instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); - if (Creature* boss = instance->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos)) - boss->AI()->DoAction(ACTION_START_FROSTWYRM); - } - } - break; - case 1: - ++FrostwyrmCount; - break; - default: - FrostwyrmCount = data; - break; - } + FrostwyrmGUIDs.insert(data); break; - } case DATA_SPINESTALKER: - { - if (SpinestalkerTrashCount == 255) - return; - - switch (data) - { - case 0: - if (SpinestalkerTrashCount) - { - --SpinestalkerTrashCount; - if (!SpinestalkerTrashCount) - if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) - spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); - } - break; - case 1: - ++SpinestalkerTrashCount; - break; - default: - SpinestalkerTrashCount = data; - break; - } + SpinestalkerTrash.insert(data); break; - } case DATA_RIMEFANG: - { - if (RimefangTrashCount == 255) - return; - - switch (data) - { - case 0: - if (RimefangTrashCount) - { - --RimefangTrashCount; - if (!RimefangTrashCount) - if (Creature* rime = instance->GetCreature(RimefangGUID)) - rime->AI()->DoAction(ACTION_START_FROSTWYRM); - } - break; - case 1: - ++RimefangTrashCount; - break; - default: - RimefangTrashCount = data; - break; - } + RimefangTrash.insert(data); break; - } case DATA_COLDFLAME_JETS: ColdflameJetsState = data; if (ColdflameJetsState == DONE) @@ -1095,6 +1082,28 @@ class instance_icecrown_citadel : public InstanceMapScript return true; } + void CheckLichKingAvailability() + { + if (GetBossState(DATA_PROFESSOR_PUTRICIDE) == DONE && GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == DONE && GetBossState(DATA_SINDRAGOSA) == DONE) + { + if (GameObject* teleporter = instance->GetGameObject(TheLichKingTeleportGUID)) + { + teleporter->SetGoState(GO_STATE_ACTIVE); + + std::list<Creature*> stalkers; + GetCreatureListWithEntryInGrid(stalkers, teleporter, NPC_INVISIBLE_STALKER, 100.0f); + if (stalkers.empty()) + return; + + stalkers.sort(Trinity::ObjectDistanceOrderPred(teleporter)); + stalkers.front()->CastSpell((Unit*)NULL, SPELL_ARTHAS_TELEPORTER_CEREMONY, false); + stalkers.pop_front(); + for (std::list<Creature*>::iterator itr = stalkers.begin(); itr != stalkers.end(); ++itr) + (*itr)->AI()->Reset(); + } + } + } + std::string GetSaveData() { OUT_SAVE_INST_DATA; @@ -1276,6 +1285,7 @@ class instance_icecrown_citadel : public InstanceMapScript uint64 SindragosaGUID; uint64 SpinestalkerGUID; uint64 RimefangGUID; + uint64 TheLichKingTeleportGUID; uint64 TheLichKingGUID; uint64 HighlordTirionFordringGUID; uint64 TerenasMenethilGUID; @@ -1289,9 +1299,9 @@ class instance_icecrown_citadel : public InstanceMapScript uint64 PillarsUnchainedGUID; uint32 TeamInInstance; uint32 ColdflameJetsState; - uint32 FrostwyrmCount; - uint32 SpinestalkerTrashCount; - uint32 RimefangTrashCount; + std::set<uint32> FrostwyrmGUIDs; + std::set<uint32> SpinestalkerTrash; + std::set<uint32> RimefangTrash; uint32 BloodQuickeningState; uint32 HeroicAttempts; uint16 BloodQuickeningMinutes; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index 17ed6a79c76..f81ddbf6bf8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -15,7 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "naxxramas.h" enum Horsemen @@ -26,6 +29,11 @@ enum Horsemen HORSEMEN_SIR, }; +enum Spells +{ + SPELL_MARK_DAMAGE = 28836 +}; + enum Events { EVENT_NONE, @@ -395,7 +403,63 @@ public: }; +class spell_four_horsemen_mark : public SpellScriptLoader +{ + public: + spell_four_horsemen_mark() : SpellScriptLoader("spell_four_horsemen_mark") { } + + class spell_four_horsemen_mark_AuraScript : public AuraScript + { + PrepareAuraScript(spell_four_horsemen_mark_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + int32 damage; + switch (GetStackAmount()) + { + case 1: + damage = 0; + break; + case 2: + damage = 500; + break; + case 3: + damage = 1000; + break; + case 4: + damage = 1500; + break; + case 5: + damage = 4000; + break; + case 6: + damage = 12000; + break; + default: + damage = 20000 + 1000 * (GetStackAmount() - 7); + break; + } + if (damage) + caster->CastCustomSpell(SPELL_MARK_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetTarget()); + } + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_four_horsemen_mark_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_four_horsemen_mark_AuraScript(); + } +}; + void AddSC_boss_four_horsemen() { new boss_four_horsemen(); + new spell_four_horsemen_mark(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 8d23de5427c..faaea9c4cae 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -15,7 +15,11 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "GridNotifiers.h" +#include "CombatAI.h" #include "naxxramas.h" enum Yells @@ -25,6 +29,7 @@ enum Yells SAY_DEATH = -1533042, SAY_TELEPORT = -1533043 }; + //Gothik enum Spells { @@ -36,8 +41,11 @@ enum Spells SPELL_INFORM_LIVE_RIDER = 27935, SPELL_INFORM_DEAD_TRAINEE = 27915, SPELL_INFORM_DEAD_KNIGHT = 27931, - SPELL_INFORM_DEAD_RIDER = 27937 + SPELL_INFORM_DEAD_RIDER = 27937, + + SPELL_SHADOW_MARK = 27825 }; + enum Creatures { MOB_LIVE_TRAINEE = 16124, @@ -585,8 +593,35 @@ class mob_gothik_minion : public CreatureScript } }; +class spell_gothik_shadow_bolt_volley : public SpellScriptLoader +{ + public: + spell_gothik_shadow_bolt_volley() : SpellScriptLoader("spell_gothik_shadow_bolt_volley") { } + + class spell_gothik_shadow_bolt_volley_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gothik_shadow_bolt_volley_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(Trinity::UnitAuraCheck(false, SPELL_SHADOW_MARK)); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gothik_shadow_bolt_volley_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gothik_shadow_bolt_volley_SpellScript(); + } +}; + void AddSC_boss_gothik() { new boss_gothik(); new mob_gothik_minion(); + new spell_gothik_shadow_bolt_volley(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 0a4fdec7222..38c22a93ac4 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -86,6 +86,7 @@ enum Spells SPELL_SHADOW_FISURE = 27810, SPELL_VOID_BLAST = 27812, SPELL_MANA_DETONATION = 27819, + SPELL_MANA_DETONATION_DAMAGE = 27820, SPELL_FROST_BLAST = 27808, SPELL_CHAINS_OF_KELTHUZAD = 28410, //28408 script effect SPELL_KELTHUZAD_CHANNEL = 29423, @@ -773,6 +774,46 @@ class npc_kelthuzad_abomination : public CreatureScript } }; +class spell_kelthuzad_detonate_mana : public SpellScriptLoader +{ + public: + spell_kelthuzad_detonate_mana() : SpellScriptLoader("spell_kelthuzad_detonate_mana") { } + + class spell_kelthuzad_detonate_mana_AuraScript : public AuraScript + { + PrepareAuraScript(spell_kelthuzad_detonate_mana_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MANA_DETONATION_DAMAGE)) + return false; + return true; + } + + void HandleScript(AuraEffect const* aurEff) + { + PreventDefaultAction(); + + Unit* target = GetTarget(); + if (int32 mana = int32(target->GetMaxPower(POWER_MANA) / 10)) + { + mana = target->ModifyPower(POWER_MANA, -mana); + target->CastCustomSpell(SPELL_MANA_DETONATION_DAMAGE, SPELLVALUE_BASE_POINT0, -mana * 10, target, true, NULL, aurEff); + } + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_kelthuzad_detonate_mana_AuraScript::HandleScript, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_kelthuzad_detonate_mana_AuraScript(); + } +}; + class achievement_just_cant_get_enough : public AchievementCriteriaScript { public: @@ -796,5 +837,6 @@ void AddSC_boss_kelthuzad() new boss_kelthuzad(); new at_kelthuzad_center(); new npc_kelthuzad_abomination(); + new spell_kelthuzad_detonate_mana(); new achievement_just_cant_get_enough(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index ccc8e9a5663..e45700ebd72 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -456,10 +456,10 @@ class spell_thaddius_pos_neg_charge : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_UNIT; } - void HandleTargets(std::list<Unit*>& targetList) + void HandleTargets(std::list<WorldObject*>& targets) { uint8 count = 0; - for (std::list<Unit*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit) + for (std::list<WorldObject*>::iterator ihit = targets.begin(); ihit != targets.end(); ++ihit) if ((*ihit)->GetGUID() != GetCaster()->GetGUID()) if (Player* target = (*ihit)->ToPlayer()) if (target->HasAura(GetTriggeringSpell()->Id)) @@ -498,7 +498,7 @@ class spell_thaddius_pos_neg_charge : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnUnitTargetSelect += SpellUnitTargetFn(spell_thaddius_pos_neg_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp index 19a84fdae84..d200e8bf4bf 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp @@ -297,7 +297,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader { PrepareSpellScript(spell_varos_energize_core_area_enemySpellScript) - void FilterTargets(std::list<Unit*>& targetList) + void FilterTargets(std::list<WorldObject*>& targets) { Creature* varos = GetCaster()->ToCreature(); if (!varos) @@ -308,7 +308,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader float orientation = CAST_AI(boss_varos::boss_varosAI, varos->AI())->GetCoreEnergizeOrientation(); - for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end();) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { Position pos; (*itr)->GetPosition(&pos); @@ -317,7 +317,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader float diff = fabs(orientation - angle); if (diff > 1.0f) - itr = targetList.erase(itr); + itr = targets.erase(itr); else ++itr; } @@ -325,7 +325,7 @@ class spell_varos_energize_core_area_enemy : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_varos_energize_core_area_enemySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_varos_energize_core_area_enemySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -344,7 +344,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader { PrepareSpellScript(spell_varos_energize_core_area_entrySpellScript) - void FilterTargets(std::list<Unit*>& targetList) + void FilterTargets(std::list<WorldObject*>& targets) { Creature* varos = GetCaster()->ToCreature(); if (!varos) @@ -355,7 +355,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader float orientation = CAST_AI(boss_varos::boss_varosAI, varos->AI())->GetCoreEnergizeOrientation(); - for (std::list<Unit*>::iterator itr = targetList.begin(); itr != targetList.end();) + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();) { Position pos; (*itr)->GetPosition(&pos); @@ -364,7 +364,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader float diff = fabs(orientation - angle); if (diff > 1.0f) - itr = targetList.erase(itr); + itr = targets.erase(itr); else ++itr; } @@ -372,7 +372,7 @@ class spell_varos_energize_core_area_entry : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_varos_energize_core_area_entrySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_varos_energize_core_area_entrySpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); } }; diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index 23f55a3033b..0eafd7a7fea 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -47,7 +47,9 @@ enum Drakes NPC_VERDISA = 27657, NPC_BELGARISTRASZ = 27658, - NPC_ETERNOS = 27659 + NPC_ETERNOS = 27659, + + SPELL_SHOCK_CHARGE = 49836, }; enum Says @@ -210,8 +212,40 @@ public: } }; +class spell_gen_stop_time : public SpellScriptLoader +{ +public: + spell_gen_stop_time() : SpellScriptLoader("spell_gen_stop_time") { } + + class spell_gen_stop_time_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_stop_time_AuraScript); + + void Apply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* caster = GetCaster(); + if (!caster) + return; + Unit* target = GetTarget(); + for (uint32 i = 0; i < 5; ++i) + caster->CastSpell(target, SPELL_SHOCK_CHARGE, false); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_gen_stop_time_AuraScript::Apply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_stop_time_AuraScript(); + } +}; + void AddSC_oculus() { new npc_oculus_drake(); new npc_image_belgaristrasz(); + new spell_gen_stop_time(); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index 2e2744baa3c..f42fd87c643 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -19,11 +19,13 @@ /* ScriptData SDName: Boss Loken SD%Complete: 60% -SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) +SDComment: Missing intro. SDCategory: Halls of Lightning EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "halls_of_lightning.h" enum eEnums @@ -73,23 +75,17 @@ public: InstanceScript* instance; - bool m_bIsAura; - uint32 m_uiArcLightning_Timer; uint32 m_uiLightningNova_Timer; - uint32 m_uiPulsingShockwave_Timer; uint32 m_uiResumePulsingShockwave_Timer; uint32 m_uiHealthAmountModifier; void Reset() { - m_bIsAura = false; - m_uiArcLightning_Timer = 15000; m_uiLightningNova_Timer = 20000; - m_uiPulsingShockwave_Timer = 2000; - m_uiResumePulsingShockwave_Timer = 15000; + m_uiResumePulsingShockwave_Timer = 1000; m_uiHealthAmountModifier = 1; @@ -116,7 +112,10 @@ public: Talk(SAY_DEATH); if (instance) + { instance->SetData(TYPE_LOKEN, DONE); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PULSING_SHOCKWAVE_AURA); + } } void KilledUnit(Unit* /*victim*/) @@ -130,44 +129,13 @@ public: if (!UpdateVictim()) return; - if (m_bIsAura) - { - // workaround for PULSING_SHOCKWAVE - if (m_uiPulsingShockwave_Timer <= uiDiff) - { - Map* map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) - { - int32 dmg; - float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); - - dmg = DUNGEON_MODE(100, 150); // need to correct damage - if (m_fDist > 1.0f) // Further from 1 yard - dmg = int32(dmg*m_fDist); - - me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); - } - } - m_uiPulsingShockwave_Timer = 2000; - } else m_uiPulsingShockwave_Timer -= uiDiff; - } - else + if (m_uiResumePulsingShockwave_Timer) { if (m_uiResumePulsingShockwave_Timer <= uiDiff) { - //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); - DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support - m_bIsAura = true; + DoCast(me, SPELL_PULSING_SHOCKWAVE_N, true); m_uiResumePulsingShockwave_Timer = 0; } else @@ -190,7 +158,7 @@ public: Talk(EMOTE_NOVA); DoCast(me, SPELL_LIGHTNING_NOVA_N); - m_bIsAura = false; + me->RemoveAurasDueToSpell(DUNGEON_MODE<uint32>(SPELL_PULSING_SHOCKWAVE_N, SPELL_PULSING_SHOCKWAVE_H)); m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura m_uiLightningNova_Timer = urand(20000, 21000); } @@ -216,7 +184,39 @@ public: }; +class spell_loken_pulsing_shockwave : public SpellScriptLoader +{ + public: + spell_loken_pulsing_shockwave() : SpellScriptLoader("spell_loken_pulsing_shockwave") { } + + class spell_loken_pulsing_shockwave_SpellScript : public SpellScript + { + PrepareSpellScript(spell_loken_pulsing_shockwave_SpellScript); + + void CalculateDamage(SpellEffIndex /*effIndex*/) + { + if (!GetHitUnit()) + return; + + float distance = GetCaster()->GetDistance2d(GetHitUnit()); + if (distance > 1.0f) + SetHitDamage(int32(GetHitDamage() * distance)); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_loken_pulsing_shockwave_SpellScript::CalculateDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_loken_pulsing_shockwave_SpellScript(); + } +}; + void AddSC_boss_loken() { new boss_loken(); + new spell_loken_pulsing_shockwave(); } diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp index bc57ce21a4d..93bea92503c 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp @@ -23,7 +23,9 @@ SDComment: SDCategory: Script Data End */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "halls_of_stone.h" enum Spells @@ -157,17 +159,12 @@ public: DoScriptText(SAY_KILL, me); } - void SpellHitTarget(Unit* target, const SpellInfo* pSpell) + void SpellHitTarget(Unit* /*target*/, const SpellInfo* pSpell) { //this part should be in the core if (pSpell->Id == SPELL_SHATTER || pSpell->Id == H_SPELL_SHATTER) { - //this spell must have custom handling in the core, dealing damage based on distance - target->CastSpell(target, DUNGEON_MODE(SPELL_SHATTER_EFFECT, H_SPELL_SHATTER_EFFECT), true); - - if (target->HasAura(SPELL_STONED)) - target->RemoveAurasDueToSpell(SPELL_STONED); - + // todo: we need eventmap to kill this stuff //clear this, if we are still performing if (bIsSlam) { @@ -186,7 +183,74 @@ public: }; +class spell_krystallus_shatter : public SpellScriptLoader +{ + public: + spell_krystallus_shatter() : SpellScriptLoader("spell_krystallus_shatter") { } + + class spell_krystallus_shatter_SpellScript : public SpellScript + { + PrepareSpellScript(spell_krystallus_shatter_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->RemoveAurasDueToSpell(SPELL_STONED); + target->CastSpell((Unit*)NULL, SPELL_SHATTER_EFFECT, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_krystallus_shatter_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_krystallus_shatter_SpellScript(); + } +}; + +class spell_krystallus_shatter_effect : public SpellScriptLoader +{ + public: + spell_krystallus_shatter_effect() : SpellScriptLoader("spell_krystallus_shatter_effect") { } + + class spell_krystallus_shatter_effect_SpellScript : public SpellScript + { + PrepareSpellScript(spell_krystallus_shatter_effect_SpellScript); + + void CalculateDamage() + { + if (!GetHitUnit()) + return; + + float radius = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + if (!radius) + return; + + float distance = GetCaster()->GetDistance2d(GetHitUnit()); + if (distance > 1.0f) + SetHitDamage(int32(GetHitDamage() * ((radius - distance) / radius))); + } + + void Register() + { + OnHit += SpellHitFn(spell_krystallus_shatter_effect_SpellScript::CalculateDamage); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_krystallus_shatter_effect_SpellScript(); + } +}; + void AddSC_boss_krystallus() { new boss_krystallus(); + new spell_krystallus_shatter(); + new spell_krystallus_shatter_effect(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 2af73389ecb..7ee67060f97 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -1080,7 +1080,7 @@ class NotVictimFilter { } - bool operator()(Unit* target) + bool operator()(WorldObject* target) { return target != _victim; } @@ -1098,14 +1098,14 @@ class spell_algalon_arcane_barrage : public SpellScriptLoader { PrepareSpellScript(spell_algalon_arcane_barrage_SpellScript); - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { targets.remove_if(NotVictimFilter(GetCaster())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_algalon_arcane_barrage_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_arcane_barrage_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; @@ -1118,9 +1118,9 @@ class spell_algalon_arcane_barrage : public SpellScriptLoader class ActiveConstellationFilter { public: - bool operator()(Unit* target) const + bool operator()(WorldObject* target) const { - return target->GetAI()->GetData(0); + return target->ToUnit() && target->ToUnit()->GetAI() && target->ToUnit()->GetAI()->GetData(0); } }; @@ -1133,7 +1133,7 @@ class spell_algalon_trigger_3_adds : public SpellScriptLoader { PrepareSpellScript(spell_algalon_trigger_3_adds_SpellScript); - void SelectTarget(std::list<Unit*>& targets) + void SelectTarget(std::list<WorldObject*>& targets) { targets.remove_if(ActiveConstellationFilter()); } @@ -1150,7 +1150,7 @@ class spell_algalon_trigger_3_adds : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); } }; @@ -1202,7 +1202,7 @@ class spell_algalon_big_bang : public SpellScriptLoader return true; } - void CountTargets(std::list<Unit*>& targets) + void CountTargets(std::list<WorldObject*>& targets) { _targetCount = targets.size(); } @@ -1215,7 +1215,7 @@ class spell_algalon_big_bang : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_algalon_big_bang_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); AfterCast += SpellCastFn(spell_algalon_big_bang_SpellScript::CheckTargets); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp index 472ff153d73..ec3125f7c0a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp @@ -472,9 +472,9 @@ class npc_feral_defender : public CreatureScript class SanctumSentryCheck { public: - bool operator() (Unit* unit) + bool operator()(WorldObject* object) const { - if (unit->GetEntry() == NPC_SANCTUM_SENTRY) + if (object->GetEntry() == NPC_SANCTUM_SENTRY) return false; return true; @@ -490,14 +490,14 @@ class spell_auriaya_strenght_of_the_pack : public SpellScriptLoader { PrepareSpellScript(spell_auriaya_strenght_of_the_pack_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (SanctumSentryCheck()); + unitList.remove_if(SanctumSentryCheck()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_auriaya_strenght_of_the_pack_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_strenght_of_the_pack_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; @@ -516,15 +516,15 @@ class spell_auriaya_sentinel_blast : public SpellScriptLoader { PrepareSpellScript(spell_auriaya_sentinel_blast_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (PlayerOrPetCheck()); + unitList.remove_if(PlayerOrPetCheck()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 0e453eceaa1..9d5adf39817 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -720,20 +720,18 @@ class boss_flame_leviathan_overload_device : public CreatureScript { } - void DoAction(const int32 param) + void OnSpellClick(Unit* /*clicker*/) { - if (param == EVENT_SPELLCLICK) + if (me->GetVehicle()) { - if (me->GetVehicle()) + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (Unit* player = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (Unit* player = me->GetVehicle()->GetPassenger(SEAT_PLAYER)) - { - me->GetVehicleBase()->CastSpell(player, SPELL_SMOKE_TRAIL, true); - player->GetMotionMaster()->MoveKnockbackFrom(me->GetVehicleBase()->GetPositionX(), me->GetVehicleBase()->GetPositionY(), 30, 30); - player->ExitVehicle(); - } + me->GetVehicleBase()->CastSpell(player, SPELL_SMOKE_TRAIL, true); + player->GetMotionMaster()->MoveKnockbackFrom(me->GetVehicleBase()->GetPositionX(), me->GetVehicleBase()->GetPositionY(), 30, 30); + player->ExitVehicle(); } } } @@ -1232,7 +1230,7 @@ public: //bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) //{ // player->PlayerTalkClass->ClearMenus(); - // switch(action) + // switch (action) // { // case GOSSIP_ACTION_INFO_DEF+1: // if (player) @@ -1619,7 +1617,7 @@ class FlameLeviathanPursuedTargetSelector public: explicit FlameLeviathanPursuedTargetSelector(Unit* unit) : _me(unit) {}; - bool operator()(Unit* target) const + bool operator()(WorldObject* target) const { //! No players, only vehicles (todo: check if blizzlike) Creature* creatureTarget = target->ToCreature(); @@ -1667,7 +1665,7 @@ class spell_pursue : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& targets) + void FilterTargets(std::list<WorldObject*>& targets) { targets.remove_if(FlameLeviathanPursuedTargetSelector(GetCaster())); if (targets.empty()) @@ -1683,7 +1681,7 @@ class spell_pursue : public SpellScriptLoader } } - void FilterTargetsSubsequently(std::list<Unit*>& targets) + void FilterTargetsSubsequently(std::list<WorldObject*>& targets) { targets.clear(); if (_target) @@ -1710,12 +1708,12 @@ class spell_pursue : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_pursue_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_pursue_SpellScript::FilterTargetsSubsequently, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue_SpellScript::FilterTargetsSubsequently, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_pursue_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); } - Unit* _target; + WorldObject* _target; }; SpellScript* GetSpellScript() const diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 3556bf188de..8090b9e8a3e 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -51,6 +51,8 @@ enum VezaxSpells SPELL_SHADOW_CRASH_HIT = 62659, SPELL_SURGE_OF_DARKNESS = 62662, SPELL_SARONITE_VAPORS = 63323, + SPELL_SARONITE_VAPORS_ENERGIZE = 63337, + SPELL_SARONITE_VAPORS_DAMAGE = 63338, SPELL_SUMMON_SARONITE_VAPORS = 63081, SPELL_BERSERK = 26662, @@ -463,6 +465,45 @@ class spell_mark_of_the_faceless : public SpellScriptLoader } }; +class spell_general_vezax_saronite_vapors : public SpellScriptLoader +{ + public: + spell_general_vezax_saronite_vapors() : SpellScriptLoader("spell_general_vezax_saronite_vapors") { } + + class spell_general_vezax_saronite_vapors_AuraScript : public AuraScript + { + PrepareAuraScript(spell_general_vezax_saronite_vapors_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SARONITE_VAPORS_ENERGIZE) || !sSpellMgr->GetSpellInfo(SPELL_SARONITE_VAPORS_DAMAGE)) + return false; + return true; + } + + void HandleEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + int32 mana = int32(aurEff->GetAmount() * pow(2.0f, GetStackAmount())); // mana restore - bp * 2^stackamount + int32 damage = mana * 2; + caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_ENERGIZE, &mana, NULL, NULL, true); + caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DAMAGE, &damage, NULL, NULL, true); + } + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_general_vezax_saronite_vapors_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_general_vezax_saronite_vapors_AuraScript(); + } +}; + class achievement_shadowdodger : public AchievementCriteriaScript { public: @@ -509,6 +550,7 @@ void AddSC_boss_general_vezax() new boss_saronite_animus(); new npc_saronite_vapors(); new spell_mark_of_the_faceless(); + new spell_general_vezax_saronite_vapors(); new achievement_shadowdodger(); new achievement_smell_saronite(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index d89d640b083..24a9171e29f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -354,7 +354,7 @@ class StoneGripTargetSelector : public std::unary_function<Unit*, bool> public: StoneGripTargetSelector(Creature* me, Unit const* victim) : _me(me), _victim(victim) {} - bool operator() (Unit* target) + bool operator()(WorldObject* target) { if (target == _victim && _me->getThreatManager().getThreatList().size() > 1) return true; @@ -385,10 +385,10 @@ class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader return true; } - void FilterTargetsInitial(std::list<Unit*>& unitList) + void FilterTargetsInitial(std::list<WorldObject*>& unitList) { // Remove "main tank" and non-player targets - unitList.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->getVictim())); + unitList.remove_if(StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->getVictim())); // Maximum affected targets per difficulty mode uint32 maxTargets = 1; if (GetSpellInfo()->Id == 63981) @@ -397,7 +397,7 @@ class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader // Return a random amount of targets based on maxTargets while (maxTargets < unitList.size()) { - std::list<Unit*>::iterator itr = unitList.begin(); + std::list<WorldObject*>::iterator itr = unitList.begin(); advance(itr, urand(0, unitList.size()-1)); unitList.erase(itr); } @@ -406,20 +406,20 @@ class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader m_unitList = unitList; } - void FillTargetsSubsequential(std::list<Unit*>& unitList) + void FillTargetsSubsequential(std::list<WorldObject*>& unitList) { unitList = m_unitList; } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FillTargetsSubsequential, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY); } // Shared between effects - std::list<Unit*> m_unitList; + std::list<WorldObject*> m_unitList; }; SpellScript* GetSpellScript() const @@ -598,14 +598,14 @@ class spell_kologarn_stone_shout : public SpellScriptLoader { PrepareSpellScript(spell_kologarn_stone_shout_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (PlayerOrPetCheck()); + unitList.remove_if(PlayerOrPetCheck()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index c7091b42c5a..79e4684f3a6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -170,7 +170,11 @@ enum AchievementCredits ACHIEV_MUST_DECONSTRUCT_FASTER = 21027, }; -#define HEART_VEHICLE_SEAT 0 +enum VehicleSeats +{ + HEART_VEHICLE_SEAT_NORMAL = 0, + HEART_VEHICLE_SEAT_EXPOSED = 1, +}; /*------------------------------------------------------- * @@ -198,6 +202,8 @@ class boss_xt002 : public CreatureScript _Reset(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + DoCast(me, SPELL_STAND); _healthRecovered = false; _gravityBombCasualty = false; @@ -356,15 +362,16 @@ class boss_xt002 : public CreatureScript me->AttackStop(); me->SetReactState(REACT_PASSIVE); - Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT) : NULL; + Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT_NORMAL) : NULL; if (heart) { heart->CastSpell(heart, SPELL_HEART_OVERLOAD, false); heart->CastSpell(me, SPELL_HEART_LIGHTNING_TETHER, false); heart->CastSpell(heart, SPELL_HEART_HEAL_TO_FULL, true); heart->CastSpell(heart, SPELL_EXPOSED_HEART, false); // Channeled - - heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + heart->ChangeSeat(HEART_VEHICLE_SEAT_EXPOSED, true); + heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); } events.CancelEvent(EVENT_SEARING_LIGHT); @@ -392,11 +399,13 @@ class boss_xt002 : public CreatureScript events.RescheduleEvent(EVENT_GRAVITY_BOMB, TIMER_GRAVITY_BOMB); events.RescheduleEvent(EVENT_TYMPANIC_TANTRUM, urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX)); - Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT) : NULL; + Unit* heart = me->GetVehicleKit() ? me->GetVehicleKit()->GetPassenger(HEART_VEHICLE_SEAT_EXPOSED) : NULL; if (!heart) return; - heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + heart->ChangeSeat(HEART_VEHICLE_SEAT_NORMAL, false); + heart->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + heart->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); heart->RemoveAurasDueToSpell(SPELL_EXPOSED_HEART); if (!_hardMode) @@ -425,43 +434,39 @@ class boss_xt002 : public CreatureScript * XT-002 HEART * *///---------------------------------------------------- + class mob_xt002_heart : public CreatureScript { public: mob_xt002_heart() : CreatureScript("mob_xt002_heart") { } - CreatureAI* GetAI(Creature* creature) const + struct mob_xt002_heartAI : public Scripted_NoMovementAI { - return new mob_xt002_heartAI(creature); - } - - struct mob_xt002_heartAI : public ScriptedAI - { - mob_xt002_heartAI(Creature* creature) : ScriptedAI(creature) + mob_xt002_heartAI(Creature* creature) : Scripted_NoMovementAI(creature), + _instance(creature->GetInstanceScript()) { - _instance = creature->GetInstanceScript(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); } - void DamageTaken(Unit* /*pDone*/, uint32 &damage) + void UpdateAI(uint32 const /*diff*/) { } + + void JustDied(Unit* /*killer*/) { - Creature* xt002 = me->GetCreature(*me, _instance->GetData64(BOSS_XT002)); + Creature* xt002 = _instance ? me->GetCreature(*me, _instance->GetData64(BOSS_XT002)) : NULL; if (!xt002 || !xt002->AI()) return; - if (damage >= me->GetHealth()) - { - xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetMaxHealth()); - xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE); - damage = 0; - } + xt002->AI()->SetData(DATA_TRANSFERED_HEALTH, me->GetHealth()); + xt002->AI()->DoAction(ACTION_ENTER_HARD_MODE); } - private: - InstanceScript* _instance; - uint32 _damageTaken; + private: + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new mob_xt002_heartAI(creature); + } }; /*------------------------------------------------------- @@ -915,7 +920,7 @@ class spell_xt002_heart_overload_periodic : public SpellScriptLoader { uint8 a = urand(0, 4); uint32 spellId = spells[a]; - toyPile->CastSpell(toyPile, spellId, true); + toyPile->CastSpell(toyPile, spellId, true, NULL, NULL, instance->GetData64(BOSS_XT002)); } } } @@ -945,9 +950,9 @@ class spell_xt002_tympanic_tantrum : public SpellScriptLoader { PrepareSpellScript(spell_xt002_tympanic_tantrum_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if(PlayerOrPetCheck()); + targets.remove_if(PlayerOrPetCheck()); } void RecalculateDamage() @@ -957,8 +962,9 @@ class spell_xt002_tympanic_tantrum : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY); + OnHit += SpellHitFn(spell_xt002_tympanic_tantrum_SpellScript::RecalculateDamage); OnHit += SpellHitFn(spell_xt002_tympanic_tantrum_SpellScript::RecalculateDamage); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index d35f0559080..858a82bbe57 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -268,10 +268,10 @@ GameObjectAI* GetUlduarAI(GameObject* go) class PlayerOrPetCheck { public: - bool operator() (Unit* unit) + bool operator()(WorldObject* object) const { - if (unit->GetTypeId() != TYPEID_PLAYER) - if (!unit->ToCreature()->isPet()) + if (object->GetTypeId() != TYPEID_PLAYER) + if (!object->ToCreature()->isPet()) return true; return false; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp index 29b8f2e7f48..41a25ce5f76 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp @@ -276,7 +276,7 @@ public: arthas->CastSpell(me, SPELL_TRANSFORMING_CHANNEL, false); pos.Relocate(me); pos.m_positionZ += 8.0f; - me->GetMotionMaster()->MoveTakeoff(0, pos, 3.30078125f); + me->GetMotionMaster()->MoveTakeoff(0, pos); // spectators flee event if (instance) { @@ -333,7 +333,9 @@ public: pos.m_positionX = me->GetHomePosition().GetPositionX(); pos.m_positionY = me->GetHomePosition().GetPositionY(); pos.m_positionZ = 90.6065f; - me->GetMotionMaster()->MoveLand(0, pos, 6.247422f); + me->GetMotionMaster()->MoveLand(0, pos); + me->SetDisableGravity(false, true); + me->SetHover(true); me->SetDisableGravity(false, true); me->SetHover(true); ++introPhase; @@ -522,12 +524,12 @@ public: }; }; -class checkRitualTarget +class RitualTargetCheck { public: - explicit checkRitualTarget(Unit* _caster) : caster(_caster) { } + explicit RitualTargetCheck(Unit* _caster) : caster(_caster) { } - bool operator() (Unit* unit) + bool operator() (WorldObject* unit) const { if (InstanceScript* instance = caster->GetInstanceScript()) if (instance->GetData64(DATA_SACRIFICED_PLAYER) == unit->GetGUID()) @@ -549,14 +551,14 @@ class spell_paralyze_pinnacle : public SpellScriptLoader { PrepareSpellScript(spell_paralyze_pinnacle_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if(checkRitualTarget(GetCaster())); + unitList.remove_if(RitualTargetCheck(GetCaster())); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_paralyze_pinnacle_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_paralyze_pinnacle_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); } }; diff --git a/src/server/scripts/Northrend/dragonblight.cpp b/src/server/scripts/Northrend/dragonblight.cpp index 4cbe280a9f2..1b339b24549 100644 --- a/src/server/scripts/Northrend/dragonblight.cpp +++ b/src/server/scripts/Northrend/dragonblight.cpp @@ -69,7 +69,106 @@ public: } }; +/*###### +## Quest Strengthen the Ancients (12096|12092) +######*/ + +enum StrengthenAncientsMisc +{ + SAY_WALKER_FRIENDLY = 0, + SAY_WALKER_ENEMY = 1, + SAY_LOTHALOR = 0, + + SPELL_CREATE_ITEM_BARK = 47550, + SPELL_CONFUSED = 47044, + + NPC_LOTHALOR = 26321, + + FACTION_WALKER_ENEMY = 14, +}; + +class spell_q12096_q12092_dummy : public SpellScriptLoader // Strengthen the Ancients: On Interact Dummy to Woodlands Walker +{ +public: + spell_q12096_q12092_dummy() : SpellScriptLoader("spell_q12096_q12092_dummy") { } + + class spell_q12096_q12092_dummy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_dummy_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 roll = rand() % 2; + + Creature* tree = GetHitCreature(); + Player* player = GetCaster()->ToPlayer(); + + if (!tree || !player) + return; + + tree->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + + if (roll == 1) // friendly version + { + tree->CastSpell(player, SPELL_CREATE_ITEM_BARK); + tree->AI()->Talk(SAY_WALKER_FRIENDLY, player->GetGUID()); + tree->DespawnOrUnsummon(1000); + } + else if (roll == 0) // enemy version + { + tree->AI()->Talk(SAY_WALKER_ENEMY, player->GetGUID()); + tree->setFaction(FACTION_WALKER_ENEMY); + tree->Attack(player, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_dummy_SpellScript(); + } +}; + +class spell_q12096_q12092_bark : public SpellScriptLoader // Bark of the Walkers +{ +public: + spell_q12096_q12092_bark() : SpellScriptLoader("spell_q12096_q12092_bark") { } + + class spell_q12096_q12092_bark_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12096_q12092_bark_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Creature* lothalor = GetHitCreature(); + if (!lothalor || lothalor->GetEntry() != NPC_LOTHALOR) + return; + + lothalor->AI()->Talk(SAY_LOTHALOR); + lothalor->RemoveAura(SPELL_CONFUSED); + lothalor->DespawnOrUnsummon(4000); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_bark_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12096_q12092_bark_SpellScript(); + } +}; + void AddSC_dragonblight() { new npc_alexstrasza_wr_gate; + new spell_q12096_q12092_dummy; + new spell_q12096_q12092_bark; } diff --git a/src/server/scripts/Northrend/sholazar_basin.cpp b/src/server/scripts/Northrend/sholazar_basin.cpp index 93d0182ea08..afab9b90a4a 100644 --- a/src/server/scripts/Northrend/sholazar_basin.cpp +++ b/src/server/scripts/Northrend/sholazar_basin.cpp @@ -746,6 +746,130 @@ public: } }; +/*###### +## Quest Kick, What Kick? (12589) +######*/ + +enum KickWhatKick +{ + NPC_LUCKY_WILHELM = 28054, + NPC_APPLE = 28053, + NPC_DROSTAN = 28328, + NPC_CRUNCHY = 28346, + NPC_THICKBIRD = 28093, + + SPELL_HIT_APPLE = 51331, + SPELL_MISS_APPLE = 51332, + SPELL_MISS_BIRD_APPLE = 51366, + SPELL_APPLE_FALL = 51371, + SPELL_BIRD_FALL = 51369, + + EVENT_MISS = 0, + EVENT_HIT = 1, + EVENT_MISS_BIRD = 2, + + SAY_WILHELM_MISS = 0, + SAY_WILHELM_HIT = 1, + SAY_DROSTAN_REPLY_MISS = 0, +}; + +class spell_q12589_shoot_rjr : public SpellScriptLoader +{ +public: + spell_q12589_shoot_rjr() : SpellScriptLoader("spell_q12589_shoot_rjr") { } + + class spell_q12589_shoot_rjr_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12589_shoot_rjr_SpellScript); + + SpellCastResult CheckCast() + { + if (Unit* target = GetExplTargetUnit()) + if (target->GetEntry() == NPC_LUCKY_WILHELM) + return SPELL_CAST_OK; + + SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_TARGET_WILHELM); + return SPELL_FAILED_CUSTOM_ERROR; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 roll = urand(1, 100); + + uint8 ev; + if (roll <= 50) + ev = EVENT_MISS; + else if (roll <= 83) + ev = EVENT_HIT; + else + ev = EVENT_MISS_BIRD; + + Unit* shooter = GetCaster(); + Creature* wilhelm = GetHitUnit()->ToCreature(); + Creature* apple = shooter->FindNearestCreature(NPC_APPLE, 30); + Creature* drostan = shooter->FindNearestCreature(NPC_DROSTAN, 30); + + if (!wilhelm || !apple || !drostan) + return; + + switch (ev) + { + case EVENT_MISS_BIRD: + { + Creature* crunchy = shooter->FindNearestCreature(NPC_CRUNCHY, 30); + Creature* bird = shooter->FindNearestCreature(NPC_THICKBIRD, 30); + + if (!bird || !crunchy) + ; // fall to EVENT_MISS + else + { + shooter->CastSpell(bird, SPELL_MISS_BIRD_APPLE); + bird->CastSpell(bird, SPELL_BIRD_FALL); + wilhelm->AI()->Talk(SAY_WILHELM_MISS); + drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS); + + bird->Kill(bird); + crunchy->GetMotionMaster()->MovePoint(0, bird->GetPositionX(), bird->GetPositionY(), + bird->GetMap()->GetWaterOrGroundLevel(bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); + // TODO: Make crunchy perform emote eat when he reaches the bird + + break; + } + } + case EVENT_MISS: + { + shooter->CastSpell(wilhelm, SPELL_MISS_APPLE); + wilhelm->AI()->Talk(SAY_WILHELM_MISS); + drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS); + break; + } + case EVENT_HIT: + { + shooter->CastSpell(apple, SPELL_HIT_APPLE); + apple->CastSpell(apple, SPELL_APPLE_FALL); + wilhelm->AI()->Talk(SAY_WILHELM_HIT); + if (Player* player = shooter->ToPlayer()) + player->KilledMonsterCredit(NPC_APPLE, 0); + apple->DespawnOrUnsummon(); + + break; + } + } + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_q12589_shoot_rjr_SpellScript::CheckCast); + OnEffectHitTarget += SpellEffectFn(spell_q12589_shoot_rjr_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12589_shoot_rjr_SpellScript(); + } +}; + void AddSC_sholazar_basin() { new npc_injured_rainspeaker_oracle(); @@ -756,4 +880,5 @@ void AddSC_sholazar_basin() new npc_adventurous_dwarf(); new npc_jungle_punch_target(); new spell_q12620_the_lifewarden_wrath(); + new spell_q12589_shoot_rjr(); } diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp index 0e654ade995..3443103fa70 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp @@ -19,11 +19,13 @@ /* ScriptData SDName: Boss_Gruul SD%Complete: 60 -SDComment: Ground Slam need further development (knock back effect and shatter effect must be added to the core) +SDComment: Ground Slam need further development (knock back effect must be added to the core) SDCategory: Gruul's Lair EndScriptData */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" #include "gruuls_lair.h" enum eEnums @@ -144,12 +146,7 @@ public: //this part should be in the core if (pSpell->Id == SPELL_SHATTER) { - //this spell must have custom handling in the core, dealing damage based on distance - target->CastSpell(target, SPELL_SHATTER_EFFECT, true); - - if (target->HasAura(SPELL_STONED)) - target->RemoveAurasDueToSpell(SPELL_STONED); - + // todo: use eventmap to kill this stuff //clear this, if we are still performing if (m_bPerformingGroundSlam) { @@ -258,7 +255,83 @@ public: }; +class spell_gruul_shatter : public SpellScriptLoader +{ + public: + spell_gruul_shatter() : SpellScriptLoader("spell_gruul_shatter") { } + + class spell_gruul_shatter_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gruul_shatter_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_STONED)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_SHATTER_EFFECT)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->RemoveAurasDueToSpell(SPELL_STONED); + target->CastSpell((Unit*)NULL, SPELL_SHATTER_EFFECT, true); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gruul_shatter_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gruul_shatter_SpellScript(); + } +}; + +class spell_gruul_shatter_effect : public SpellScriptLoader +{ + public: + spell_gruul_shatter_effect() : SpellScriptLoader("spell_gruul_shatter_effect") { } + + class spell_gruul_shatter_effect_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gruul_shatter_effect_SpellScript); + + void CalculateDamage() + { + if (!GetHitUnit()) + return; + + float radius = GetSpellInfo()->Effects[EFFECT_0].CalcRadius(GetCaster()); + if (!radius) + return; + + float distance = GetCaster()->GetDistance2d(GetHitUnit()); + if (distance > 1.0f) + SetHitDamage(int32(GetHitDamage() * ((radius - distance) / radius))); + } + + void Register() + { + OnHit += SpellHitFn(spell_gruul_shatter_effect_SpellScript::CalculateDamage); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gruul_shatter_effect_SpellScript(); + } +}; + void AddSC_boss_gruul() { new boss_gruul(); + new spell_gruul_shatter(); + new spell_gruul_shatter_effect(); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index d202fdd2f44..0454274401c 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -518,7 +518,7 @@ class spell_astromancer_wrath_of_the_astromancer : public SpellScriptLoader return true; } - void CountTargets(std::list<Unit*>& targetList) + void CountTargets(std::list<WorldObject*>& targetList) { _targetCount = targetList.size(); } @@ -549,7 +549,7 @@ class spell_astromancer_wrath_of_the_astromancer : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_astromancer_wrath_of_the_astromancer_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_astromancer_wrath_of_the_astromancer_SpellScript::CountTargets, EFFECT_0, TARGET_DEST_CASTER_RADIUS); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_astromancer_wrath_of_the_astromancer_SpellScript::CountTargets, EFFECT_0, TARGET_DEST_CASTER_RADIUS); } }; diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp index 3579a7d697b..1cd67065af1 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp @@ -52,10 +52,10 @@ class spell_capacitus_polarity_charge : public SpellScriptLoader return true; } - void HandleTargets(std::list<Unit*>& targetList) + void HandleTargets(std::list<WorldObject*>& targetList) { uint8 count = 0; - for (std::list<Unit*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit) + for (std::list<WorldObject*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit) if ((*ihit)->GetGUID() != GetCaster()->GetGUID()) if (Player* target = (*ihit)->ToPlayer()) if (target->HasAura(GetTriggeringSpell()->Id)) @@ -88,7 +88,7 @@ class spell_capacitus_polarity_charge : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_capacitus_polarity_charge_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnUnitTargetSelect += SpellUnitTargetFn(spell_capacitus_polarity_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_capacitus_polarity_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; diff --git a/src/server/scripts/Outland/blades_edge_mountains.cpp b/src/server/scripts/Outland/blades_edge_mountains.cpp index 4ec1d04b6ad..c46757a3956 100644 --- a/src/server/scripts/Outland/blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/blades_edge_mountains.cpp @@ -651,7 +651,7 @@ class npc_simon_bunny : public CreatureScript { _events.Update(diff); - switch(_events.ExecuteEvent()) + switch (_events.ExecuteEvent()) { case EVENT_SIMON_PERIODIC_PLAYER_CHECK: if (!CheckPlayer()) diff --git a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp index a213713ae1a..96897ae3033 100644 --- a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp +++ b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp @@ -16,7 +16,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptPCH.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" enum Texts { @@ -36,6 +39,7 @@ enum Spells SPELL_THUNDERCLAP = 36706, SPELL_VOID_BOLT = 39329, SPELL_MARK_OF_KAZZAK = 32960, + SPELL_MARK_OF_KAZZAK_DAMAGE = 32961, SPELL_ENRAGE = 32964, SPELL_CAPTURE_SOUL = 32966, SPELL_TWISTED_REFLECTION = 21063, @@ -171,7 +175,55 @@ class boss_doomlord_kazzak : public CreatureScript } }; +class spell_mark_of_kazzak : public SpellScriptLoader +{ + public: + spell_mark_of_kazzak() : SpellScriptLoader("spell_mark_of_kazzak") { } + + class spell_mark_of_kazzak_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mark_of_kazzak_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_KAZZAK_DAMAGE)) + return false; + return true; + } + + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* owner = GetUnitOwner()) + amount = CalculatePctU(owner->GetPower(POWER_MANA), 5); + } + + void OnPeriodic(AuraEffect const* aurEff) + { + Unit* target = GetTarget(); + + if (target->GetPower(POWER_MANA) == 0) + { + target->CastSpell(target, SPELL_MARK_OF_KAZZAK_DAMAGE, true, NULL, aurEff); + // Remove aura + SetDuration(0); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mark_of_kazzak_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_kazzak_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mark_of_kazzak_AuraScript(); + } +}; + void AddSC_boss_doomlordkazzak() { new boss_doomlord_kazzak(); + new spell_mark_of_kazzak(); } diff --git a/src/server/scripts/Outland/netherstorm.cpp b/src/server/scripts/Outland/netherstorm.cpp index afc18c71b92..16dac13d1a9 100644 --- a/src/server/scripts/Outland/netherstorm.cpp +++ b/src/server/scripts/Outland/netherstorm.cpp @@ -777,10 +777,10 @@ public: PlayerGUID = who->GetGUID(); } - void SpellHit(Unit* /*caster*/, const SpellInfo* /*spell*/) - { - DoCast(me, SPELL_DE_MATERIALIZE); - } + //void SpellHit(Unit* /*caster*/, const SpellInfo* /*spell*/) + //{ + // DoCast(me, SPELL_DE_MATERIALIZE); + //} void UpdateAI(const uint32 diff) { diff --git a/src/server/scripts/Spells/CMakeLists.txt b/src/server/scripts/Spells/CMakeLists.txt index 04dcee9287c..2bb695bd8a9 100644 --- a/src/server/scripts/Spells/CMakeLists.txt +++ b/src/server/scripts/Spells/CMakeLists.txt @@ -24,6 +24,7 @@ set(scripts_STAT_SRCS Spells/spell_paladin.cpp Spells/spell_item.cpp Spells/spell_holiday.cpp + Spells/spell_pet.cpp ) message(" -> Prepared: Spells") diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 36dcb53ad00..5095092927e 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -40,6 +40,8 @@ enum DeathKnightSpells DK_SPELL_IMPROVED_BLOOD_PRESENCE_TRIGGERED = 63611, DK_SPELL_UNHOLY_PRESENCE = 48265, DK_SPELL_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622, + SPELL_DK_ITEM_T8_MALEE_4P_BONUS = 64736, + DK_SPELL_BLACK_ICE_R1 = 49140, }; // 50462 - Anti-Magic Shell (on raid member) @@ -111,8 +113,7 @@ class spell_dk_anti_magic_shell_self : public SpellScriptLoader void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/) { - // Set absorbtion amount to unlimited - amount = -1; + amount = GetCaster()->CountPctFromMaxHealth(hpPct); } void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount) @@ -334,16 +335,30 @@ class spell_dk_death_pact : public SpellScriptLoader { PrepareSpellScript(spell_dk_death_pact_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + SpellCastResult CheckCast() + { + // Check if we have valid targets, otherwise skip spell casting here + if (Player* player = GetCaster()->ToPlayer()) + for (Unit::ControlList::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr) + if (Creature* undeadPet = (*itr)->ToCreature()) + if (undeadPet->isAlive() && + undeadPet->GetOwnerGUID() == player->GetGUID() && + undeadPet->GetCreatureType() == CREATURE_TYPE_UNDEAD && + undeadPet->IsWithinDist(player, 100.0f, false)) + return SPELL_CAST_OK; + + return SPELL_FAILED_NO_PET; + } + + void FilterTargets(std::list<WorldObject*>& unitList) { Unit* unit_to_add = NULL; - for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) + for (std::list<WorldObject*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr) { - if ((*itr)->GetTypeId() == TYPEID_UNIT - && (*itr)->GetOwnerGUID() == GetCaster()->GetGUID() - && (*itr)->ToCreature()->GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD) + if (Unit* unit = (*itr)->ToUnit()) + if (unit->GetOwnerGUID() == GetCaster()->GetGUID() && unit->GetCreatureType() == CREATURE_TYPE_UNDEAD) { - unit_to_add = (*itr); + unit_to_add = unit; break; } } @@ -351,18 +366,12 @@ class spell_dk_death_pact : public SpellScriptLoader unitList.clear(); if (unit_to_add) unitList.push_back(unit_to_add); - else - { - // Pet not found - remove cooldown - if (Player* modOwner = GetCaster()->GetSpellModOwner()) - modOwner->RemoveSpellCooldown(GetSpellInfo()->Id, true); - FinishCast(SPELL_FAILED_NO_PET); - } } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_dk_death_pact_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ALLY); + OnCheckCast += SpellCheckCastFn(spell_dk_death_pact_SpellScript::CheckCast); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_death_pact_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ALLY); } }; @@ -381,6 +390,13 @@ class spell_dk_scourge_strike : public SpellScriptLoader class spell_dk_scourge_strike_SpellScript : public SpellScript { PrepareSpellScript(spell_dk_scourge_strike_SpellScript); + float multiplier; + + bool Load() + { + multiplier = 1.0f; + return true; + } bool Validate(SpellInfo const* /*spellEntry*/) { @@ -394,7 +410,23 @@ class spell_dk_scourge_strike : public SpellScriptLoader Unit* caster = GetCaster(); if (Unit* unitTarget = GetHitUnit()) { - int32 bp = CalculatePctN(GetHitDamage(), GetEffectValue() * unitTarget->GetDiseasesByCaster(caster->GetGUID())); + multiplier = (GetEffectValue() * unitTarget->GetDiseasesByCaster(caster->GetGUID()) / 100.f); + // Death Knight T8 Melee 4P Bonus + if (AuraEffect const* aurEff = caster->GetAuraEffect(SPELL_DK_ITEM_T8_MALEE_4P_BONUS, EFFECT_0)) + AddPctF(multiplier, aurEff->GetAmount()); + } + } + + void HandleAfterHit() + { + Unit* caster = GetCaster(); + if (Unit* unitTarget = GetHitUnit()) + { + int32 bp = GetHitDamage() * multiplier; + + if (AuraEffect* aurEff = caster->GetAuraEffectOfRankedSpell(DK_SPELL_BLACK_ICE_R1, EFFECT_0)) + AddPctN(bp, aurEff->GetAmount()); + caster->CastCustomSpell(unitTarget, DK_SPELL_SCOURGE_STRIKE_TRIGGERED, &bp, NULL, NULL, true); } } @@ -402,6 +434,7 @@ class spell_dk_scourge_strike : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_dk_scourge_strike_SpellScript::HandleDummy, EFFECT_2, SPELL_EFFECT_DUMMY); + AfterHit += SpellHitFn(spell_dk_scourge_strike_SpellScript::HandleAfterHit); } }; @@ -588,7 +621,7 @@ public: if (!target->HasAura(DK_SPELL_BLOOD_PRESENCE) && !target->HasAura(DK_SPELL_IMPROVED_BLOOD_PRESENCE_TRIGGERED)) { int32 basePoints1 = aurEff->GetAmount(); - target->CastCustomSpell(target, 63611, NULL, &basePoints1, NULL, true, 0, aurEff); + target->CastCustomSpell(target, DK_SPELL_IMPROVED_BLOOD_PRESENCE_TRIGGERED, NULL, &basePoints1, NULL, true, 0, aurEff); } } @@ -723,14 +756,14 @@ class spell_dk_death_coil : public SpellScriptLoader { PrepareSpellScript(spell_dk_death_coil_SpellScript); - bool Validate(SpellInfo const* /*SpellEntry*/) + bool Validate(SpellInfo const* /*spell*/) { if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_COIL_DAMAGE) || !sSpellMgr->GetSpellInfo(SPELL_DEATH_COIL_HEAL)) return false; return true; } - void HandleDummy(SpellEffIndex /* effIndex */) + void HandleDummy(SpellEffIndex /*effIndex*/) { int32 damage = GetEffectValue(); Unit* caster = GetCaster(); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 286bec6abab..f34e9e772f3 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -28,7 +28,11 @@ enum DruidSpells { DRUID_INCREASED_MOONFIRE_DURATION = 38414, - DRUID_NATURES_SPLENDOR = 57865 + DRUID_NATURES_SPLENDOR = 57865, + DRUID_LIFEBLOOM_FINAL_HEAL = 33778, + DRUID_LIFEBLOOM_ENERGIZE = 64372, + DRUID_SURVIVAL_INSTINCTS = 50322, + DRUID_SAVAGE_ROAR = 62071 }; // 54846 Glyph of Starfire @@ -154,7 +158,7 @@ class spell_dru_primal_tenacity : public SpellScriptLoader void Absorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount) { // reduces all damage taken while Stunned in Cat Form - if (GetTarget()->GetShapeshiftForm() == FORM_CAT && GetTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & (UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1<<MECHANIC_STUN)) + if (GetTarget()->GetShapeshiftForm() == FORM_CAT && GetTarget()->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED) && GetTarget()->HasAuraWithMechanic(1<<MECHANIC_STUN)) absorbAmount = CalculatePctN(dmgInfo.GetDamage(), absorbPct); } @@ -228,37 +232,37 @@ class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_PLAYER; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { if (!GetCaster()->ToPlayer()->GetGroup()) { - unitList.clear(); - unitList.push_back(GetCaster()); + targets.clear(); + targets.push_back(GetCaster()); } else { - unitList.remove(GetExplTargetUnit()); + targets.remove(GetExplTargetUnit()); std::list<Unit*> tempTargets; - for (std::list<Unit*>::const_iterator itr = unitList.begin(); itr != unitList.end(); ++itr) - if ((*itr)->GetTypeId() == TYPEID_PLAYER && GetCaster()->IsInRaidWith(*itr)) - tempTargets.push_back(*itr); + for (std::list<WorldObject*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + if ((*itr)->GetTypeId() == TYPEID_PLAYER && GetCaster()->IsInRaidWith((*itr)->ToUnit())) + tempTargets.push_back((*itr)->ToUnit()); if (tempTargets.empty()) { - unitList.clear(); + targets.clear(); FinishCast(SPELL_FAILED_DONT_REPORT); return; } Unit* target = Trinity::Containers::SelectRandomContainerElement(tempTargets); - unitList.clear(); - unitList.push_back(target); + targets.clear(); + targets.push_back(target); } } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_dru_t10_restoration_4p_bonus_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dru_t10_restoration_4p_bonus_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY); } }; @@ -277,14 +281,14 @@ class spell_dru_starfall_aoe : public SpellScriptLoader { PrepareSpellScript(spell_dru_starfall_aoe_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove(GetExplTargetUnit()); + targets.remove(GetExplTargetUnit()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_dru_starfall_aoe_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dru_starfall_aoe_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; @@ -337,7 +341,12 @@ class spell_dru_starfall_dummy : public SpellScriptLoader { PrepareSpellScript(spell_dru_starfall_dummy_SpellScript); - void HandleDummy(SpellEffIndex /* effIndex */) + void FilterTargets(std::list<WorldObject*>& targets) + { + Trinity::Containers::RandomResizeList(targets, 2); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) { Unit* caster = GetCaster(); // Shapeshifting into an animal form or mounting cancels the effect @@ -348,15 +357,16 @@ class spell_dru_starfall_dummy : public SpellScriptLoader return; } - //Any effect which causes you to lose control of your character will supress the starfall effect. + // Any effect which causes you to lose control of your character will supress the starfall effect. if (caster->HasUnitState(UNIT_STATE_CONTROLLED)) return; - caster->CastSpell(GetHitUnit(), GetEffectValue(), true); + caster->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); } void Register() { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dru_starfall_dummy_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_dru_starfall_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; @@ -367,6 +377,244 @@ class spell_dru_starfall_dummy : public SpellScriptLoader } }; +class spell_dru_lifebloom : public SpellScriptLoader +{ + public: + spell_dru_lifebloom() : SpellScriptLoader("spell_dru_lifebloom") { } + + class spell_dru_lifebloom_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_lifebloom_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(DRUID_LIFEBLOOM_FINAL_HEAL)) + return false; + if (!sSpellMgr->GetSpellInfo(DRUID_LIFEBLOOM_ENERGIZE)) + return false; + return true; + } + + void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + // Final heal only on duration end + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) + return; + + // final heal + int32 stack = GetStackAmount(); + int32 healAmount = aurEff->GetAmount(); + if (Unit* caster = GetCaster()) + { + healAmount = caster->SpellHealingBonusDone(GetTarget(), GetSpellInfo(), healAmount, HEAL, stack); + healAmount = GetTarget()->SpellHealingBonusTaken(caster, GetSpellInfo(), healAmount, HEAL, stack); + + GetTarget()->CastCustomSpell(GetTarget(), DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); + + // restore mana + int32 returnMana = CalculatePctU(caster->GetCreateMana(), GetSpellInfo()->ManaCostPercentage) * stack / 2; + caster->CastCustomSpell(caster, DRUID_LIFEBLOOM_ENERGIZE, &returnMana, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); + return; + } + + GetTarget()->CastCustomSpell(GetTarget(), DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); + } + + void HandleDispel(DispelInfo* dispelInfo) + { + if (Unit* target = GetUnitOwner()) + { + if (AuraEffect const* aurEff = GetEffect(EFFECT_1)) + { + // final heal + int32 healAmount = aurEff->GetAmount(); + if (Unit* caster = GetCaster()) + { + healAmount = caster->SpellHealingBonusDone(target, GetSpellInfo(), healAmount, HEAL, dispelInfo->GetRemovedCharges()); + healAmount = target->SpellHealingBonusTaken(caster, GetSpellInfo(), healAmount, HEAL, dispelInfo->GetRemovedCharges()); + target->CastCustomSpell(target, DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, NULL, GetCasterGUID()); + + // restore mana + int32 returnMana = CalculatePctU(caster->GetCreateMana(), GetSpellInfo()->ManaCostPercentage) * dispelInfo->GetRemovedCharges() / 2; + caster->CastCustomSpell(caster, DRUID_LIFEBLOOM_ENERGIZE, &returnMana, NULL, NULL, true, NULL, NULL, GetCasterGUID()); + return; + } + + target->CastCustomSpell(target, DRUID_LIFEBLOOM_FINAL_HEAL, &healAmount, NULL, NULL, true, NULL, NULL, GetCasterGUID()); + } + } + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_lifebloom_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterDispel += AuraDispelFn(spell_dru_lifebloom_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_lifebloom_AuraScript(); + } +}; + +class spell_dru_predatory_strikes : public SpellScriptLoader +{ + public: + spell_dru_predatory_strikes() : SpellScriptLoader("spell_dru_predatory_strikes") { } + + class spell_dru_predatory_strikes_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_predatory_strikes_AuraScript); + + void UpdateAmount(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Player* target = GetTarget()->ToPlayer()) + target->UpdateAttackPowerAndDamage(); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_dru_predatory_strikes_AuraScript::UpdateAmount, EFFECT_ALL, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_predatory_strikes_AuraScript::UpdateAmount, EFFECT_ALL, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dru_predatory_strikes_AuraScript(); + } +}; + +class spell_dru_savage_roar : public SpellScriptLoader +{ + public: + spell_dru_savage_roar() : SpellScriptLoader("spell_dru_savage_roar") { } + + class spell_dru_savage_roar_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_savage_roar_SpellScript); + + SpellCastResult CheckCast() + { + Unit* caster = GetCaster(); + if (caster->GetShapeshiftForm() != FORM_CAT) + return SPELL_FAILED_ONLY_SHAPESHIFT; + + return SPELL_CAST_OK; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_dru_savage_roar_SpellScript::CheckCast); + } + }; + + class spell_dru_savage_roar_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_savage_roar_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(DRUID_SAVAGE_ROAR)) + return false; + return true; + } + + void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + target->CastSpell(target, DRUID_SAVAGE_ROAR, true, NULL, aurEff, GetCasterGUID()); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(DRUID_SAVAGE_ROAR); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_dru_savage_roar_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_savage_roar_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dru_savage_roar_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_dru_savage_roar_AuraScript(); + } +}; + +class spell_dru_survival_instincts : public SpellScriptLoader +{ + public: + spell_dru_survival_instincts() : SpellScriptLoader("spell_dru_survival_instincts") { } + + class spell_dru_survival_instincts_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_survival_instincts_SpellScript); + + SpellCastResult CheckCast() + { + Unit* caster = GetCaster(); + if (!caster->IsInFeralForm()) + return SPELL_FAILED_ONLY_SHAPESHIFT; + + return SPELL_CAST_OK; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_dru_survival_instincts_SpellScript::CheckCast); + } + }; + + class spell_dru_survival_instincts_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_survival_instincts_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(DRUID_SURVIVAL_INSTINCTS)) + return false; + return true; + } + + void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + Unit* target = GetTarget(); + int32 bp0 = target->CountPctFromMaxHealth(aurEff->GetAmount()); + target->CastCustomSpell(target, DRUID_SURVIVAL_INSTINCTS, &bp0, NULL, NULL, true); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(DRUID_SURVIVAL_INSTINCTS); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_dru_survival_instincts_AuraScript::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectRemove += AuraEffectRemoveFn(spell_dru_survival_instincts_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_dru_survival_instincts_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_dru_survival_instincts_AuraScript(); + } +}; + void AddSC_druid_spell_scripts() { new spell_dru_glyph_of_starfire(); @@ -377,4 +625,8 @@ void AddSC_druid_spell_scripts() new spell_dru_starfall_aoe(); new spell_dru_swift_flight_passive(); new spell_dru_starfall_dummy(); + new spell_dru_lifebloom(); + new spell_dru_predatory_strikes(); + new spell_dru_savage_roar(); + new spell_dru_survival_instincts(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 0c879cfb029..a35d243593e 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -239,7 +239,7 @@ class spell_gen_parachute : public SpellScriptLoader { PrepareAuraScript(spell_gen_parachute_AuraScript); - bool Validate(SpellInfo const* /*spellEntry*/) + bool Validate(SpellInfo const* /*spell*/) { if (!sSpellMgr->GetSpellInfo(SPELL_PARACHUTE) || !sSpellMgr->GetSpellInfo(SPELL_PARACHUTE_BUFF)) return false; @@ -660,22 +660,16 @@ class spell_pvp_trinket_wotf_shared_cd : public SpellScriptLoader return true; } - void HandleScript(SpellEffIndex /*effIndex*/) + void HandleScript() { - Player* caster = GetCaster()->ToPlayer(); - SpellInfo const* spellInfo = GetSpellInfo(); - caster->AddSpellCooldown(spellInfo->Id, 0, time(NULL) + sSpellMgr->GetSpellInfo(SPELL_WILL_OF_THE_FORSAKEN_COOLDOWN_TRIGGER)->GetRecoveryTime() / IN_MILLISECONDS); - WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4); - data << uint64(caster->GetGUID()); - data << uint8(0); - data << uint32(spellInfo->Id); - data << uint32(0); - caster->GetSession()->SendPacket(&data); + // This is only needed because spells cast from spell_linked_spell are triggered by default + // Spell::SendSpellCooldown() skips all spells with TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD + GetCaster()->ToPlayer()->AddSpellAndCategoryCooldowns(GetSpellInfo(), GetCastItem() ? GetCastItem()->GetEntry() : 0, GetSpell()); } void Register() { - OnEffectHit += SpellEffectFn(spell_pvp_trinket_wotf_shared_cd_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + AfterCast += SpellCastFn(spell_pvp_trinket_wotf_shared_cd_SpellScript::HandleScript); } }; @@ -2052,9 +2046,9 @@ class spell_gen_defend : public SpellScriptLoader public: spell_gen_defend() : SpellScriptLoader("spell_gen_defend") { } - class spell_gen_defendAuraScript : public AuraScript + class spell_gen_defend_AuraScript : public AuraScript { - PrepareAuraScript(spell_gen_defendAuraScript); + PrepareAuraScript(spell_gen_defend_AuraScript); bool Validate(SpellInfo const* /*spellEntry*/) { @@ -2103,26 +2097,26 @@ class spell_gen_defend : public SpellScriptLoader // Defend spells casted by NPCs (add visuals) if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) { - AfterEffectApply += AuraEffectApplyFn(spell_gen_defendAuraScript::RefreshVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_gen_defendAuraScript::RemoveVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); } // Remove Defend spell from player when he dismounts if (spell->Effects[EFFECT_2].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) - OnEffectRemove += AuraEffectRemoveFn(spell_gen_defendAuraScript::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveDummyFromDriver, EFFECT_2, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); // Defend spells casted by players (add/remove visuals) if (spell->Effects[EFFECT_1].ApplyAuraName == SPELL_AURA_DUMMY) { - AfterEffectApply += AuraEffectApplyFn(spell_gen_defendAuraScript::RefreshVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_gen_defendAuraScript::RemoveVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_gen_defend_AuraScript::RefreshVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_defend_AuraScript::RemoveVisualShields, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); } } }; AuraScript* GetAuraScript() const { - return new spell_gen_defendAuraScript(); + return new spell_gen_defend_AuraScript(); } }; @@ -2326,9 +2320,9 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader public: spell_gen_on_tournament_mount() : SpellScriptLoader("spell_gen_on_tournament_mount") { } - class spell_gen_on_tournament_mountAuraScript : public AuraScript + class spell_gen_on_tournament_mount_AuraScript : public AuraScript { - PrepareAuraScript(spell_gen_on_tournament_mountAuraScript); + PrepareAuraScript(spell_gen_on_tournament_mount_AuraScript); uint32 _pennantSpellId; @@ -2468,14 +2462,14 @@ class spell_gen_on_tournament_mount : public SpellScriptLoader void Register() { - AfterEffectApply += AuraEffectApplyFn(spell_gen_on_tournament_mountAuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); - OnEffectRemove += AuraEffectRemoveFn(spell_gen_on_tournament_mountAuraScript::HandleRemoveEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_gen_on_tournament_mount_AuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_on_tournament_mount_AuraScript::HandleRemoveEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); } }; AuraScript* GetAuraScript() const { - return new spell_gen_on_tournament_mountAuraScript(); + return new spell_gen_on_tournament_mount_AuraScript(); } }; @@ -2484,9 +2478,9 @@ class spell_gen_tournament_pennant : public SpellScriptLoader public: spell_gen_tournament_pennant() : SpellScriptLoader("spell_gen_tournament_pennant") { } - class spell_gen_tournament_pennantAuraScript : public AuraScript + class spell_gen_tournament_pennant_AuraScript : public AuraScript { - PrepareAuraScript(spell_gen_tournament_pennantAuraScript); + PrepareAuraScript(spell_gen_tournament_pennant_AuraScript); bool Load() { @@ -2502,13 +2496,13 @@ class spell_gen_tournament_pennant : public SpellScriptLoader void Register() { - OnEffectApply += AuraEffectApplyFn(spell_gen_tournament_pennantAuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + OnEffectApply += AuraEffectApplyFn(spell_gen_tournament_pennant_AuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); } }; AuraScript* GetAuraScript() const { - return new spell_gen_tournament_pennantAuraScript(); + return new spell_gen_tournament_pennant_AuraScript(); } }; @@ -2688,6 +2682,401 @@ public: } }; +class spell_gen_touch_the_nightmare : public SpellScriptLoader +{ +public: + spell_gen_touch_the_nightmare() : SpellScriptLoader("spell_gen_touch_the_nightmare") { } + + class spell_gen_touch_the_nightmare_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_touch_the_nightmare_SpellScript); + + void HandleDamageCalc(SpellEffIndex /*effIndex*/) + { + uint32 bp = GetCaster()->GetMaxHealth() * 0.3f; + SetHitDamage(bp); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_touch_the_nightmare_SpellScript::HandleDamageCalc, EFFECT_2, SPELL_EFFECT_SCHOOL_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_touch_the_nightmare_SpellScript(); + } +}; + +class spell_gen_dream_funnel: public SpellScriptLoader +{ +public: + spell_gen_dream_funnel() : SpellScriptLoader("spell_gen_dream_funnel") { } + + class spell_gen_dream_funnel_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_dream_funnel_AuraScript); + + void HandleEffectCalcAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) + { + if (GetCaster()) + amount = GetCaster()->GetMaxHealth() * 0.05f; + + canBeRecalculated = false; + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_dream_funnel_AuraScript::HandleEffectCalcAmount, EFFECT_0, SPELL_AURA_PERIODIC_HEAL); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_dream_funnel_AuraScript::HandleEffectCalcAmount, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_dream_funnel_AuraScript(); + } +}; + +enum GenericBandage +{ + SPELL_RECENTLY_BANDAGED = 11196, +}; + +class spell_gen_bandage : public SpellScriptLoader +{ + public: + spell_gen_bandage() : SpellScriptLoader("spell_gen_bandage") { } + + class spell_gen_bandage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_bandage_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_RECENTLY_BANDAGED)) + return false; + return true; + } + + SpellCastResult CheckCast() + { + if (Unit* target = GetExplTargetUnit()) + { + if (target->HasAura(SPELL_RECENTLY_BANDAGED)) + return SPELL_FAILED_TARGET_AURASTATE; + } + return SPELL_CAST_OK; + } + + void HandleScript() + { + if (Unit* target = GetHitUnit()) + GetCaster()->CastSpell(target, SPELL_RECENTLY_BANDAGED, true); + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_gen_bandage_SpellScript::CheckCast); + AfterHit += SpellHitFn(spell_gen_bandage_SpellScript::HandleScript); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_bandage_SpellScript(); + } +}; + +enum GenericLifebloom +{ + SPELL_HEXLORD_MALACRASS_LIFEBLOOM_FINAL_HEAL = 43422, + SPELL_TUR_RAGEPAW_LIFEBLOOM_FINAL_HEAL = 52552, + SPELL_CENARION_SCOUT_LIFEBLOOM_FINAL_HEAL = 53692, + SPELL_TWISTED_VISAGE_LIFEBLOOM_FINAL_HEAL = 57763, + SPELL_FACTION_CHAMPIONS_DRU_LIFEBLOOM_FINAL_HEAL = 66094, +}; + +class spell_gen_lifebloom : public SpellScriptLoader +{ + public: + spell_gen_lifebloom(const char* name, uint32 spellId) : SpellScriptLoader(name), _spellId(spellId) { } + + class spell_gen_lifebloom_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_lifebloom_AuraScript); + + public: + spell_gen_lifebloom_AuraScript(uint32 spellId) : AuraScript(), _spellId(spellId) { } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(_spellId)) + return false; + return true; + } + + void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + // Final heal only on duration end + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + // final heal + GetTarget()->CastSpell(GetTarget(), _spellId, true, NULL, aurEff, GetCasterGUID()); + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_gen_lifebloom_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL); + } + + private: + uint32 _spellId; + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_lifebloom_AuraScript(_spellId); + } + + private: + uint32 _spellId; +}; + +enum SummonElemental +{ + SPELL_SUMMON_FIRE_ELEMENTAL = 8985, + SPELL_SUMMON_EARTH_ELEMENTAL = 19704 +}; + +class spell_gen_summon_elemental : public SpellScriptLoader +{ + public: + spell_gen_summon_elemental(const char* name, uint32 spellId) : SpellScriptLoader(name), _spellId(spellId) { } + + class spell_gen_summon_elemental_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_summon_elemental_AuraScript); + + public: + spell_gen_summon_elemental_AuraScript(uint32 spellId) : AuraScript(), _spellId(spellId) { } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(_spellId)) + return false; + return true; + } + + void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetCaster()) + if (Unit* owner = GetCaster()->GetOwner()) + owner->CastSpell(owner, _spellId, true); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetCaster()) + if (Unit* owner = GetCaster()->GetOwner()) + if (owner->GetTypeId() == TYPEID_PLAYER) // todo: this check is maybe wrong + owner->ToPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_gen_summon_elemental_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_gen_summon_elemental_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + + private: + uint32 _spellId; + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_summon_elemental_AuraScript(_spellId); + } + + private: + uint32 _spellId; +}; + +enum Mounts +{ + SPELL_COLD_WEATHER_FLYING = 54197, + + // Magic Broom + SPELL_MAGIC_BROOM_60 = 42680, + SPELL_MAGIC_BROOM_100 = 42683, + SPELL_MAGIC_BROOM_150 = 42667, + SPELL_MAGIC_BROOM_280 = 42668, + + // Headless Horseman's Mount + SPELL_HEADLESS_HORSEMAN_MOUNT_60 = 51621, + SPELL_HEADLESS_HORSEMAN_MOUNT_100 = 48024, + SPELL_HEADLESS_HORSEMAN_MOUNT_150 = 51617, + SPELL_HEADLESS_HORSEMAN_MOUNT_280 = 48023, + + // Winged Steed of the Ebon Blade + SPELL_WINGED_STEED_150 = 54726, + SPELL_WINGED_STEED_280 = 54727, + + // Big Love Rocket + SPELL_BIG_LOVE_ROCKET_0 = 71343, + SPELL_BIG_LOVE_ROCKET_60 = 71344, + SPELL_BIG_LOVE_ROCKET_100 = 71345, + SPELL_BIG_LOVE_ROCKET_150 = 71346, + SPELL_BIG_LOVE_ROCKET_310 = 71347, + + // Invincible + SPELL_INVINCIBLE_60 = 72281, + SPELL_INVINCIBLE_100 = 72282, + SPELL_INVINCIBLE_150 = 72283, + SPELL_INVINCIBLE_310 = 72284, + + // Blazing Hippogryph + SPELL_BLAZING_HIPPOGRYPH_150 = 74854, + SPELL_BLAZING_HIPPOGRYPH_280 = 74855, + + // Celestial Steed + SPELL_CELESTIAL_STEED_60 = 75619, + SPELL_CELESTIAL_STEED_100 = 75620, + SPELL_CELESTIAL_STEED_150 = 75617, + SPELL_CELESTIAL_STEED_280 = 75618, + SPELL_CELESTIAL_STEED_310 = 76153, + + // X-53 Touring Rocket + SPELL_X53_TOURING_ROCKET_150 = 75957, + SPELL_X53_TOURING_ROCKET_280 = 75972, + SPELL_X53_TOURING_ROCKET_310 = 76154, +}; + +class spell_gen_mount : public SpellScriptLoader +{ + public: + spell_gen_mount(const char* name, uint32 mount0 = 0, uint32 mount60 = 0, uint32 mount100 = 0, uint32 mount150 = 0, uint32 mount280 = 0, uint32 mount310 = 0) : SpellScriptLoader(name), + _mount0(mount0), _mount60(mount60), _mount100(mount100), _mount150(mount150), _mount280(mount280), _mount310(mount310) { } + + class spell_gen_mount_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_mount_SpellScript); + + public: + spell_gen_mount_SpellScript(uint32 mount0, uint32 mount60, uint32 mount100, uint32 mount150, uint32 mount280, uint32 mount310) : SpellScript(), + _mount0(mount0), _mount60(mount60), _mount100(mount100), _mount150(mount150), _mount280(mount280), _mount310(mount310) { } + + bool Validate(SpellInfo const* /*spell*/) + { + if (_mount0 && !sSpellMgr->GetSpellInfo(_mount0)) + return false; + if (_mount60 && !sSpellMgr->GetSpellInfo(_mount60)) + return false; + if (_mount100 && !sSpellMgr->GetSpellInfo(_mount100)) + return false; + if (_mount150 && !sSpellMgr->GetSpellInfo(_mount150)) + return false; + if (_mount280 && !sSpellMgr->GetSpellInfo(_mount280)) + return false; + if (_mount310 && !sSpellMgr->GetSpellInfo(_mount310)) + return false; + return true; + } + + void HandleMount(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + if (Player* target = GetHitPlayer()) + { + // Prevent stacking of mounts and client crashes upon dismounting + target->RemoveAurasByType(SPELL_AURA_MOUNTED, 0, GetHitAura()); + + // Triggered spell id dependent on riding skill and zone + bool canFly = false; + uint32 map = GetVirtualMapForMapAndZone(target->GetMapId(), target->GetZoneId()); + if (map == 530 || (map == 571 && target->HasSpell(SPELL_COLD_WEATHER_FLYING))) + canFly = true; + + float x, y, z; + target->GetPosition(x, y, z); + uint32 areaFlag = target->GetBaseMap()->GetAreaFlag(x, y, z); + AreaTableEntry const* area = sAreaStore.LookupEntry(areaFlag); + if (!area || (canFly && (area->flags & AREA_FLAG_NO_FLY_ZONE))) + canFly = false; + + uint32 mount = 0; + switch (target->GetBaseSkillValue(SKILL_RIDING)) + { + case 0: + mount = _mount0; + break; + case 75: + mount = _mount60; + break; + case 150: + mount = _mount100; + break; + case 225: + if (canFly) + mount = _mount150; + else + mount = _mount100; + break; + case 300: + if (canFly) + mount = _mount280; + else + mount = _mount100; + break; + case 375: + if (canFly) + mount = _mount310; + else + mount = _mount100; + break; + default: + break; + } + + if (mount) + { + PreventHitAura(); + target->CastSpell(target, mount, true); + } + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_gen_mount_SpellScript::HandleMount, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } + + private: + uint32 _mount0; + uint32 _mount60; + uint32 _mount100; + uint32 _mount150; + uint32 _mount280; + uint32 _mount310; + }; + + SpellScript* GetSpellScript() const + { + return new spell_gen_mount_SpellScript(_mount0, _mount60, _mount100, _mount150, _mount280, _mount310); + } + + private: + uint32 _mount0; + uint32 _mount60; + uint32 _mount100; + uint32 _mount150; + uint32 _mount280; + uint32 _mount310; +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -2742,4 +3131,22 @@ void AddSC_generic_spell_scripts() new spell_gen_count_pct_from_max_hp("spell_gen_default_count_pct_from_max_hp"); new spell_gen_count_pct_from_max_hp("spell_gen_50pct_count_pct_from_max_hp", 50); new spell_gen_despawn_self(); + new spell_gen_touch_the_nightmare(); + new spell_gen_dream_funnel(); + new spell_gen_bandage(); + new spell_gen_lifebloom("spell_hexlord_lifebloom", SPELL_HEXLORD_MALACRASS_LIFEBLOOM_FINAL_HEAL); + new spell_gen_lifebloom("spell_tur_ragepaw_lifebloom", SPELL_TUR_RAGEPAW_LIFEBLOOM_FINAL_HEAL); + new spell_gen_lifebloom("spell_cenarion_scout_lifebloom", SPELL_CENARION_SCOUT_LIFEBLOOM_FINAL_HEAL); + new spell_gen_lifebloom("spell_twisted_visage_lifebloom", SPELL_TWISTED_VISAGE_LIFEBLOOM_FINAL_HEAL); + new spell_gen_lifebloom("spell_faction_champion_dru_lifebloom", SPELL_FACTION_CHAMPIONS_DRU_LIFEBLOOM_FINAL_HEAL); + new spell_gen_summon_elemental("spell_gen_summon_fire_elemental", SPELL_SUMMON_FIRE_ELEMENTAL); + new spell_gen_summon_elemental("spell_gen_summon_earth_elemental", SPELL_SUMMON_EARTH_ELEMENTAL); + new spell_gen_mount("spell_magic_broom", 0, SPELL_MAGIC_BROOM_60, SPELL_MAGIC_BROOM_100, SPELL_MAGIC_BROOM_150, SPELL_MAGIC_BROOM_280); + new spell_gen_mount("spell_headless_horseman_mount", 0, SPELL_HEADLESS_HORSEMAN_MOUNT_60, SPELL_HEADLESS_HORSEMAN_MOUNT_100, SPELL_HEADLESS_HORSEMAN_MOUNT_150, SPELL_HEADLESS_HORSEMAN_MOUNT_280); + new spell_gen_mount("spell_winged_steed_of_the_ebon_blade", 0, 0, 0, SPELL_WINGED_STEED_150, SPELL_WINGED_STEED_280); + new spell_gen_mount("spell_big_love_rocket", SPELL_BIG_LOVE_ROCKET_0, SPELL_BIG_LOVE_ROCKET_60, SPELL_BIG_LOVE_ROCKET_100, SPELL_BIG_LOVE_ROCKET_150, SPELL_BIG_LOVE_ROCKET_310); + new spell_gen_mount("spell_invincible", 0, SPELL_INVINCIBLE_60, SPELL_INVINCIBLE_100, SPELL_INVINCIBLE_150, SPELL_INVINCIBLE_310); + new spell_gen_mount("spell_blazing_hippogryph", 0, 0, 0, SPELL_BLAZING_HIPPOGRYPH_150, SPELL_BLAZING_HIPPOGRYPH_280); + new spell_gen_mount("spell_celestial_steed", 0, SPELL_CELESTIAL_STEED_60, SPELL_CELESTIAL_STEED_100, SPELL_CELESTIAL_STEED_150, SPELL_CELESTIAL_STEED_280, SPELL_CELESTIAL_STEED_310); + new spell_gen_mount("spell_x53_touring_rocket", 0, 0, 0, SPELL_X53_TOURING_ROCKET_150, SPELL_X53_TOURING_ROCKET_280, SPELL_X53_TOURING_ROCKET_310); } diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 896ed331bde..a2ee6c1c3a3 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -618,6 +618,86 @@ class spell_hun_misdirection_proc : public SpellScriptLoader } }; +class spell_hun_disengage : public SpellScriptLoader +{ + public: + spell_hun_disengage() : SpellScriptLoader("spell_hun_disengage") { } + + class spell_hun_disengage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_hun_disengage_SpellScript); + + SpellCastResult CheckCast() + { + Unit* caster = GetCaster(); + if (caster->GetTypeId() == TYPEID_PLAYER && !caster->isInCombat()) + return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; + + return SPELL_CAST_OK; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_hun_disengage_SpellScript::CheckCast); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_hun_disengage_SpellScript(); + } +}; + +class spell_hun_tame_beast : public SpellScriptLoader +{ + public: + spell_hun_tame_beast() : SpellScriptLoader("spell_hun_tame_beast") { } + + class spell_hun_tame_beast_SpellScript : public SpellScript + { + PrepareSpellScript(spell_hun_tame_beast_SpellScript); + + SpellCastResult CheckCast() + { + Unit* caster = GetCaster(); + if (caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_DONT_REPORT; + + if (!GetExplTargetUnit()) + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + if (Creature* target = GetExplTargetUnit()->ToCreature()) + { + if (target->getLevel() > caster->getLevel()) + return SPELL_FAILED_HIGHLEVEL; + + // use SMSG_PET_TAME_FAILURE? + if (!target->GetCreatureTemplate()->isTameable(caster->ToPlayer()->CanTameExoticPets())) + return SPELL_FAILED_BAD_TARGETS; + + if (caster->GetPetGUID()) + return SPELL_FAILED_ALREADY_HAVE_SUMMON; + + if (caster->GetCharmGUID()) + return SPELL_FAILED_ALREADY_HAVE_CHARM; + } + else + return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + + return SPELL_CAST_OK; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_hun_tame_beast_SpellScript::CheckCast); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_hun_tame_beast_SpellScript(); + } +}; void AddSC_hunter_spell_scripts() { @@ -633,4 +713,6 @@ void AddSC_hunter_spell_scripts() new spell_hun_pet_carrion_feeder(); new spell_hun_misdirection(); new spell_hun_misdirection_proc(); + new spell_hun_disengage(); + new spell_hun_tame_beast(); } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 4e2eb633662..3c89cb7005a 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -1848,60 +1848,6 @@ class spell_item_unusual_compass : public SpellScriptLoader } }; -enum UDED -{ - NPC_IRONWOOL_MAMMOTH = 53806, - SPELL_MAMMOTH_CARCASS = 57444, - SPELL_MAMMOTH_MEAT = 54625, -}; - -class spell_item_uded : public SpellScriptLoader -{ - public: - spell_item_uded() : SpellScriptLoader("spell_item_uded") { } - - class spell_item_uded_SpellScript : public SpellScript - { - PrepareSpellScript(spell_item_uded_SpellScript); - - bool Load() - { - if (GetHitCreature() && GetHitCreature()->GetEntry() == NPC_IRONWOOL_MAMMOTH) - return true; - return false; - } - - bool Validate(SpellInfo const* /*spell*/) - { - if (!sSpellMgr->GetSpellInfo(SPELL_MAMMOTH_CARCASS) || !sSpellMgr->GetSpellInfo(SPELL_MAMMOTH_MEAT)) - return false; - return true; - } - - void HandleDummy(SpellEffIndex /* effIndex */) - { - Unit* caster = GetCaster(); - Creature* creature = GetHitCreature(); - caster->CastSpell(caster,SPELL_MAMMOTH_CARCASS,true); - - for (uint8 i = 0; i < 4; ++i) - caster->CastSpell(caster,SPELL_MAMMOTH_MEAT,true); - - creature->Kill(creature); - } - - void Register() - { - OnEffectHitTarget += SpellEffectFn(spell_item_uded_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const - { - return new spell_item_uded_SpellScript(); - } -}; - enum ChickenCover { SPELL_CHICKEN_NET = 51959, @@ -2109,7 +2055,6 @@ void AddSC_item_spell_scripts() new spell_item_rocket_boots(); new spell_item_pygmy_oil(); new spell_item_unusual_compass(); - new spell_item_uded(); new spell_item_chicken_cover(); new spell_item_muisek_vessel(); new spell_item_greatmothers_soulcatcher(); diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 050741ffaba..0edfbaee437 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -342,13 +342,52 @@ public: } }; +class spell_mage_living_bomb : public SpellScriptLoader +{ + public: + spell_mage_living_bomb() : SpellScriptLoader("spell_mage_living_bomb") { } + + class spell_mage_living_bomb_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_living_bomb_AuraScript); + + bool Validate(SpellInfo const* spell) + { + if (!sSpellMgr->GetSpellInfo(uint32(spell->Effects[EFFECT_1].CalcValue()))) + return false; + return true; + } + + void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + AuraRemoveMode removeMode = GetTargetApplication()->GetRemoveMode(); + if (removeMode != AURA_REMOVE_BY_ENEMY_SPELL && removeMode != AURA_REMOVE_BY_EXPIRE) + return; + + if (Unit* caster = GetCaster()) + caster->CastSpell(GetTarget(), uint32(aurEff->GetAmount()), true, NULL, aurEff); + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_mage_living_bomb_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_mage_living_bomb_AuraScript(); + } +}; + void AddSC_mage_spell_scripts() { - new spell_mage_blast_wave; - new spell_mage_cold_snap; + new spell_mage_blast_wave(); + new spell_mage_cold_snap(); new spell_mage_frost_warding_trigger(); new spell_mage_incanters_absorbtion_absorb(); new spell_mage_incanters_absorbtion_manashield(); - new spell_mage_polymorph_cast_visual; - new spell_mage_summon_water_elemental; + new spell_mage_polymorph_cast_visual(); + new spell_mage_summon_water_elemental(); + new spell_mage_living_bomb(); } diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 4baa1eb3735..7d248b35853 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -43,6 +43,10 @@ enum PaladinSpells SPELL_DIVINE_STORM = 53385, SPELL_DIVINE_STORM_DUMMY = 54171, SPELL_DIVINE_STORM_HEAL = 54172, + + SPELL_FORBEARANCE = 25771, + SPELL_AVENGING_WRATH_MARKER = 61987, + SPELL_IMMUNE_SHIELD_MARKER = 61988, }; // 31850 - Ardent Defender @@ -255,17 +259,18 @@ class spell_pal_holy_shock : public SpellScriptLoader class spell_pal_holy_shock_SpellScript : public SpellScript { - PrepareSpellScript(spell_pal_holy_shock_SpellScript) - bool Validate(SpellInfo const* spellEntry) + PrepareSpellScript(spell_pal_holy_shock_SpellScript); + + bool Validate(SpellInfo const* spell) { if (!sSpellMgr->GetSpellInfo(PALADIN_SPELL_HOLY_SHOCK_R1)) return false; // can't use other spell than holy shock due to spell_ranks dependency - if (sSpellMgr->GetFirstSpellInChain(PALADIN_SPELL_HOLY_SHOCK_R1) != sSpellMgr->GetFirstSpellInChain(spellEntry->Id)) + if (sSpellMgr->GetFirstSpellInChain(PALADIN_SPELL_HOLY_SHOCK_R1) != sSpellMgr->GetFirstSpellInChain(spell->Id)) return false; - uint8 rank = sSpellMgr->GetSpellRank(spellEntry->Id); + uint8 rank = sSpellMgr->GetSpellRank(spell->Id); if (!sSpellMgr->GetSpellWithRank(PALADIN_SPELL_HOLY_SHOCK_R1_DAMAGE, rank, true) || !sSpellMgr->GetSpellWithRank(PALADIN_SPELL_HOLY_SHOCK_R1_HEALING, rank, true)) return false; @@ -287,7 +292,7 @@ class spell_pal_holy_shock : public SpellScriptLoader SpellCastResult CheckCast() { - Player* caster = GetCaster()->ToPlayer(); + Unit* caster = GetCaster(); if (Unit* target = GetExplTargetUnit()) { if (!caster->IsFriendlyTo(target)) @@ -404,7 +409,7 @@ class spell_pal_divine_storm_dummy : public SpellScriptLoader return true; } - void CountTargets(std::list<Unit*>& targetList) + void CountTargets(std::list<WorldObject*>& targetList) { _targetCount = targetList.size(); } @@ -423,7 +428,7 @@ class spell_pal_divine_storm_dummy : public SpellScriptLoader void Register() { OnEffectHitTarget += SpellEffectFn(spell_pal_divine_storm_dummy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - OnUnitTargetSelect += SpellUnitTargetFn(spell_pal_divine_storm_dummy_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pal_divine_storm_dummy_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID); } }; @@ -433,6 +438,99 @@ class spell_pal_divine_storm_dummy : public SpellScriptLoader } }; +class spell_pal_lay_on_hands : public SpellScriptLoader +{ + public: + spell_pal_lay_on_hands() : SpellScriptLoader("spell_pal_lay_on_hands") { } + + class spell_pal_lay_on_hands_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pal_lay_on_hands_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_FORBEARANCE)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_AVENGING_WRATH_MARKER)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_IMMUNE_SHIELD_MARKER)) + return false; + return true; + } + + SpellCastResult CheckCast() + { + Unit* caster = GetCaster(); + if (Unit* target = GetExplTargetUnit()) + if (caster == target) + if (target->HasAura(SPELL_FORBEARANCE) || target->HasAura(SPELL_AVENGING_WRATH_MARKER) || target->HasAura(SPELL_IMMUNE_SHIELD_MARKER)) + return SPELL_FAILED_TARGET_AURASTATE; + + return SPELL_CAST_OK; + } + + void HandleScript() + { + Unit* caster = GetCaster(); + if (caster == GetHitUnit()) + { + caster->CastSpell(caster, SPELL_FORBEARANCE, true); + caster->CastSpell(caster, SPELL_AVENGING_WRATH_MARKER, true); + caster->CastSpell(caster, SPELL_IMMUNE_SHIELD_MARKER, true); + } + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_pal_lay_on_hands_SpellScript::CheckCast); + AfterHit += SpellHitFn(spell_pal_lay_on_hands_SpellScript::HandleScript); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_pal_lay_on_hands_SpellScript(); + } +}; + +class spell_pal_righteous_defense : public SpellScriptLoader +{ + public: + spell_pal_righteous_defense() : SpellScriptLoader("spell_pal_righteous_defense") { } + + class spell_pal_righteous_defense_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pal_righteous_defense_SpellScript); + + SpellCastResult CheckCast() + { + Unit* caster = GetCaster(); + if (caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_DONT_REPORT; + + if (Unit* target = GetExplTargetUnit()) + { + if (!target->IsFriendlyTo(caster) || target->getAttackers().empty()) + return SPELL_FAILED_BAD_TARGETS; + } + else + return SPELL_FAILED_BAD_TARGETS; + + return SPELL_CAST_OK; + } + + void Register() + { + OnCheckCast += SpellCheckCastFn(spell_pal_righteous_defense_SpellScript::CheckCast); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_pal_righteous_defense_SpellScript(); + } +}; + void AddSC_paladin_spell_scripts() { new spell_pal_ardent_defender(); @@ -443,4 +541,6 @@ void AddSC_paladin_spell_scripts() new spell_pal_judgement_of_command(); new spell_pal_divine_storm(); new spell_pal_divine_storm_dummy(); + new spell_pal_lay_on_hands(); + new spell_pal_righteous_defense(); } diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp new file mode 100644 index 00000000000..4928ec40abd --- /dev/null +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -0,0 +1,1726 @@ +/* + * Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* + * Scripts for spells with SPELLFAMILY_DEATHKNIGHT and SPELLFAMILY_GENERIC spells used by deathknight players. + * Ordered alphabetically using scriptname. + * Scriptnames of files in this file should be prefixed with "spell_dk_". + */ + +#include "ScriptMgr.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "Unit.h" +#include "Player.h" +#include "Pet.h" + +enum HunterPetCalculate +{ + SPELL_TAMED_PET_PASSIVE_06 = 19591, + SPELL_TAMED_PET_PASSIVE_07 = 20784, + SPELL_TAMED_PET_PASSIVE_08 = 34666, + SPELL_TAMED_PET_PASSIVE_09 = 34667, + SPELL_TAMED_PET_PASSIVE_10 = 34675, + SPELL_HUNTER_PET_SCALING_01 = 34902, + SPELL_HUNTER_PET_SCALING_02 = 34903, + SPELL_HUNTER_PET_SCALING_03 = 34904, + SPELL_HUNTER_PET_SCALING_04 = 61017, + SPELL_HUNTER_ANIMAL_HANDLER = 34453, +}; + +enum WarlockPetCalculate +{ + SPELL_PET_PASSIVE_CRIT = 35695, + SPELL_PET_PASSIVE_DAMAGE_TAKEN = 35697, + SPELL_WARLOCK_PET_SCALING_01 = 34947, + SPELL_WARLOCK_PET_SCALING_02 = 34956, + SPELL_WARLOCK_PET_SCALING_03 = 34957, + SPELL_WARLOCK_PET_SCALING_04 = 34958, + SPELL_WARLOCK_PET_SCALING_05 = 61013, + ENTRY_FELGUARD = 17252, + ENTRY_VOIDWALKER = 1860, + ENTRY_FELHUNTER = 417, + ENTRY_SUCCUBUS = 1863, + ENTRY_IMP = 416, + SPELL_WARLOCK_GLYPH_OF_VOIDWALKER = 56247, +}; + +enum DKPetCalculate +{ + SPELL_DEATH_KNIGHT_RUNE_WEAPON_02 = 51906, + SPELL_DEATH_KNIGHT_PET_SCALING_01 = 54566, + SPELL_DEATH_KNIGHT_PET_SCALING_02 = 51996, + SPELL_DEATH_KNIGHT_PET_SCALING_03 = 61697, + SPELL_NIGHT_OF_THE_DEAD = 55620, + ENTRY_ARMY_OF_THE_DEAD_GHOUL = 24207, + SPELL_DEATH_KNIGHT_GLYPH_OF_GHOUL = 58686, +}; + +enum ShamanPetCalculate +{ + SPELL_FERAL_SPIRIT_PET_UNK_01 = 35674, + SPELL_FERAL_SPIRIT_PET_UNK_02 = 35675, + SPELL_FERAL_SPIRIT_PET_UNK_03 = 35676, + SPELL_FERAL_SPIRIT_PET_SCALING_04 = 61783, +}; + +enum MiscPetCalculate +{ + SPELL_MAGE_PET_PASSIVE_ELEMENTAL = 44559, + SPELL_PET_HEALTH_SCALING = 61679, + SPELL_PET_UNK_01 = 67561, + SPELL_PET_UNK_02 = 67557, +}; + +class spell_gen_pet_calculate : public SpellScriptLoader +{ + public: + spell_gen_pet_calculate() : SpellScriptLoader("spell_gen_pet_calculate") { } + + class spell_gen_pet_calculate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_pet_calculate_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountCritSpell(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritSpell = 0.0f; + // Crit from Intellect + CritSpell += owner->GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit spell from spell crit ratings + CritSpell += owner->GetRatingBonusValue(CR_CRIT_SPELL); + + amount += int32(CritSpell); + } + } + + void CalculateAmountCritMelee(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritMelee = 0.0f; + // Crit from Agility + CritMelee += owner->GetMeleeCritFromAgility(); + // Increase crit from SPELL_AURA_MOD_WEAPON_CRIT_PERCENT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit melee from melee crit ratings + CritMelee += owner->GetRatingBonusValue(CR_CRIT_MELEE); + + amount += int32(CritMelee); + } + } + + void CalculateAmountMeleeHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void CalculateAmountExpertise(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float Expertise = 0.0f; + // Increase hit from SPELL_AURA_MOD_EXPERTISE + Expertise += owner->GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE); + // Increase Expertise from Expertise ratings + Expertise += owner->GetRatingBonusValue(CR_EXPERTISE); + + amount += int32(Expertise); + } + } + + void Register() + { + switch (m_scriptSpellId) + { + case SPELL_TAMED_PET_PASSIVE_06: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritMelee, EFFECT_0, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritSpell, EFFECT_1, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + break; + case SPELL_PET_PASSIVE_CRIT: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritSpell, EFFECT_0, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountCritMelee, EFFECT_1, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + break; + case SPELL_WARLOCK_PET_SCALING_05: + case SPELL_HUNTER_PET_SCALING_04: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountExpertise, EFFECT_2, SPELL_AURA_MOD_EXPERTISE); + break; + case SPELL_DEATH_KNIGHT_PET_SCALING_03: +// case SPELL_SHAMAN_PET_HIT: + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_gen_pet_calculate_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + break; + default: + break; + } + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_gen_pet_calculate_AuraScript(); + } +}; + +class spell_warl_pet_scaling_01 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_01() : SpellScriptLoader("spell_warl_pet_scaling_01") { } + + class spell_warl_pet_scaling_01_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_01_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + _tempBonus = 0; + return true; + } + + void CalculateStaminaAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = CalculatePctN(owner->GetStat(STAT_STAMINA), 75); + + amount += ownerBonus; + } + } + + void ApplyEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempBonus) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + uint32 healthMod = 0; + uint32 baseHealth = pInfo->health; + switch (pet->GetEntry()) + { + case ENTRY_IMP: + healthMod = uint32(_tempBonus * 8.4f); + break; + case ENTRY_FELGUARD: + case ENTRY_VOIDWALKER: + healthMod = _tempBonus * 11; + break; + case ENTRY_SUCCUBUS: + healthMod = uint32(_tempBonus * 9.1f); + break; + case ENTRY_FELHUNTER: + healthMod = uint32(_tempBonus * 9.5f); + break; + default: + healthMod = 0; + break; + } + if (healthMod) + pet->ToPet()->SetCreateHealth(baseHealth + healthMod); + } + } + + void RemoveEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + pet->ToPet()->SetCreateHealth(pInfo->health); + } + } + + void CalculateAttackPowerAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + + if (Unit* owner = pet->ToPet()->GetOwner()) + { + int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); + int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW); + int32 maximum = (fire > shadow) ? fire : shadow; + if (maximum < 0) + maximum = 0; + float bonusAP = maximum * 0.57f; + + amount += bonusAP; + + // Glyph of felguard + if (pet->GetEntry() == ENTRY_FELGUARD) + { + if (AuraEffect* /* aurEff */ect = owner->GetAuraEffect(56246, EFFECT_0)) + { + float base_attPower = pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE) * pet->GetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_PCT); + amount += CalculatePctN(amount+base_attPower, /* aurEff */ect->GetAmount()); + } + } + } + } + + void CalculateDamageDoneAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + //the damage bonus used for pets is either fire or shadow damage, whatever is higher + int32 fire = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_FIRE)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_FIRE); + int32 shadow = int32(owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS + SPELL_SCHOOL_SHADOW)) - owner->GetUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG + SPELL_SCHOOL_SHADOW); + int32 maximum = (fire > shadow) ? fire : shadow; + float bonusDamage = 0.0f; + + if (maximum > 0) + bonusDamage = maximum * 0.15f; + + amount += bonusDamage; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_warl_pet_scaling_01_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_warl_pet_scaling_01_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_01_AuraScript::CalculateStaminaAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_01_AuraScript::CalculateAttackPowerAmount, EFFECT_1, SPELL_AURA_MOD_ATTACK_POWER); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_01_AuraScript::CalculateDamageDoneAmount, EFFECT_2, SPELL_AURA_MOD_DAMAGE_DONE); + } + + private: + uint32 _tempBonus; + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_01_AuraScript(); + } +}; + +class spell_warl_pet_scaling_02 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_02() : SpellScriptLoader("spell_warl_pet_scaling_02") { } + + class spell_warl_pet_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + _tempBonus = 0; + return true; + } + + void CalculateIntellectAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetStat(STAT_INTELLECT), 30); + + amount += ownerBonus; + _tempBonus = ownerBonus; + } + } + + void ApplyEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempBonus) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + uint32 manaMod = 0; + uint32 baseMana = pInfo->mana; + switch (pet->GetEntry()) + { + case ENTRY_IMP: + manaMod = uint32(_tempBonus * 4.9f); + break; + case ENTRY_VOIDWALKER: + case ENTRY_SUCCUBUS: + case ENTRY_FELHUNTER: + case ENTRY_FELGUARD: + manaMod = uint32(_tempBonus * 11.5f); + break; + default: + manaMod = 0; + break; + } + if (manaMod) + pet->ToPet()->SetCreateMana(baseMana + manaMod); + } + } + + void RemoveEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + { + PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(pet->GetEntry(), pet->getLevel()); + pet->ToPet()->SetCreateMana(pInfo->mana); + } + } + + void CalculateArmorAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetArmor(), 35); + amount += ownerBonus; + } + } + + void CalculateFireResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FIRE), 40); + amount += ownerBonus; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_warl_pet_scaling_02_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_warl_pet_scaling_02_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_02_AuraScript::CalculateIntellectAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_02_AuraScript::CalculateArmorAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_02_AuraScript::CalculateFireResistanceAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + + private: + uint32 _tempBonus; + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_02_AuraScript(); + } +}; + +class spell_warl_pet_scaling_03 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_03() : SpellScriptLoader("spell_warl_pet_scaling_03") { } + + class spell_warl_pet_scaling_03_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_03_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateFrostResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FROST), 40); + amount += ownerBonus; + } + } + + void CalculateArcaneResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_ARCANE), 40); + amount += ownerBonus; + } + } + + void CalculateNatureResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_NATURE), 40); + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_03_AuraScript::CalculateFrostResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_03_AuraScript::CalculateArcaneResistanceAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_03_AuraScript::CalculateNatureResistanceAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_03_AuraScript(); + } +}; + + +class spell_warl_pet_scaling_04 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_04() : SpellScriptLoader("spell_warl_pet_scaling_04") { } + + class spell_warl_pet_scaling_04_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_04_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateShadowResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float ownerBonus = 0.0f; + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_SHADOW), 40); + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_04_AuraScript::CalculateShadowResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_04_AuraScript(); + } +}; + +class spell_warl_pet_scaling_05 : public SpellScriptLoader +{ +public: + spell_warl_pet_scaling_05() : SpellScriptLoader("spell_warl_pet_scaling_05") { } + + class spell_warl_pet_scaling_05_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_scaling_05_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void CalculateAmountExpertise(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float Expertise = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + Expertise += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + Expertise += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(Expertise); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_05_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_05_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_scaling_05_AuraScript::CalculateAmountExpertise, EFFECT_2, SPELL_AURA_MOD_EXPERTISE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_scaling_05_AuraScript(); + } +}; + +class spell_warl_pet_passive : public SpellScriptLoader +{ +public: + spell_warl_pet_passive() : SpellScriptLoader("spell_warl_pet_passive") { } + + class spell_warl_pet_passive_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_passive_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountCritSpell(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritSpell = 0.0f; + // Crit from Intellect + CritSpell += owner->GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit spell from spell crit ratings + CritSpell += owner->GetRatingBonusValue(CR_CRIT_SPELL); + + if (AuraApplication* improvedDemonicTacticsApp = owner->GetAuraApplicationOfRankedSpell(54347)) + if (Aura* improvedDemonicTactics = improvedDemonicTacticsApp->GetBase()) + if (AuraEffect* improvedDemonicTacticsEffect = improvedDemonicTactics->GetEffect(EFFECT_0)) + amount += CalculatePctN(CritSpell, improvedDemonicTacticsEffect->GetAmount()); + } + } + + void CalculateAmountCritMelee(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritMelee = 0.0f; + // Crit from Agility + CritMelee += owner->GetMeleeCritFromAgility(); + // Increase crit from SPELL_AURA_MOD_WEAPON_CRIT_PERCENT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit melee from melee crit ratings + CritMelee += owner->GetRatingBonusValue(CR_CRIT_MELEE); + + if (AuraApplication* improvedDemonicTacticsApp = owner->GetAuraApplicationOfRankedSpell(54347)) + if (Aura* improvedDemonicTactics = improvedDemonicTacticsApp->GetBase()) + if (AuraEffect* improvedDemonicTacticsEffect = improvedDemonicTactics->GetEffect(EFFECT_0)) + amount += CalculatePctN(CritMelee, improvedDemonicTacticsEffect->GetAmount()); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_AuraScript::CalculateAmountCritSpell, EFFECT_0, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_AuraScript::CalculateAmountCritMelee, EFFECT_1, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_passive_AuraScript(); + } +}; +// this doesnt actually fit in here +class spell_warl_pet_passive_damage_done : public SpellScriptLoader +{ +public: + spell_warl_pet_passive_damage_done() : SpellScriptLoader("spell_warl_pet_passive_damage_done") { } + + class spell_warl_pet_passive_damage_done_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_passive_damage_done_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountDamageDone(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (GetCaster()->GetOwner()->ToPlayer()) + { + switch (GetCaster()->GetEntry()) + { + case ENTRY_VOIDWALKER: + amount += -16; + break; + case ENTRY_FELHUNTER: + amount += -20; + break; + case ENTRY_SUCCUBUS: + case ENTRY_FELGUARD: + amount += 5; + break; + } + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_damage_done_AuraScript::CalculateAmountDamageDone, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_damage_done_AuraScript::CalculateAmountDamageDone, EFFECT_1, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_passive_damage_done_AuraScript(); + } +}; + +class spell_warl_pet_passive_voidwalker : public SpellScriptLoader +{ +public: + spell_warl_pet_passive_voidwalker() : SpellScriptLoader("spell_warl_pet_passive_voidwalker") { } + + class spell_warl_pet_passive_voidwalker_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_pet_passive_voidwalker_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + if (AuraEffect* /* aurEff */ect = owner->GetAuraEffect(SPELL_WARLOCK_GLYPH_OF_VOIDWALKER, EFFECT_0)) + amount += /* aurEff */ect->GetAmount(); + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_warl_pet_passive_voidwalker_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_pet_passive_voidwalker_AuraScript(); + } +}; + + +class spell_sha_pet_scaling_04 : public SpellScriptLoader +{ +public: + spell_sha_pet_scaling_04() : SpellScriptLoader("spell_sha_pet_scaling_04") { } + + class spell_sha_pet_scaling_04_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_pet_scaling_04_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_pet_scaling_04_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_sha_pet_scaling_04_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_sha_pet_scaling_04_AuraScript(); + } +}; + +class spell_hun_pet_scaling_01 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_01() : SpellScriptLoader("spell_hun_pet_scaling_01") { } + + class spell_hun_pet_scaling_01_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_01_AuraScript); + + void CalculateStaminaAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + if (pet->isPet()) + if (Unit* owner = pet->ToPet()->GetOwner()) + { + float mod = 0.45f; + float ownerBonus = 0.0f; + + PetSpellMap::const_iterator itr = (pet->ToPet()->m_spells.find(62758)); // Wild Hunt rank 1 + if (itr == pet->ToPet()->m_spells.end()) + itr = pet->ToPet()->m_spells.find(62762); // Wild Hunt rank 2 + + if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + AddPctN(mod, spellInfo->Effects[EFFECT_0].CalcValue()); + } + + ownerBonus = owner->GetStat(STAT_STAMINA)*mod; + + amount += ownerBonus; + } + } + + void ApplyEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempHealth) + pet->SetHealth(_tempHealth); + } + + void RemoveEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + _tempHealth = pet->GetHealth(); + } + + void CalculateAttackPowerAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float mod = 1.0f; //Hunter contribution modifier + float bonusAP = 0.0f; + + PetSpellMap::const_iterator itr = (pet->ToPet()->m_spells.find(62758)); // Wild Hunt rank 1 + if (itr == pet->ToPet()->m_spells.end()) + itr = pet->ToPet()->m_spells.find(62762); // Wild Hunt rank 2 + + if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + mod += CalculatePctN(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); + } + + bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f * mod; + + amount += bonusAP; + } + } + + void CalculateDamageDoneAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float mod = 1.0f; //Hunter contribution modifier + float bonusDamage = 0.0f; + + PetSpellMap::const_iterator itr = (pet->ToPet()->m_spells.find(62758)); // Wild Hunt rank 1 + if (itr == pet->ToPet()->m_spells.end()) + itr = pet->ToPet()->m_spells.find(62762); // Wild Hunt rank 2 + + if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + mod += CalculatePctN(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); + } + + bonusDamage = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f * mod; + + amount += bonusDamage; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_hun_pet_scaling_01_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_hun_pet_scaling_01_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_01_AuraScript::CalculateStaminaAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_01_AuraScript::CalculateAttackPowerAmount, EFFECT_1, SPELL_AURA_MOD_ATTACK_POWER); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_01_AuraScript::CalculateDamageDoneAmount, EFFECT_2, SPELL_AURA_MOD_DAMAGE_DONE); + } + + private: + uint32 _tempHealth; + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_01_AuraScript(); + } +}; + +class spell_hun_pet_scaling_02 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_02() : SpellScriptLoader("spell_hun_pet_scaling_02") { } + + class spell_hun_pet_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateFrostResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FROST), 40); + + amount += ownerBonus; + } + } + + void CalculateFireResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_FIRE), 40); + + amount += ownerBonus; + } + } + + void CalculateNatureResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_NATURE), 40); + + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_02_AuraScript::CalculateFrostResistanceAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_02_AuraScript::CalculateFireResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_02_AuraScript::CalculateNatureResistanceAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_02_AuraScript(); + } +}; + +class spell_hun_pet_scaling_03 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_03() : SpellScriptLoader("spell_hun_pet_scaling_03") { } + + class spell_hun_pet_scaling_03_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_03_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateShadowResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_SHADOW), 40); + + amount += ownerBonus; + } + } + + void CalculateArcaneResistanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetResistance(SPELL_SCHOOL_ARCANE), 40); + + amount += ownerBonus; + } + } + + void CalculateArmorAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isPet()) + return; + + Unit* owner = pet->ToPet()->GetOwner(); + if (!owner) + return; + + float ownerBonus = 0.0f; + + ownerBonus = CalculatePctN(owner->GetArmor(), 35); + + amount += ownerBonus; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_03_AuraScript::CalculateShadowResistanceAmount, EFFECT_0, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_03_AuraScript::CalculateArcaneResistanceAmount, EFFECT_1, SPELL_AURA_MOD_RESISTANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_03_AuraScript::CalculateArmorAmount, EFFECT_2, SPELL_AURA_MOD_RESISTANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_03_AuraScript(); + } +}; + +class spell_hun_pet_scaling_04 : public SpellScriptLoader +{ +public: + spell_hun_pet_scaling_04() : SpellScriptLoader("spell_hun_pet_scaling_04") { } + + class spell_hun_pet_scaling_04_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_scaling_04_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void CalculateAmountExpertise(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float Expertise = 0.0f; + // Increase hit from SPELL_AURA_MOD_EXPERTISE + Expertise += owner->GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE); + // Increase Expertise from Expertise ratings + Expertise += owner->GetRatingBonusValue(CR_EXPERTISE); + + amount += int32(Expertise); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_04_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_04_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_scaling_04_AuraScript::CalculateAmountExpertise, EFFECT_2, SPELL_AURA_MOD_EXPERTISE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_scaling_04_AuraScript(); + } +}; + +class spell_hun_pet_passive_crit : public SpellScriptLoader +{ +public: + spell_hun_pet_passive_crit() : SpellScriptLoader("spell_hun_pet_passive_crit") { } + + class spell_hun_pet_passive_crit_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_passive_crit_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountCritSpell(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritSpell = 0.0f; + // Crit from Intellect + // CritSpell += owner->GetSpellCritFromIntellect(); + // Increase crit from SPELL_AURA_MOD_SPELL_CRIT_CHANCE + // CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + // CritSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit spell from spell crit ratings + // CritSpell += owner->GetRatingBonusValue(CR_CRIT_SPELL); + + amount += (CritSpell*0.8f); + } + } + + void CalculateAmountCritMelee(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float CritMelee = 0.0f; + // Crit from Agility + // CritMelee += owner->GetMeleeCritFromAgility(); + // Increase crit from SPELL_AURA_MOD_WEAPON_CRIT_PERCENT + // CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + // Increase crit from SPELL_AURA_MOD_CRIT_PCT + // CritMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PCT); + // Increase crit melee from melee crit ratings + // CritMelee += owner->GetRatingBonusValue(CR_CRIT_MELEE); + + amount += (CritMelee*0.8f); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_passive_crit_AuraScript::CalculateAmountCritSpell, EFFECT_1, SPELL_AURA_MOD_SPELL_CRIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_passive_crit_AuraScript::CalculateAmountCritMelee, EFFECT_0, SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_passive_crit_AuraScript(); + } +}; + +class spell_hun_pet_passive_damage_done : public SpellScriptLoader +{ +public: + spell_hun_pet_passive_damage_done() : SpellScriptLoader("spell_hun_pet_passive_damage_done") { } + + class spell_hun_pet_passive_damage_done_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_pet_passive_damage_done_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountDamageDone(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (GetCaster()->GetOwner()->ToPlayer()) + { + // Cobra Reflexes + if (AuraEffect* cobraReflexes = GetCaster()->GetAuraEffectOfRankedSpell(61682, EFFECT_0)) + amount -= cobraReflexes->GetAmount(); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_pet_passive_damage_done_AuraScript::CalculateAmountDamageDone, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_pet_passive_damage_done_AuraScript(); + } +}; + +class spell_hun_animal_handler : public SpellScriptLoader +{ +public: + spell_hun_animal_handler() : SpellScriptLoader("spell_hun_animal_handler") { } + + class spell_hun_animal_handler_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_animal_handler_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountDamageDone(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + if (AuraEffect* /* aurEff */ect = owner->GetAuraEffectOfRankedSpell(SPELL_HUNTER_ANIMAL_HANDLER, EFFECT_1)) + amount = /* aurEff */ect->GetAmount(); + else + amount = 0; + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_hun_animal_handler_AuraScript::CalculateAmountDamageDone, EFFECT_0, SPELL_AURA_MOD_ATTACK_POWER_PCT); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_hun_animal_handler_AuraScript(); + } +}; + + +class spell_dk_avoidance_passive : public SpellScriptLoader +{ +public: + spell_dk_avoidance_passive() : SpellScriptLoader("spell_dk_avoidance_passive") { } + + class spell_dk_avoidance_passive_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_avoidance_passive_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAvoidanceAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (Unit* owner = pet->GetOwner()) + { + // Army of the dead ghoul + if (pet->GetEntry() == ENTRY_ARMY_OF_THE_DEAD_GHOUL) + amount = -90; + // Night of the dead + else if ( Aura * aur = owner->GetAuraOfRankedSpell(SPELL_NIGHT_OF_THE_DEAD)) + amount = aur->GetSpellInfo()->Effects[EFFECT_2].CalcValue(); + } + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_avoidance_passive_AuraScript::CalculateAvoidanceAmount, EFFECT_0, SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_avoidance_passive_AuraScript(); + } +}; + +class spell_dk_pet_scaling_01 : public SpellScriptLoader +{ +public: + spell_dk_pet_scaling_01() : SpellScriptLoader("spell_dk_pet_scaling_01") { } + + class spell_dk_pet_scaling_01_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_pet_scaling_01_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + _tempHealth = 0; + return true; + } + + void CalculateStaminaAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (pet->isGuardian()) + { + if (Unit* owner = pet->GetOwner()) + { + float mod = 0.3f; + + // Ravenous Dead. Check just if owner has Ravenous Dead since it's effect is not an aura + if (AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0)) + { + mod += aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()/100; // Ravenous Dead edits the original scale + } + // Glyph of the Ghoul + if (AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_DEATH_KNIGHT_GLYPH_OF_GHOUL, 0)) + mod += aurEff->GetAmount()/100; + + float ownerBonus = float(owner->GetStat(STAT_STAMINA)) * mod; + amount += ownerBonus; + } + } + } + } + + void ApplyEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + if (_tempHealth) + pet->SetHealth(_tempHealth); + } + + void RemoveEffect(AuraEffect const* /* aurEff */, AuraEffectHandleModes /*mode*/) + { + if (Unit* pet = GetUnitOwner()) + _tempHealth = pet->GetHealth(); + } + + void CalculateStrengthAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + if (!pet->isGuardian()) + return; + + Unit* owner = pet->GetOwner(); + if (!owner) + return; + + float mod = 0.7f; + + // Ravenous Dead + AuraEffect const* aurEff = NULL; + // Check just if owner has Ravenous Dead since it's effect is not an aura + aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); + if (aurEff) + { + mod += CalculatePctN(mod, aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale + } + // Glyph of the Ghoul + aurEff = owner->GetAuraEffect(58686, 0); + if (aurEff) + mod += CalculatePctN(1.0f, aurEff->GetAmount()); // Glyph of the Ghoul adds a flat value to the scale mod + float ownerBonus = float(owner->GetStat(STAT_STRENGTH)) * mod; + amount += ownerBonus; + } + } + + void Register() + { + OnEffectRemove += AuraEffectRemoveFn(spell_dk_pet_scaling_01_AuraScript::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + AfterEffectApply += AuraEffectApplyFn(spell_dk_pet_scaling_01_AuraScript::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_STAT, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_01_AuraScript::CalculateStaminaAmount, EFFECT_0, SPELL_AURA_MOD_STAT); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_01_AuraScript::CalculateStrengthAmount, EFFECT_1, SPELL_AURA_MOD_STAT); + } + + private: + uint32 _tempHealth; + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_pet_scaling_01_AuraScript(); + } +}; + +class spell_dk_pet_scaling_02 : public SpellScriptLoader +{ +public: + spell_dk_pet_scaling_02() : SpellScriptLoader("spell_dk_pet_scaling_02") { } + + class spell_dk_pet_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_pet_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHaste(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HasteMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HasteMelee += (1-owner->m_modAttackSpeedPct[BASE_ATTACK])*100; + + amount += int32(HasteMelee); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_02_AuraScript::CalculateAmountMeleeHaste, EFFECT_1, SPELL_AURA_MELEE_SLOW); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_pet_scaling_02_AuraScript(); + } +}; + +class spell_dk_pet_scaling_03 : public SpellScriptLoader +{ +public: + spell_dk_pet_scaling_03() : SpellScriptLoader("spell_dk_pet_scaling_03") { } + + class spell_dk_pet_scaling_03_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_pet_scaling_03_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateAmountMeleeHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HitMelee += owner->GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + // Increase hit melee from meele hit ratings + HitMelee += owner->GetRatingBonusValue(CR_HIT_MELEE); + + amount += int32(HitMelee); + } + } + + void CalculateAmountSpellHit(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HitSpell = 0.0f; + // Increase hit from SPELL_AURA_MOD_SPELL_HIT_CHANCE + HitSpell += owner->GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + // Increase hit spell from spell hit ratings + HitSpell += owner->GetRatingBonusValue(CR_HIT_SPELL); + + amount += int32(HitSpell); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_03_AuraScript::CalculateAmountMeleeHit, EFFECT_0, SPELL_AURA_MOD_HIT_CHANCE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_pet_scaling_03_AuraScript::CalculateAmountSpellHit, EFFECT_1, SPELL_AURA_MOD_SPELL_HIT_CHANCE); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_pet_scaling_03_AuraScript(); + } +}; + +class spell_dk_rune_weapon_scaling_02 : public SpellScriptLoader +{ +public: + spell_dk_rune_weapon_scaling_02() : SpellScriptLoader("spell_dk_rune_weapon_scaling_02") { } + + class spell_dk_rune_weapon_scaling_02_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_rune_weapon_scaling_02_AuraScript); + + bool Load() + { + if (!GetCaster() || !GetCaster()->GetOwner() || GetCaster()->GetOwner()->GetTypeId() != TYPEID_PLAYER) + return false; + return true; + } + + void CalculateDamageDoneAmount(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (Unit* pet = GetUnitOwner()) + { + Unit* owner = pet->GetOwner(); + if (!owner) + return; + + if (pet->isGuardian()) + ((Guardian*)pet)->SetBonusDamage(owner->GetTotalAttackPowerValue(BASE_ATTACK)); + + amount += owner->CalculateDamage(BASE_ATTACK, true, true);; + } + } + + void CalculateAmountMeleeHaste(AuraEffect const* /* aurEff */, int32& amount, bool& /*canBeRecalculated*/) + { + if (!GetCaster() || !GetCaster()->GetOwner()) + return; + if (Player* owner = GetCaster()->GetOwner()->ToPlayer()) + { + // For others recalculate it from: + float HasteMelee = 0.0f; + // Increase hit from SPELL_AURA_MOD_HIT_CHANCE + HasteMelee += (1-owner->m_modAttackSpeedPct[BASE_ATTACK])*100; + + amount += int32(HasteMelee); + } + } + + void Register() + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_rune_weapon_scaling_02_AuraScript::CalculateDamageDoneAmount, EFFECT_0, SPELL_AURA_MOD_DAMAGE_DONE); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_rune_weapon_scaling_02_AuraScript::CalculateAmountMeleeHaste, EFFECT_1, SPELL_AURA_MELEE_SLOW); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_dk_rune_weapon_scaling_02_AuraScript(); + } +}; + +void AddSC_pet_spell_scripts() +{ + new spell_gen_pet_calculate(); +} diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 8088004c9d1..aab1e974e53 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -34,6 +34,9 @@ enum PriestSpells PRIEST_SPELL_PENANCE_R1_HEAL = 47757, PRIEST_SPELL_REFLECTIVE_SHIELD_TRIGGERED = 33619, PRIEST_SPELL_REFLECTIVE_SHIELD_R1 = 33201, + PRIEST_SPELL_VAMPIRIC_TOUCH_DISPEL = 64085, + PRIEST_SPELL_EMPOWERED_RENEW = 63544, + PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT = 3021, }; // Guardian Spirit @@ -129,14 +132,14 @@ class spell_pri_mind_sear : public SpellScriptLoader { PrepareSpellScript(spell_pri_mind_sear_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (Trinity::ObjectGUIDCheck(GetCaster()->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT))); + unitList.remove_if(Trinity::ObjectGUIDCheck(GetCaster()->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT))); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_pri_mind_sear_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pri_mind_sear_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; @@ -330,6 +333,88 @@ public: } }; +class spell_pri_vampiric_touch : public SpellScriptLoader +{ + public: + spell_pri_vampiric_touch() : SpellScriptLoader("spell_pri_vampiric_touch") { } + + class spell_pri_vampiric_touch_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_vampiric_touch_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(PRIEST_SPELL_VAMPIRIC_TOUCH_DISPEL)) + return false; + return true; + } + + void HandleDispel(DispelInfo* /*dispelInfo*/) + { + if (Unit* caster = GetCaster()) + if (Unit* target = GetUnitOwner()) + if (AuraEffect const* aurEff = GetEffect(EFFECT_1)) + { + int32 damage = aurEff->GetAmount() * 8; + // backfire damage + caster->CastCustomSpell(target, PRIEST_SPELL_VAMPIRIC_TOUCH_DISPEL, &damage, NULL, NULL, true, NULL, aurEff); + } + } + + void Register() + { + AfterDispel += AuraDispelFn(spell_pri_vampiric_touch_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_pri_vampiric_touch_AuraScript(); + } +}; + +class spell_priest_renew : public SpellScriptLoader +{ + public: + spell_priest_renew() : SpellScriptLoader("spell_priest_renew") { } + + class spell_priest_renew_AuraScript : public AuraScript + { + PrepareAuraScript(spell_priest_renew_AuraScript); + + bool Load() + { + return GetCaster() && GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleApplyEffect(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + { + // Empowered Renew + if (AuraEffect const* empoweredRenewAurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, PRIEST_ICON_ID_EMPOWERED_RENEW_TALENT, EFFECT_1)) + { + uint32 heal = caster->SpellHealingBonusDone(GetTarget(), GetSpellInfo(), GetEffect(EFFECT_0)->GetAmount(), DOT); + heal = GetTarget()->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT); + + int32 basepoints0 = empoweredRenewAurEff->GetAmount() * GetEffect(EFFECT_0)->GetTotalTicks() * int32(heal) / 100; + caster->CastCustomSpell(GetTarget(), PRIEST_SPELL_EMPOWERED_RENEW, &basepoints0, NULL, NULL, true, NULL, aurEff); + } + } + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_priest_renew_AuraScript::HandleApplyEffect, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_priest_renew_AuraScript(); + } +}; + void AddSC_priest_spell_scripts() { new spell_pri_guardian_spirit(); @@ -339,4 +424,6 @@ void AddSC_priest_spell_scripts() new spell_pri_reflective_shield_trigger(); new spell_pri_mind_sear(); new spell_pri_prayer_of_mending_heal(); + new spell_pri_vampiric_touch(); + new spell_priest_renew(); } diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 810cc20e04b..e3714a22304 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -639,7 +639,7 @@ class spell_q12851_going_bearback : public SpellScriptLoader // Already in fire if (target->HasAura(SPELL_ABLAZE)) return; - + if (Player* player = caster->GetCharmerOrOwnerPlayerOrPlayerItself()) { switch (target->GetEntry()) @@ -1162,6 +1162,84 @@ class spell_q12277_wintergarde_mine_explosion : public SpellScriptLoader } }; +enum FocusOnTheBeach +{ + SPELL_BUNNY_CREDIT_BEAM = 47390, +}; + +class spell_q12066_bunny_kill_credit : public SpellScriptLoader +{ +public: + spell_q12066_bunny_kill_credit() : SpellScriptLoader("spell_q12066_bunny_kill_credit") { } + + class spell_q12066_bunny_kill_credit_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12066_bunny_kill_credit_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Creature* target = GetHitCreature()) + target->CastSpell(GetCaster(), SPELL_BUNNY_CREDIT_BEAM, false); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12066_bunny_kill_credit_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12066_bunny_kill_credit_SpellScript(); + } +}; + +enum ACleansingSong +{ + SPELL_SUMMON_SPIRIT_ATAH = 52954, + SPELL_SUMMON_SPIRIT_HAKHALAN = 52958, + SPELL_SUMMON_SPIRIT_KOOSU = 52959, + + AREA_BITTERTIDELAKE = 4385, + AREA_RIVERSHEART = 4290, + AREA_WINTERGRASPRIVER = 4388, +}; + +class spell_q12735_song_of_cleansing : public SpellScriptLoader +{ + public: + spell_q12735_song_of_cleansing() : SpellScriptLoader("spell_q12735_song_of_cleansing") { } + + class spell_q12735_song_of_cleansing_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12735_song_of_cleansing_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + + if (caster && caster->GetAreaId() == AREA_BITTERTIDELAKE) + caster->CastSpell(caster, SPELL_SUMMON_SPIRIT_ATAH); + + else if (caster && caster->GetAreaId() == AREA_RIVERSHEART) + caster->CastSpell(caster, SPELL_SUMMON_SPIRIT_HAKHALAN); + + else if (caster && caster->GetAreaId() == AREA_WINTERGRASPRIVER) + caster->CastSpell(caster, SPELL_SUMMON_SPIRIT_KOOSU); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q12735_song_of_cleansing_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q12735_song_of_cleansing_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -1189,4 +1267,6 @@ void AddSC_quest_spell_scripts() new spell_q9452_cast_net(); new spell_q12987_read_pronouncement(); new spell_q12277_wintergarde_mine_explosion(); + new spell_q12066_bunny_kill_credit(); + new spell_q12735_song_of_cleansing(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index c9c036d5329..c863c2363af 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -35,13 +35,19 @@ enum ShamanSpells SHAMAN_SPELL_FIRE_NOVA_TRIGGERED_R1 = 8349, SHAMAN_SPELL_SATED = 57724, SHAMAN_SPELL_EXHAUSTION = 57723, - + SHAMAN_SPELL_STORM_EARTH_AND_FIRE = 51483, EARTHBIND_TOTEM_SPELL_EARTHGRAB = 64695, // For Earthen Power SHAMAN_TOTEM_SPELL_EARTHBIND_TOTEM = 6474, SHAMAN_TOTEM_SPELL_EARTHEN_POWER = 59566, + + SHAMAN_BIND_SIGHT = 6277, + + ICON_ID_SHAMAN_LAVA_FLOW = 3087, + SHAMAN_LAVA_FLOWS_R1 = 51480, + SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 64694, }; // 51474 - Astral shift @@ -255,10 +261,13 @@ class EarthenPowerTargetSelector { public: EarthenPowerTargetSelector() { } - - bool operator() (Unit* target) + + bool operator() (WorldObject* target) { - if (!target->HasAuraWithMechanic(1 << MECHANIC_SNARE)) + if (!target->ToUnit()) + return true; + + if (!target->ToUnit()->HasAuraWithMechanic(1 << MECHANIC_SNARE)) return true; return false; @@ -274,14 +283,14 @@ class spell_sha_earthen_power : public SpellScriptLoader { PrepareSpellScript(spell_sha_earthen_power_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { unitList.remove_if(EarthenPowerTargetSelector()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_earthen_power_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_earthen_power_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; @@ -307,7 +316,7 @@ class spell_sha_bloodlust : public SpellScriptLoader return true; } - void RemoveInvalidTargets(std::list<Unit*>& targets) + void RemoveInvalidTargets(std::list<WorldObject*>& targets) { targets.remove_if(Trinity::UnitAuraCheck(true, SHAMAN_SPELL_SATED)); } @@ -320,9 +329,9 @@ class spell_sha_bloodlust : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_bloodlust_SpellScript::RemoveInvalidTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID); - OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_bloodlust_SpellScript::RemoveInvalidTargets, EFFECT_1, TARGET_UNIT_CASTER_AREA_RAID); - OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_bloodlust_SpellScript::RemoveInvalidTargets, EFFECT_2, TARGET_UNIT_CASTER_AREA_RAID); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_bloodlust_SpellScript::RemoveInvalidTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_bloodlust_SpellScript::RemoveInvalidTargets, EFFECT_1, TARGET_UNIT_CASTER_AREA_RAID); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_bloodlust_SpellScript::RemoveInvalidTargets, EFFECT_2, TARGET_UNIT_CASTER_AREA_RAID); AfterHit += SpellHitFn(spell_sha_bloodlust_SpellScript::ApplyDebuff); } }; @@ -349,9 +358,9 @@ class spell_sha_heroism : public SpellScriptLoader return true; } - void RemoveInvalidTargets(std::list<Unit*>& targets) + void RemoveInvalidTargets(std::list<WorldObject*>& targets) { - targets.remove_if (Trinity::UnitAuraCheck(true, SHAMAN_SPELL_EXHAUSTION)); + targets.remove_if(Trinity::UnitAuraCheck(true, SHAMAN_SPELL_EXHAUSTION)); } void ApplyDebuff() @@ -362,9 +371,9 @@ class spell_sha_heroism : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID); - OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_1, TARGET_UNIT_CASTER_AREA_RAID); - OnUnitTargetSelect += SpellUnitTargetFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_2, TARGET_UNIT_CASTER_AREA_RAID); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_RAID); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_1, TARGET_UNIT_CASTER_AREA_RAID); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sha_heroism_SpellScript::RemoveInvalidTargets, EFFECT_2, TARGET_UNIT_CASTER_AREA_RAID); AfterHit += SpellHitFn(spell_sha_heroism_SpellScript::ApplyDebuff); } }; @@ -652,6 +661,94 @@ class spell_sha_chain_heal : public SpellScriptLoader } }; +class spell_sha_flame_shock : public SpellScriptLoader +{ + public: + spell_sha_flame_shock() : SpellScriptLoader("spell_sha_flame_shock") { } + + class spell_sha_flame_shock_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_flame_shock_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SHAMAN_LAVA_FLOWS_R1)) + return false; + if (!sSpellMgr->GetSpellInfo(SHAMAN_LAVA_FLOWS_TRIGGERED_R1)) + return false; + return true; + } + + void HandleDispel(DispelInfo* /*dispelInfo*/) + { + if (Unit* caster = GetCaster()) + // Lava Flows + if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, ICON_ID_SHAMAN_LAVA_FLOW, EFFECT_0)) + { + if (sSpellMgr->GetFirstSpellInChain(SHAMAN_LAVA_FLOWS_R1) != sSpellMgr->GetFirstSpellInChain(aurEff->GetId())) + return; + + uint8 rank = sSpellMgr->GetSpellRank(aurEff->GetId()); + caster->CastSpell(caster, sSpellMgr->GetSpellWithRank(SHAMAN_LAVA_FLOWS_TRIGGERED_R1, rank), true); + } + } + + void Register() + { + AfterDispel += AuraDispelFn(spell_sha_flame_shock_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_sha_flame_shock_AuraScript(); + } +}; + +class spell_sha_sentry_totem : public SpellScriptLoader +{ + public: + spell_sha_sentry_totem() : SpellScriptLoader("spell_sha_sentry_totem") { } + + class spell_sha_sentry_totem_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_sentry_totem_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SHAMAN_BIND_SIGHT)) + return false; + return true; + } + + void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (Creature* totem = caster->GetMap()->GetCreature(caster->m_SummonSlot[4])) + if (totem->isTotem()) + caster->CastSpell(totem, SHAMAN_BIND_SIGHT, true); + } + + void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (caster->GetTypeId() == TYPEID_PLAYER) + caster->ToPlayer()->StopCastingBindSight(); + } + + void Register() + { + AfterEffectApply += AuraEffectApplyFn(spell_sha_sentry_totem_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_sha_sentry_totem_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_sha_sentry_totem_AuraScript(); + } +}; + void AddSC_shaman_spell_scripts() { new spell_sha_astral_shift(); @@ -667,4 +764,6 @@ void AddSC_shaman_spell_scripts() new spell_sha_mana_spring_totem(); new spell_sha_lava_lash(); new spell_sha_chain_heal(); + new spell_sha_flame_shock(); + new spell_sha_sentry_totem(); } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 838b9e4f932..74118599b9f 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -37,6 +37,9 @@ enum WarlockSpells WARLOCK_DEMONIC_CIRCLE_SUMMON = 48018, WARLOCK_DEMONIC_CIRCLE_TELEPORT = 48020, WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST = 62388, + WARLOCK_HAUNT = 48181, + WARLOCK_HAUNT_HEAL = 48210, + WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117, }; class spell_warl_banish : public SpellScriptLoader @@ -299,15 +302,15 @@ class spell_warl_seed_of_corruption : public SpellScriptLoader { PrepareSpellScript(spell_warl_seed_of_corruption_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { if (GetExplTargetUnit()) - unitList.remove(GetExplTargetUnit()); + targets.remove(GetExplTargetUnit()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_warl_seed_of_corruption_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warl_seed_of_corruption_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; @@ -523,6 +526,107 @@ class spell_warl_demonic_circle_teleport : public SpellScriptLoader } }; +class spell_warl_haunt : public SpellScriptLoader +{ + public: + spell_warl_haunt() : SpellScriptLoader("spell_warl_haunt") { } + + class spell_warl_haunt_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warl_haunt_SpellScript); + + void HandleOnHit() + { + if (Aura* aura = GetHitAura()) + if (AuraEffect* aurEff = aura->GetEffect(EFFECT_1)) + aurEff->SetAmount(CalculatePctN(aurEff->GetAmount(), GetHitDamage())); + } + + void Register() + { + OnHit += SpellHitFn(spell_warl_haunt_SpellScript::HandleOnHit); + } + }; + + class spell_warl_haunt_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_haunt_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(WARLOCK_HAUNT_HEAL)) + return false; + return true; + } + + void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL && GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) + return; + + if (Unit* caster = GetCaster()) + { + int32 amount = aurEff->GetAmount(); + GetTarget()->CastCustomSpell(caster, WARLOCK_HAUNT_HEAL, &amount, NULL, NULL, true, NULL, aurEff, GetCasterGUID()); + } + } + + void Register() + { + OnEffectRemove += AuraEffectApplyFn(spell_warl_haunt_AuraScript::HandleRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warl_haunt_SpellScript(); + } + + AuraScript* GetAuraScript() const + { + return new spell_warl_haunt_AuraScript(); + } +}; + +class spell_warl_unstable_affliction : public SpellScriptLoader +{ + public: + spell_warl_unstable_affliction() : SpellScriptLoader("spell_warl_unstable_affliction") { } + + class spell_warl_unstable_affliction_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_unstable_affliction_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(WARLOCK_UNSTABLE_AFFLICTION_DISPEL)) + return false; + return true; + } + + void HandleDispel(DispelInfo* dispelInfo) + { + if (Unit* caster = GetCaster()) + if (AuraEffect const* aurEff = GetEffect(EFFECT_0)) + { + int32 damage = aurEff->GetAmount() * 9; + // backfire damage and silence + caster->CastCustomSpell(dispelInfo->GetDispeller(), WARLOCK_UNSTABLE_AFFLICTION_DISPEL, &damage, NULL, NULL, true, NULL, aurEff); + } + } + + void Register() + { + AfterDispel += AuraDispelFn(spell_warl_unstable_affliction_AuraScript::HandleDispel); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_warl_unstable_affliction_AuraScript(); + } +}; + void AddSC_warlock_spell_scripts() { new spell_warl_banish(); @@ -535,4 +639,6 @@ void AddSC_warlock_spell_scripts() new spell_warl_life_tap(); new spell_warl_demonic_circle_summon(); new spell_warl_demonic_circle_teleport(); + new spell_warl_haunt(); + new spell_warl_unstable_affliction(); } diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 0ba5c866d63..c64101e11ea 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -77,7 +77,7 @@ class spell_warr_improved_spell_reflection : public SpellScriptLoader { PrepareSpellScript(spell_warr_improved_spell_reflection_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { if (GetCaster()) unitList.remove(GetCaster()); @@ -85,7 +85,7 @@ class spell_warr_improved_spell_reflection : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_warr_improved_spell_reflection_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_warr_improved_spell_reflection_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER_AREA_PARTY); } }; @@ -184,9 +184,9 @@ class spell_warr_deep_wounds : public SpellScriptLoader damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE); ApplyPctN(damage, 16 * sSpellMgr->GetSpellRank(GetSpellInfo()->Id)); - + damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE); - + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_DEEP_WOUNDS_RANK_PERIODIC); uint32 ticks = spellInfo->GetDuration() / spellInfo->Effects[EFFECT_0].Amplitude; @@ -397,7 +397,20 @@ class spell_warr_bloodthirst : public SpellScriptLoader { PrepareSpellScript(spell_warr_bloodthirst_SpellScript); - void HandleDummy(SpellEffIndex /* effIndex */) + void HandleDamage(SpellEffIndex /*effIndex*/) + { + int32 damage = GetEffectValue(); + ApplyPctF(damage, GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK)); + + if (Unit* target = GetHitUnit()) + { + damage = GetCaster()->SpellDamageBonusDone(target, GetSpellInfo(), uint32(damage), SPELL_DIRECT_DAMAGE); + damage = target->SpellDamageBonusTaken(GetCaster(), GetSpellInfo(), uint32(damage), SPELL_DIRECT_DAMAGE); + } + SetHitDamage(damage); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) { int32 damage = GetEffectValue(); GetCaster()->CastCustomSpell(GetCaster(), SPELL_BLOODTHIRST, &damage, NULL, NULL, true, NULL); @@ -405,7 +418,8 @@ class spell_warr_bloodthirst : public SpellScriptLoader void Register() { - OnEffectHitTarget += SpellEffectFn(spell_warr_bloodthirst_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); + OnEffectHitTarget += SpellEffectFn(spell_warr_bloodthirst_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + OnEffectHit += SpellEffectFn(spell_warr_bloodthirst_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_DUMMY); } }; @@ -415,6 +429,38 @@ class spell_warr_bloodthirst : public SpellScriptLoader } }; +enum BloodthirstHeal +{ + SPELL_BLOODTHIRST_DAMAGE = 23881, +}; + +class spell_warr_bloodthirst_heal : public SpellScriptLoader +{ + public: + spell_warr_bloodthirst_heal() : SpellScriptLoader("spell_warr_bloodthirst_heal") { } + + class spell_warr_bloodthirst_heal_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warr_bloodthirst_heal_SpellScript); + + void HandleHeal(SpellEffIndex /*effIndex*/) + { + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_BLOODTHIRST_DAMAGE)) + SetHitHeal(GetCaster()->CountPctFromMaxHealth(spellInfo->Effects[EFFECT_1].CalcValue(GetCaster()))); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_warr_bloodthirst_heal_SpellScript::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_warr_bloodthirst_heal_SpellScript(); + } +}; + enum Overpower { SPELL_UNRELENTING_ASSAULT_RANK_1 = 46859, @@ -471,5 +517,6 @@ void AddSC_warrior_spell_scripts() new spell_warr_execute(); new spell_warr_concussion_blow(); new spell_warr_bloodthirst(); + new spell_warr_bloodthirst_heal(); new spell_warr_overpower(); } diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index 9bcf450b3aa..3dc737f0c95 100755 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -313,6 +313,27 @@ class achievement_tilted : public AchievementCriteriaScript } }; +class achievement_not_even_a_scratch : public AchievementCriteriaScript +{ + public: + achievement_not_even_a_scratch() : AchievementCriteriaScript("achievement_not_even_a_scratch") { } + + bool OnCheck(Player* source, Unit* /*target*/) + { + if (!source) + return false; + + Battleground* battleground = source->GetBattleground(); + if (!battleground) + return false; + + if (static_cast<BattlegroundSA*>(battleground)->notEvenAScratch(source->GetTeam())) + return true; + + return false; + } +}; + void AddSC_achievement_scripts() { new achievement_resilient_victory(); @@ -331,4 +352,5 @@ void AddSC_achievement_scripts() new achievement_arena_kills("achievement_arena_5v5_kills", ARENA_TYPE_5v5); new achievement_bg_sa_defense_of_ancients(); new achievement_tilted(); + new achievement_not_even_a_scratch(); } diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp index 045dea9c9a9..abb20130ef8 100644 --- a/src/server/scripts/World/boss_emerald_dragons.cpp +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -224,9 +224,9 @@ class DreamFogTargetSelector public: DreamFogTargetSelector() { } - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - return unit->HasAura(SPELL_SLEEP); + return object->ToUnit() && object->ToUnit()->HasAura(SPELL_SLEEP); } }; @@ -239,14 +239,14 @@ class spell_dream_fog_sleep : public SpellScriptLoader { PrepareSpellScript(spell_dream_fog_sleep_SpellScript); - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& unitList) { - unitList.remove_if (DreamFogTargetSelector()); + unitList.remove_if(DreamFogTargetSelector()); } void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_dream_fog_sleep_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dream_fog_sleep_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); } }; @@ -265,10 +265,12 @@ class MarkOfNatureTargetSelector public: MarkOfNatureTargetSelector() { } - bool operator()(Unit* unit) + bool operator()(WorldObject* object) const { - // return anyone that isn't tagged or already under the influence of Aura of Nature - return !(unit->HasAura(SPELL_MARK_OF_NATURE) && !unit->HasAura(SPELL_AURA_OF_NATURE)); + if (Unit* unit = object->ToUnit()) + // return anyone that isn't tagged or already under the influence of Aura of Nature + return !(unit->HasAura(SPELL_MARK_OF_NATURE) && !unit->HasAura(SPELL_AURA_OF_NATURE)); + return true; } }; @@ -290,9 +292,9 @@ class spell_mark_of_nature : public SpellScriptLoader return true; } - void FilterTargets(std::list<Unit*>& unitList) + void FilterTargets(std::list<WorldObject*>& targets) { - unitList.remove_if (MarkOfNatureTargetSelector()); + targets.remove_if(MarkOfNatureTargetSelector()); } void HandleEffect(SpellEffIndex effIndex) @@ -305,7 +307,7 @@ class spell_mark_of_nature : public SpellScriptLoader void Register() { - OnUnitTargetSelect += SpellUnitTargetFn(spell_mark_of_nature_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_nature_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_mark_of_nature_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA); } }; diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index 790a9d0f814..21a852ae9ed 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -1245,6 +1245,58 @@ class go_veil_skith_cage : public GameObjectScript } }; +/*###### +## go_frostblade_shrine +######*/ + +enum TheCleansing +{ + QUEST_THE_CLEANSING_HORDE = 11317, + QUEST_THE_CLEANSING_ALLIANCE = 11322, + SPELL_CLEANSING_SOUL = 43351, + SPELL_RECENT_MEDITATION = 61720, +}; + +class go_frostblade_shrine : public GameObjectScript +{ +public: + go_frostblade_shrine() : GameObjectScript("go_frostblade_shrine") { } + + bool OnGossipHello(Player* player, GameObject* go) + { + if (!player->HasAura(SPELL_RECENT_MEDITATION)) + if (player->GetQuestStatus(QUEST_THE_CLEANSING_HORDE) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_THE_CLEANSING_ALLIANCE) == QUEST_STATUS_INCOMPLETE) + { + go->UseDoorOrButton(10); + player->CastSpell(player, SPELL_CLEANSING_SOUL); + player->SetStandState(UNIT_STAND_STATE_SIT); + } + return true; + } +}; + +/*###### +## go_midsummer_bonfire +######*/ + +enum eMidsummerBonfire +{ + STAMP_OUT_BONFIRE_QUEST_COMPLETE = 45458, +}; + +class go_midsummer_bonfire : public GameObjectScript +{ +public: + go_midsummer_bonfire() : GameObjectScript("go_midsummer_bonfire") { } + + bool OnGossipSelect(Player* player, GameObject* /*go*/, uint32 /*sender*/, uint32 /*action*/) + { + player->CastSpell(player, STAMP_OUT_BONFIRE_QUEST_COMPLETE, true); + player->CLOSE_GOSSIP_MENU(); + return false; + } +}; + void AddSC_go_scripts() { new go_cat_figurine; @@ -1285,4 +1337,6 @@ void AddSC_go_scripts() new go_gjalerbron_cage; new go_large_gjalerbron_cage; new go_veil_skith_cage; + new go_frostblade_shrine; + new go_midsummer_bonfire; } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index ecd1a439a58..57a65423b6f 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -47,6 +47,7 @@ EndContentData */ #include "ObjectMgr.h" #include "ScriptMgr.h" #include "World.h" +#include "PetAI.h" /*######## # npc_air_force_bots @@ -2100,16 +2101,18 @@ class npc_shadowfiend : public CreatureScript public: npc_shadowfiend() : CreatureScript("npc_shadowfiend") { } - struct npc_shadowfiendAI : public ScriptedAI + struct npc_shadowfiendAI : public PetAI { - npc_shadowfiendAI(Creature* creature) : ScriptedAI(creature) {} + npc_shadowfiendAI(Creature* creature) : PetAI(creature) {} - void DamageTaken(Unit* /*killer*/, uint32& damage) + void JustDied(Unit* killer) { if (me->isSummon()) if (Unit* owner = me->ToTempSummon()->GetSummoner()) - if (owner->HasAura(GLYPH_OF_SHADOWFIEND) && damage >= me->GetHealth()) + if (owner->HasAura(GLYPH_OF_SHADOWFIEND)) owner->CastSpell(owner, GLYPH_OF_SHADOWFIEND_MANA, true); + + PetAI::JustDied(killer); } }; @@ -2988,6 +2991,31 @@ public: }; }; +/*###### +## npc_generic_harpoon_cannon +######*/ + +class npc_generic_harpoon_cannon : public CreatureScript +{ +public: + npc_generic_harpoon_cannon() : CreatureScript("npc_generic_harpoon_cannon") { } + + struct npc_generic_harpoon_cannonAI : public ScriptedAI + { + npc_generic_harpoon_cannonAI(Creature* creature) : ScriptedAI(creature) {} + + void Reset() + { + me->SetUnitMovementFlags(MOVEMENTFLAG_ROOT); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_generic_harpoon_cannonAI(creature); + } +}; + void AddSC_npcs_special() { new npc_air_force_bots(); @@ -3020,4 +3048,5 @@ void AddSC_npcs_special() new npc_earth_elemental(); new npc_firework(); new npc_spring_rabbit(); + new npc_generic_harpoon_cannon(); } diff --git a/src/server/shared/Cryptography/WardenKeyGeneration.h b/src/server/shared/Cryptography/WardenKeyGeneration.h index 9b44ab1832e..f0a9905b6fe 100644 --- a/src/server/shared/Cryptography/WardenKeyGeneration.h +++ b/src/server/shared/Cryptography/WardenKeyGeneration.h @@ -21,50 +21,56 @@ #ifndef _WARDEN_KEY_GENERATION_H #define _WARDEN_KEY_GENERATION_H -class SHA1Randx { +class SHA1Randx +{ public: - SHA1Randx(uint8 *buff, uint32 size) { + SHA1Randx(uint8* buff, uint32 size) + { uint32 taken = size/2; sh.Initialize(); - sh.UpdateData(buff,taken); + sh.UpdateData(buff, taken); sh.Finalize(); - memcpy(o1,sh.GetDigest(),20); + memcpy(o1, sh.GetDigest(), 20); sh.Initialize(); - sh.UpdateData(buff+taken,size-taken); + sh.UpdateData(buff + taken, size - taken); sh.Finalize(); - memcpy(o2,sh.GetDigest(),20); + memcpy(o2, sh.GetDigest(), 20); - memset(o0,0x00,20); + memset(o0, 0x00, 20); - fillUp(); + FillUp(); } - void generate(uint8 *buf, uint32 sz) { - for(uint32 i=0;i<sz;i++) { - if(taken == 20) { - fillUp(); - } + void Generate(uint8* buf, uint32 sz) + { + for (uint32 i = 0; i < sz; ++i) + { + if (taken == 20) + FillUp(); buf[i] = o0[taken]; taken++; } } + private: - void fillUp() { + void FillUp() + { sh.Initialize(); - sh.UpdateData(o1,20); - sh.UpdateData(o0,20); - sh.UpdateData(o2,20); + sh.UpdateData(o1, 20); + sh.UpdateData(o0, 20); + sh.UpdateData(o2, 20); sh.Finalize(); - memcpy(o0,sh.GetDigest(),20); + memcpy(o0, sh.GetDigest(), 20); taken = 0; } + SHA1Hash sh; uint32 taken; uint8 o0[20],o1[20],o2[20]; diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index ea9165f86ec..27bf92ad846 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -317,18 +317,17 @@ void CharacterDatabaseConnection::DoPrepareStatements() PREPARE_STATEMENT(CHAR_DEL_OLD_CORPSES, "DELETE FROM corpse WHERE corpseType = 0 OR time < (UNIX_TIMESTAMP(NOW()) - ?)", CONNECTION_ASYNC) // Creature respawn - PREPARE_STATEMENT(CHAR_SEL_CREATURE_RESPAWNS, "SELECT guid, respawnTime, instanceId FROM creature_respawn", CONNECTION_SYNCH) - PREPARE_STATEMENT(CHAR_REP_CREATURE_RESPAWN, "REPLACE INTO creature_respawn (guid, respawnTime, instanceId) VALUES (?, ?, ?)", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN, "DELETE FROM creature_respawn WHERE guid = ? AND instanceId = ?", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN_BY_GUID, "DELETE FROM creature_respawn WHERE guid = ?", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE, "DELETE FROM creature_respawn WHERE instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_SEL_CREATURE_RESPAWNS, "SELECT guid, respawnTime FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH) + PREPARE_STATEMENT(CHAR_REP_CREATURE_RESPAWN, "REPLACE INTO creature_respawn (guid, respawnTime, mapId, instanceId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN, "DELETE FROM creature_respawn WHERE guid = ? AND mapId = ? AND instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE, "DELETE FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC) PREPARE_STATEMENT(CHAR_SEL_MAX_CREATURE_RESPAWNS, "SELECT MAX(respawnTime), instanceId FROM creature_respawn WHERE instanceId > 0 GROUP BY instanceId", CONNECTION_SYNCH) // Gameobject respawn - PREPARE_STATEMENT(CHAR_SEL_GO_RESPAWNS, "SELECT guid, respawnTime, instanceId FROM gameobject_respawn", CONNECTION_SYNCH) - PREPARE_STATEMENT(CHAR_REP_GO_RESPAWN, "REPLACE INTO gameobject_respawn (guid, respawnTime, instanceId) VALUES (?, ?, ?)", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN, "DELETE FROM gameobject_respawn WHERE guid = ? AND instanceId = ?", CONNECTION_ASYNC) - PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_SEL_GO_RESPAWNS, "SELECT guid, respawnTime FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH) + PREPARE_STATEMENT(CHAR_REP_GO_RESPAWN, "REPLACE INTO gameobject_respawn (guid, respawnTime, mapId, instanceId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN, "DELETE FROM gameobject_respawn WHERE guid = ? AND mapId = ? AND instanceId = ?", CONNECTION_ASYNC) + PREPARE_STATEMENT(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC) // GM Tickets PREPARE_STATEMENT(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed FROM gm_tickets", CONNECTION_SYNCH) diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 51ab97fe021..08265c455d6 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -298,7 +298,6 @@ enum CharacterDatabaseStatements CHAR_SEL_CREATURE_RESPAWNS, CHAR_REP_CREATURE_RESPAWN, CHAR_DEL_CREATURE_RESPAWN, - CHAR_DEL_CREATURE_RESPAWN_BY_GUID, CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE, CHAR_SEL_MAX_CREATURE_RESPAWNS, diff --git a/src/server/shared/Database/PreparedStatement.cpp b/src/server/shared/Database/PreparedStatement.cpp index db26dabaee7..58aa2bd3aa0 100755 --- a/src/server/shared/Database/PreparedStatement.cpp +++ b/src/server/shared/Database/PreparedStatement.cpp @@ -209,7 +209,7 @@ m_bind(NULL) MySQLPreparedStatement::~MySQLPreparedStatement() { ClearParameters(); - if(m_Mstmt->bind_result_done) + if (m_Mstmt->bind_result_done) { delete[] m_Mstmt->bind->length; delete[] m_Mstmt->bind->is_null; diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index bc87950da16..27d5e78bac5 100755 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -326,8 +326,7 @@ class ByteBuffer ByteBuffer &operator<<(const char *str) { - size_t len = 0; - if (str && (len = strlen(str))) + if (size_t len = (str ? strlen(str) : 0)) append((uint8 const*)str, len); append((uint8)0); return *this; diff --git a/src/server/worldserver/CommandLine/CliRunnable.cpp b/src/server/worldserver/CommandLine/CliRunnable.cpp index e85a3e1870d..699e7cad97c 100755 --- a/src/server/worldserver/CommandLine/CliRunnable.cpp +++ b/src/server/worldserver/CommandLine/CliRunnable.cpp @@ -116,458 +116,6 @@ void commandFinished(void*, bool /*success*/) fflush(stdout); } -/** - * Collects all GUIDs (and related info) from deleted characters which are still in the database. - * - * @param foundList a reference to an std::list which will be filled with info data - * @param searchString the search string which either contains a player GUID or a part fo the character-name - * @return returns false if there was a problem while selecting the characters (e.g. player name not normalizeable) - */ -bool ChatHandler::GetDeletedCharacterInfoList(DeletedInfoList& foundList, std::string searchString) -{ - PreparedQueryResult result; - PreparedStatement* stmt; - if (!searchString.empty()) - { - // search by GUID - if (isNumeric(searchString.c_str())) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID); - - stmt->setUInt32(0, uint32(atoi(searchString.c_str()))); - - result = CharacterDatabase.Query(stmt); - } - // search by name - else - { - if (!normalizePlayerName(searchString)) - return false; - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME); - - stmt->setString(0, searchString); - - result = CharacterDatabase.Query(stmt); - } - } - else - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_DEL_INFO); - - result = CharacterDatabase.Query(stmt); - } - - if (result) - { - do - { - Field* fields = result->Fetch(); - - DeletedInfo info; - - info.lowguid = fields[0].GetUInt32(); - info.name = fields[1].GetString(); - info.accountId = fields[2].GetUInt32(); - - // account name will be empty for not existed account - AccountMgr::GetName(info.accountId, info.accountName); - - info.deleteDate = time_t(fields[3].GetUInt32()); - - foundList.push_back(info); - } while (result->NextRow()); - } - - return true; -} - -/** - * Generate WHERE guids list by deleted info in way preventing return too long where list for existed query string length limit. - * - * @param itr a reference to an deleted info list iterator, it updated in function for possible next function call if list to long - * @param itr_end a reference to an deleted info list iterator end() - * @return returns generated where list string in form: 'guid IN (gui1, guid2, ...)' - */ -std::string ChatHandler::GenerateDeletedCharacterGUIDsWhereStr(DeletedInfoList::const_iterator& itr, DeletedInfoList::const_iterator const& itr_end) -{ - std::ostringstream wherestr; - wherestr << "guid IN ('"; - for (; itr != itr_end; ++itr) - { - wherestr << itr->lowguid; - - if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query - { - ++itr; - break; - } - - DeletedInfoList::const_iterator itr2 = itr; - if (++itr2 != itr_end) - wherestr << "', '"; - } - wherestr << "')"; - return wherestr.str(); -} - -/** - * Shows all deleted characters which matches the given search string, expected non empty list - * - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::DeletedInfoList - * - * @param foundList contains a list with all found deleted characters - */ -void ChatHandler::HandleCharacterDeletedListHelper(DeletedInfoList const& foundList) -{ - if (!m_session) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); - SendSysMessage(LANG_CHARACTER_DELETED_LIST_HEADER); - SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); - } - - for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) - { - std::string dateStr = TimeToTimestampStr(itr->deleteDate); - - if (!m_session) - PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE, - itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(), - itr->accountId, dateStr.c_str()); - else - PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CHAT, - itr->lowguid, itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(), - itr->accountId, dateStr.c_str()); - } - - if (!m_session) - SendSysMessage(LANG_CHARACTER_DELETED_LIST_BAR); -} - -/** - * Handles the '.character deleted list' command, which shows all deleted characters which matches the given search string - * - * @see ChatHandler::HandleCharacterDeletedListHelper - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::DeletedInfoList - * - * @param args the search string which either contains a player GUID or a part fo the character-name - */ -bool ChatHandler::HandleCharacterDeletedListCommand(const char* args) -{ - DeletedInfoList foundList; - if (!GetDeletedCharacterInfoList(foundList, args)) - return false; - - // if no characters have been found, output a warning - if (foundList.empty()) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); - return false; - } - - HandleCharacterDeletedListHelper(foundList); - return true; -} - -/** - * Restore a previously deleted character - * - * @see ChatHandler::HandleCharacterDeletedListHelper - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::DeletedInfoList - * - * @param delInfo the informations about the character which will be restored - */ -void ChatHandler::HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo) -{ - if (delInfo.accountName.empty()) // account not exist - { - PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); - return; - } - - // check character count - uint32 charcount = AccountMgr::GetCharactersCount(delInfo.accountId); - if (charcount >= 10) - { - PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_FULL, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); - return; - } - - if (sObjectMgr->GetPlayerGUIDByName(delInfo.name)) - { - PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_NAME, delInfo.name.c_str(), delInfo.lowguid, delInfo.accountId); - return; - } - - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_RESTORE_DELETE_INFO); - - stmt->setString(0, delInfo.name); - stmt->setUInt32(1, delInfo.accountId); - stmt->setUInt32(2, delInfo.lowguid); - - CharacterDatabase.Execute(stmt); - - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA); - stmt->setUInt32(0, delInfo.lowguid); - if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - sWorld->AddCharacterNameData(delInfo.lowguid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8()); -} - -/** - * Handles the '.character deleted restore' command, which restores all deleted characters which matches the given search string - * - * The command automatically calls '.character deleted list' command with the search string to show all restored characters. - * - * @see ChatHandler::HandleCharacterDeletedRestoreHelper - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * - * @param args the search string which either contains a player GUID or a part of the character-name - */ -bool ChatHandler::HandleCharacterDeletedRestoreCommand(const char* args) -{ - // It is required to submit at least one argument - if (!*args) - return false; - - std::string searchString; - std::string newCharName; - uint32 newAccount = 0; - - // GCC by some strange reason fail build code without temporary variable - std::istringstream params(args); - params >> searchString >> newCharName >> newAccount; - - DeletedInfoList foundList; - if (!GetDeletedCharacterInfoList(foundList, searchString)) - return false; - - if (foundList.empty()) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); - return false; - } - - SendSysMessage(LANG_CHARACTER_DELETED_RESTORE); - HandleCharacterDeletedListHelper(foundList); - - if (newCharName.empty()) - { - // Drop not existed account cases - for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr) - HandleCharacterDeletedRestoreHelper(*itr); - } - else if (foundList.size() == 1 && normalizePlayerName(newCharName)) - { - DeletedInfo delInfo = foundList.front(); - - // update name - delInfo.name = newCharName; - - // if new account provided update deleted info - if (newAccount && newAccount != delInfo.accountId) - { - delInfo.accountId = newAccount; - AccountMgr::GetName(newAccount, delInfo.accountName); - } - - HandleCharacterDeletedRestoreHelper(delInfo); - } - else - SendSysMessage(LANG_CHARACTER_DELETED_ERR_RENAME); - - return true; -} - -/** - * Handles the '.character deleted delete' command, which completely deletes all deleted characters which matches the given search string - * - * @see Player::GetDeletedCharacterGUIDs - * @see Player::DeleteFromDB - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * - * @param args the search string which either contains a player GUID or a part fo the character-name - */ -bool ChatHandler::HandleCharacterDeletedDeleteCommand(const char* args) -{ - // It is required to submit at least one argument - if (!*args) - return false; - - DeletedInfoList foundList; - if (!GetDeletedCharacterInfoList(foundList, args)) - return false; - - if (foundList.empty()) - { - SendSysMessage(LANG_CHARACTER_DELETED_LIST_EMPTY); - return false; - } - - SendSysMessage(LANG_CHARACTER_DELETED_DELETE); - HandleCharacterDeletedListHelper(foundList); - - // Call the appropriate function to delete them (current account for deleted characters is 0) - for (DeletedInfoList::const_iterator itr = foundList.begin(); itr != foundList.end(); ++itr) - Player::DeleteFromDB(itr->lowguid, 0, false, true); - - return true; -} - -/** - * Handles the '.character deleted old' command, which completely deletes all deleted characters deleted with some days ago - * - * @see Player::DeleteOldCharacters - * @see Player::DeleteFromDB - * @see ChatHandler::HandleCharacterDeletedDeleteCommand - * @see ChatHandler::HandleCharacterDeletedListCommand - * @see ChatHandler::HandleCharacterDeletedRestoreCommand - * - * @param args the search string which either contains a player GUID or a part fo the character-name - */ -bool ChatHandler::HandleCharacterDeletedOldCommand(const char* args) -{ - int32 keepDays = sWorld->getIntConfig(CONFIG_CHARDELETE_KEEP_DAYS); - - char* px = strtok((char*)args, " "); - if (px) - { - if (!isNumeric(px)) - return false; - - keepDays = atoi(px); - if (keepDays < 0) - return false; - } - // config option value 0 -> disabled and can't be used - else if (keepDays <= 0) - return false; - - Player::DeleteOldCharacters((uint32)keepDays); - return true; -} - -bool ChatHandler::HandleCharacterEraseCommand(const char* args){ - if (!*args) - return false; - - char *character_name_str = strtok((char*)args, " "); - if (!character_name_str) - return false; - - std::string character_name = character_name_str; - if (!normalizePlayerName(character_name)) - return false; - - uint64 character_guid; - uint32 account_id; - - Player* player = sObjectAccessor->FindPlayerByName(character_name.c_str()); - if (player) - { - character_guid = player->GetGUID(); - account_id = player->GetSession()->GetAccountId(); - player->GetSession()->KickPlayer(); - } - else - { - character_guid = sObjectMgr->GetPlayerGUIDByName(character_name); - if (!character_guid) - { - PSendSysMessage(LANG_NO_PLAYER, character_name.c_str()); - SetSentErrorMessage(true); - return false; - } - - account_id = sObjectMgr->GetPlayerAccountIdByGUID(character_guid); - } - - std::string account_name; - AccountMgr::GetName (account_id, account_name); - - Player::DeleteFromDB(character_guid, account_id, true, true); - PSendSysMessage(LANG_CHARACTER_DELETED, character_name.c_str(), GUID_LOPART(character_guid), account_name.c_str(), account_id); - return true; -} - -/// Exit the realm -bool ChatHandler::HandleServerExitCommand(const char* /*args*/) -{ - SendSysMessage(LANG_COMMAND_EXIT); - World::StopNow(SHUTDOWN_EXIT_CODE); - return true; -} - -/// Set the level of logging -bool ChatHandler::HandleServerSetLogFileLevelCommand(const char *args) -{ - if (!*args) - return false; - - char *NewLevel = strtok((char*)args, " "); - if (!NewLevel) - return false; - - sLog->SetLogFileLevel(NewLevel); - return true; -} - -/// Set the level of logging -bool ChatHandler::HandleServerSetLogLevelCommand(const char *args) -{ - if (!*args) - return false; - - char *NewLevel = strtok((char*)args, " "); - if (!NewLevel) - return false; - - sLog->SetLogLevel(NewLevel); - return true; -} - -/// set diff time record interval -bool ChatHandler::HandleServerSetDiffTimeCommand(const char *args) -{ - if (!*args) - return false; - - char *NewTimeStr = strtok((char*)args, " "); - if (!NewTimeStr) - return false; - - int32 NewTime =atoi(NewTimeStr); - if (NewTime < 0) - return false; - - sWorld->SetRecordDiffInterval(NewTime); - printf( "Record diff every %u ms\n", NewTime); - return true; -} - -/// toggle sql driver query logging -bool ChatHandler::HandleServerToggleQueryLogging(const char* /* args */) -{ - sLog->SetSQLDriverQueryLogging(!sLog->GetSQLDriverQueryLogging()); - if (sLog->GetSQLDriverQueryLogging()) - PSendSysMessage(LANG_SQLDRIVER_QUERY_LOGGING_ENABLED); - else - PSendSysMessage(LANG_SQLDRIVER_QUERY_LOGGING_DISABLED); - - return true; -} - -/// @} - #ifdef linux // Non-blocking keypress detector, when return pressed, return 1, else always return 0 int kb_hit_return() diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 6c598667a1f..110b7744b94 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -484,12 +484,13 @@ LogFileLevel = 0 DebugLogMask = 0 # -# WorldLogFile -# Description: Packet logging file for the world server. -# Example: "World.log" - (Enabled) +# PacketLogFile +# Description: Binary packet logging file for the world server. +# Filename extension must be .bin to be parsable with WowPacketParser. +# Example: "World.bin" - (Enabled) # Default: "" - (Disabled) -WorldLogFile = "" +PacketLogFile = "" # # DBErrorLogFile @@ -2025,17 +2026,17 @@ Visibility.GroupMode = 1 # Visibility.Distance.Instances # Visibility.Distance.BGArenas # Description: Visibility distance to see other players or gameobjects. -# Visibility on continents on retail ~90 yards. In BG/Arenas ~180. -# For instances default ~120. -# Max limited by active player zone: ~ 333 +# Visibility on continents on retail ~90 yards. In BG/Arenas ~533. +# For instances default ~170. +# Max limited by grid size: 533.33333 # Min limit is max aggro radius (45) * Rate.Creature.Aggro # Default: 90 - (Visibility.Distance.Continents) -# 120 - (Visibility.Distance.Instances) -# 180 - (Visibility.Distance.BGArenas) +# 170 - (Visibility.Distance.Instances) +# 533 - (Visibility.Distance.BGArenas) Visibility.Distance.Continents = 90 -Visibility.Distance.Instances = 120 -Visibility.Distance.BGArenas = 180 +Visibility.Distance.Instances = 170 +Visibility.Distance.BGArenas = 533 # # Visibility.Notify.Period.OnContinents @@ -2515,6 +2516,13 @@ Arena.MaxRatingDifference = 150 Arena.RatingDiscardTimer = 600000 # +# Arena.RatedUpdateTimer +# Description: Time (in milliseconds) between checks for matchups in rated arena +# Default: 5000 - (5 seconds) + +Arena.RatedUpdateTimer = 5000 + +# # Arena.AutoDistributePoints # Description: Automatically distribute arena points. # Default: 0 - (Disabled) diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index af66b73827e..99bdc1feb5f 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable(mapextractor ) target_link_libraries(mapextractor + mpq ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} storm diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 41941795b20..9785f89b199 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -50,9 +50,9 @@ char output_path[128] = "."; char input_path[128] = "."; uint32 maxAreaId = 0; -//************************************************** +// ************************************************** // Extractor options -//************************************************** +// ************************************************** enum Extract { EXTRACT_MAP = 1, @@ -79,13 +79,14 @@ uint32 CONF_TargetBuild = 14545; // 4.2.2.14545 char const* CONF_mpq_list[]= { "world.MPQ", + "art.MPQ", "world2.MPQ", "expansion1.MPQ", "expansion2.MPQ", "expansion3.MPQ", }; -uint32 const Builds[] = {13164, 13205, 13287, 13329, 13596, 13623, 13914, 14007, 14333, 14480, 14545, 15005, 15050, 15211, 0}; +uint32 const Builds[] = {13164, 13205, 13287, 13329, 13596, 13623, 13914, 14007, 14333, 14480, 14545, 15005, 15050, 15211, 15354, 15595, 0}; #define LAST_DBC_IN_DATA_BUILD 13623 // after this build mpqs with dbc are back to locale folder char* const Locales[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU"}; @@ -293,7 +294,7 @@ void ReadAreaTableDBC() areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); SFileCloseFile(dbcFile); - printf("Done! (%u areas loaded)\n", area_count); + printf("Done! (%zu areas loaded)\n", area_count); } void ReadLiquidTypeTableDBC() @@ -419,7 +420,7 @@ uint8 liquid_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]; bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE]; float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]; -bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32 build) +bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, uint32 build) { ADT_file adt; @@ -623,7 +624,7 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32 // Try store as packed in uint16 or uint8 values if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT)) { - float step; + float step = 0; // Try Store as uint values if (CONF_allow_float_to_int) { @@ -1018,7 +1019,9 @@ void ExtractDBCFiles(int l, bool basicLocale) uint32 count = 0; if (listFile) { - std::string outputPath = "./dbc/"; + std::string outputPath = output_path; + outputPath += "/dbc/"; + CreateDir(outputPath); if (!basicLocale) { @@ -1062,7 +1065,8 @@ void ExtractDB2Files(int l, bool basicLocale) uint32 count = 0; if (listFile) { - std::string outputPath = "./dbc/"; + std::string outputPath = output_path; + outputPath += "/dbc/"; if (!basicLocale) { outputPath += Locales[l]; @@ -1150,8 +1154,15 @@ void LoadCommonMPQFiles(uint32 build) _stprintf(filename, _T("%s/Data/%s"), input_path, CONF_mpq_list[i]); if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0)) + { if (GetLastError() != ERROR_PATH_NOT_FOUND) _tprintf(_T("Cannot open archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); + } + else + _tprintf(_T("Loaded %s\n"), filename); + } char const* prefix = NULL; @@ -1173,8 +1184,12 @@ void LoadCommonMPQFiles(uint32 build) { if (GetLastError() != ERROR_PATH_NOT_FOUND) _tprintf(_T("Cannot open patch archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); continue; } + else + _tprintf(_T("Loaded %s\n"), filename); } } @@ -1191,9 +1206,6 @@ int main(int argc, char * arg[]) for (int i = 0; i < LOCALES_COUNT; ++i) { - TCHAR tmp1[512]; - _stprintf(tmp1, _T("%s/Data/%s/locale-%s.MPQ"), input_path, Locales[i], Locales[i]); - //Open MPQs if (!LoadLocaleMPQFile(i)) { diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt index c1ef3125a20..8066b18423a 100644 --- a/src/tools/vmap4_extractor/CMakeLists.txt +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -15,9 +15,11 @@ file(GLOB_RECURSE sources *.cpp *.h) add_definitions("-DIOMAP_DEBUG") # build setup currently only supports libmpq 0.4.x -add_definitions("-Wall") -add_definitions("-ggdb") -add_definitions("-O3") +if( NOT WIN32 ) + add_definitions("-Wall") + add_definitions("-ggdb") + add_definitions("-O3") +endif() include_directories( ${CMAKE_SOURCE_DIR}/dep/StormLib/src @@ -26,6 +28,7 @@ include_directories( add_executable(vmap4extractor ${sources}) target_link_libraries(vmap4extractor + mpq ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} storm diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index a966172a3be..c53b63ffa5e 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -78,7 +78,9 @@ char * GetExtension(char * FileName) return NULL; } -ADTFile::ADTFile(char* filename): ADT(filename) +extern HANDLE WorldMpq; + +ADTFile::ADTFile(char* filename): ADT(WorldMpq, filename) { Adtfilename.append(filename); } diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index 08814996f68..795eebc892f 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -19,7 +19,7 @@ #ifndef ADT_H #define ADT_H -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include "wmo.h" #include "model.h" diff --git a/src/tools/vmap4_extractor/dbcfile.cpp b/src/tools/vmap4_extractor/dbcfile.cpp index 5b5fe314799..efc8aeabe8c 100644 --- a/src/tools/vmap4_extractor/dbcfile.cpp +++ b/src/tools/vmap4_extractor/dbcfile.cpp @@ -20,13 +20,16 @@ #include "dbcfile.h" -DBCFile::DBCFile(HANDLE file) : - _file(file), _data(NULL), _stringTable(NULL) +DBCFile::DBCFile(HANDLE mpq, const char* filename) : + _mpq(mpq), _filename(filename), _file(NULL), _data(NULL), _stringTable(NULL) { } bool DBCFile::open() { + if (!SFileOpenFileEx(_mpq, _filename, SFILE_OPEN_PATCHED_FILE, &_file)) + return false; + char header[4]; unsigned int na, nb, es, ss; @@ -38,18 +41,22 @@ bool DBCFile::open() if (header[0] != 'W' || header[1] != 'D' || header[2] != 'B' || header[3] != 'C') return false; + readBytes = 0; SFileReadFile(_file, &na, 4, &readBytes, NULL); if (readBytes != 4) // Number of records return false; + readBytes = 0; SFileReadFile(_file, &nb, 4, &readBytes, NULL); if (readBytes != 4) // Number of fields return false; + readBytes = 0; SFileReadFile(_file, &es, 4, &readBytes, NULL); if (readBytes != 4) // Size of a record return false; + readBytes = 0; SFileReadFile(_file, &ss, 4, &readBytes, NULL); if (readBytes != 4) // String size return false; @@ -65,6 +72,7 @@ bool DBCFile::open() _stringTable = _data + _recordSize*_recordCount; size_t data_size = _recordSize * _recordCount + _stringSize; + readBytes = 0; SFileReadFile(_file, _data, data_size, &readBytes, NULL); if (readBytes != data_size) return false; @@ -75,6 +83,8 @@ bool DBCFile::open() DBCFile::~DBCFile() { delete [] _data; + if (_file != NULL) + SFileCloseFile(_file); } DBCFile::Record DBCFile::getRecord(size_t id) diff --git a/src/tools/vmap4_extractor/dbcfile.h b/src/tools/vmap4_extractor/dbcfile.h index 9fdb7a9e268..007ccb6cdcb 100644 --- a/src/tools/vmap4_extractor/dbcfile.h +++ b/src/tools/vmap4_extractor/dbcfile.h @@ -25,7 +25,7 @@ class DBCFile { public: - DBCFile(HANDLE file); + DBCFile(HANDLE mpq, const char* filename); ~DBCFile(); // Open database. It must be openened before it can be used. @@ -131,6 +131,8 @@ class DBCFile size_t getMaxId(); private: + HANDLE _mpq; + const char* _filename; HANDLE _file; size_t _recordSize; size_t _recordCount; diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp index 8a1f67cd2c2..4c8e423bfc4 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -35,10 +35,12 @@ bool ExtractSingleModel(std::string& fname) return mdl.ConvertToVMAPModel(output.c_str()); } +extern HANDLE LocaleMpq; + void ExtractGameobjectModels() { printf("Extracting GameObject models..."); - DBCFile dbc("DBFilesClient\\GameObjectDisplayInfo.dbc"); + DBCFile dbc(LocaleMpq, "DBFilesClient\\GameObjectDisplayInfo.dbc"); if(!dbc.open()) { printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n"); diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index e81972f521f..d98dca9001b 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -19,18 +19,20 @@ #include "vmapexport.h" #include "model.h" #include "wmo.h" -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include <cassert> #include <algorithm> #include <cstdio> +extern HANDLE WorldMpq; + Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0) { } bool Model::open() { - MPQFile f(filename.c_str()); + MPQFile f(WorldMpq, filename.c_str()); ok = !f.isEof(); diff --git a/src/tools/vmap4_extractor/modelheaders.h b/src/tools/vmap4_extractor/modelheaders.h index d859fd3511e..7fd908d7442 100644 --- a/src/tools/vmap4_extractor/modelheaders.h +++ b/src/tools/vmap4_extractor/modelheaders.h @@ -19,12 +19,7 @@ #ifndef MODELHEADERS_H #define MODELHEADERS_H -/* typedef unsigned char uint8; -typedef char int8; -typedef unsigned short uint16; -typedef short int16; -typedef unsigned int uint32; -typedef int int32; */ +#include "mpqfile.h" // integer typedefs #pragma pack(push,1) diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp deleted file mode 100644 index 528b9679a58..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "mpq_libmpq04.h" -#include <deque> -#include <cstdio> - -ArchiveSet gOpenArchives; - -MPQArchive::MPQArchive(const char* filename) -{ - int result = libmpq__archive_open(&mpq_a, filename, -1); - printf("Opening %s\n", filename); - if(result) { - switch(result) { - case LIBMPQ_ERROR_OPEN : - printf("Error opening archive '%s': Does file really exist?\n", filename); - break; - case LIBMPQ_ERROR_FORMAT : /* bad file format */ - printf("Error opening archive '%s': Bad file format\n", filename); - break; - case LIBMPQ_ERROR_SEEK : /* seeking in file failed */ - printf("Error opening archive '%s': Seeking in file failed\n", filename); - break; - case LIBMPQ_ERROR_READ : /* Read error in archive */ - printf("Error opening archive '%s': Read error in archive\n", filename); - break; - case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */ - printf("Error opening archive '%s': Maybe not enough memory\n", filename); - break; - default: - printf("Error opening archive '%s': Unknown error\n", filename); - break; - } - return; - } - gOpenArchives.push_front(this); -} - -void MPQArchive::close() -{ - //gOpenArchives.erase(erase(&mpq_a); - libmpq__archive_close(mpq_a); -} - -MPQFile::MPQFile(const char* filename): - eof(false), - buffer(0), - pointer(0), - size(0) -{ - for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i) - { - mpq_archive *mpq_a = (*i)->mpq_a; - - uint32 filenum; - if(libmpq__file_number(mpq_a, filename, &filenum)) continue; - libmpq__off_t transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); - - // HACK: in patch.mpq some files don't want to open and give 1 for filesize - if (size<=1) { - // printf("info: file %s has size %d; considered dummy file.\n", filename, size); - eof = true; - buffer = 0; - return; - } - buffer = new char[size]; - - //libmpq_file_getdata - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - /*libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);*/ - return; - - } - eof = true; - buffer = 0; -} - -size_t MPQFile::read(void* dest, size_t bytes) -{ - if (eof) return 0; - - size_t rpos = pointer + bytes; - if (rpos > size) { - bytes = size - pointer; - eof = true; - } - - memcpy(dest, &(buffer[pointer]), bytes); - - pointer = rpos; - - return bytes; -} - -void MPQFile::seek(int offset) -{ - pointer = offset; - eof = (pointer >= size); -} - -void MPQFile::seekRelative(int offset) -{ - pointer += offset; - eof = (pointer >= size); -} - -void MPQFile::close() -{ - if (buffer) delete[] buffer; - buffer = 0; - eof = true; -} diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h deleted file mode 100644 index 5101309002e..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq04.h +++ /dev/null @@ -1,90 +0,0 @@ -#define _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_WARNINGS - -#ifndef MPQ_H -#define MPQ_H - -#include "libmpq/mpq.h" -#include <string.h> -#include <ctype.h> -#include <vector> -#include <iostream> -#include <deque> - -using namespace std; - -class MPQArchive -{ - -public: - mpq_archive_s *mpq_a; - - MPQArchive(const char* filename); - void close(); - - void GetFileListTo(vector<string>& filelist) { - uint32 filenum; - if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; - libmpq__off_t size, transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); - - char *buffer = new char[size]; - - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - - char seps[] = "\n"; - char *token; - - token = strtok( buffer, seps ); - uint32 counter = 0; - while ((token != NULL) && (counter < size)) { - //cout << token << endl; - token[strlen(token) - 1] = 0; - string s = token; - filelist.push_back(s); - counter += strlen(token) + 2; - token = strtok(NULL, seps); - } - - delete[] buffer; - } -}; -typedef std::deque<MPQArchive*> ArchiveSet; - -class MPQFile -{ - //MPQHANDLE handle; - bool eof; - char *buffer; - libmpq__off_t pointer,size; - - // disable copying - MPQFile(const MPQFile &f) {} - void operator=(const MPQFile &f) {} - -public: - MPQFile(const char* filename); // filenames are not case sensitive - ~MPQFile() { close(); } - size_t read(void* dest, size_t bytes); - size_t getSize() { return size; } - size_t getPos() { return pointer; } - char* getBuffer() { return buffer; } - char* getPointer() { return buffer + pointer; } - bool isEof() { return eof; } - void seek(int offset); - void seekRelative(int offset); - void close(); -}; - -inline void flipcc(char *fcc) -{ - char t; - t=fcc[0]; - fcc[0]=fcc[3]; - fcc[3]=t; - t=fcc[1]; - fcc[1]=fcc[2]; - fcc[2]=t; -} - -#endif diff --git a/src/tools/vmap4_extractor/mpqfile.cpp b/src/tools/vmap4_extractor/mpqfile.cpp new file mode 100644 index 00000000000..9f019f99f38 --- /dev/null +++ b/src/tools/vmap4_extractor/mpqfile.cpp @@ -0,0 +1,86 @@ +#include "mpqfile.h" +#include <deque> +#include <cstdio> +#include "StormLib.h" + +MPQFile::MPQFile(HANDLE mpq, const char* filename): + eof(false), + buffer(0), + pointer(0), + size(0) +{ + HANDLE file; + if (!SFileOpenFileEx(mpq, filename, SFILE_OPEN_PATCHED_FILE, &file)) + { + fprintf(stderr, "Can't open %s, err=%u!\n", filename, GetLastError()); + eof = true; + return; + } + + DWORD hi = 0; + size = SFileGetFileSize(file, &hi); + + if (hi) + { + fprintf(stderr, "Can't open %s, size[hi] = %u!\n", filename, (uint32)hi); + SFileCloseFile(file); + eof = true; + return; + } + + if (size <= 1) + { + fprintf(stderr, "Can't open %s, size = %u!\n", filename, size); + SFileCloseFile(file); + eof = true; + return; + } + + DWORD read = 0; + buffer = new char[size]; + if (!SFileReadFile(file, buffer, size, &read) || size != read) + { + fprintf(stderr, "Can't read %s, size=%u read=%u!\n", filename, size, read); + SFileCloseFile(file); + eof = true; + return; + } + + SFileCloseFile(file); +} + +size_t MPQFile::read(void* dest, size_t bytes) +{ + if (eof) return 0; + + size_t rpos = pointer + bytes; + if (rpos > size) { + bytes = size - pointer; + eof = true; + } + + memcpy(dest, &(buffer[pointer]), bytes); + + pointer = rpos; + + return bytes; +} + +void MPQFile::seek(int offset) +{ + pointer = offset; + eof = (pointer >= size); +} + +void MPQFile::seekRelative(int offset) +{ + pointer += offset; + eof = (pointer >= size); +} + +void MPQFile::close() +{ + if (buffer) delete[] buffer; + buffer = 0; + eof = true; +} diff --git a/src/tools/vmap4_extractor/mpqfile.h b/src/tools/vmap4_extractor/mpqfile.h new file mode 100644 index 00000000000..115d096a215 --- /dev/null +++ b/src/tools/vmap4_extractor/mpqfile.h @@ -0,0 +1,80 @@ +#define _CRT_SECURE_NO_DEPRECATE +#ifndef _CRT_SECURE_NO_WARNINGS // fuck the police^Wwarnings +#define _CRT_SECURE_NO_WARNINGS +#endif + +#ifndef MPQ_H +#define MPQ_H + +#include <string.h> +#include <ctype.h> +#include <vector> +#include <iostream> +#include <deque> + +#ifdef _WIN32 +#include <Windows.h> // mainly only HANDLE definition is required +typedef __int64 int64; +typedef __int32 int32; +typedef __int16 int16; +typedef __int8 int8; +typedef unsigned __int64 uint64; +typedef unsigned __int32 uint32; +typedef unsigned __int16 uint16; +typedef unsigned __int8 uint8; +#else +#include <stdint.h> +#ifndef uint64_t +#ifdef __linux__ +#include <linux/types.h> +#endif +#endif +typedef int64_t int64; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; +#endif + +using namespace std; + +class MPQFile +{ + //MPQHANDLE handle; + bool eof; + char *buffer; + size_t pointer,size; + + // disable copying + MPQFile(const MPQFile &f); + void operator=(const MPQFile &f); + +public: + MPQFile(HANDLE mpq, const char* filename); // filenames are not case sensitive + ~MPQFile() { close(); } + size_t read(void* dest, size_t bytes); + size_t getSize() { return size; } + size_t getPos() { return pointer; } + char* getBuffer() { return buffer; } + char* getPointer() { return buffer + pointer; } + bool isEof() { return eof; } + void seek(int offset); + void seekRelative(int offset); + void close(); +}; + +inline void flipcc(char *fcc) +{ + char t; + t=fcc[0]; + fcc[0]=fcc[3]; + fcc[3]=t; + t=fcc[1]; + fcc[1]=fcc[2]; + fcc[2]=t; +} + +#endif diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index e60a773c6de..1582f9d0b25 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -45,7 +45,7 @@ #include "wdtfile.h" #include "dbcfile.h" #include "wmo.h" -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include "vmapexport.h" @@ -56,7 +56,37 @@ //----------------------------------------------------------------------------- -extern ArchiveSet gOpenArchives; +HANDLE WorldMpq = NULL; +HANDLE LocaleMpq = NULL; + +uint32 CONF_TargetBuild = 14545; // 4.2.2.14545 + +// List MPQ for extract maps from +char const* CONF_mpq_list[]= +{ + "world.MPQ", + "art.MPQ", + "expansion1.MPQ", + "expansion2.MPQ", + "expansion3.MPQ", + "world2.MPQ", +}; + +uint32 const Builds[] = {13164, 13205, 13287, 13329, 13596, 13623, 13914, 14007, 14333, 14480, 14545, 15005, 15050, 15211, 15354, 15595, 0}; +#define LAST_DBC_IN_DATA_BUILD 13623 // after this build mpqs with dbc are back to locale folder + +char* const Locales[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU"}; +TCHAR* const LocalesT[] = +{ + _T("enGB"), _T("enUS"), + _T("deDE"), _T("esES"), + _T("frFR"), _T("koKR"), + _T("zhCN"), _T("zhTW"), + _T("enCN"), _T("enTW"), + _T("esMX"), _T("ruRU"), +}; + +#define LOCALES_COUNT 12 typedef struct { @@ -69,7 +99,6 @@ uint16 *LiqType = 0; uint32 map_count; char output_path[128]="."; char input_path[1024]="."; -bool hasInputPathParam = false; bool preciseVectorData = false; // Constants @@ -78,6 +107,148 @@ bool preciseVectorData = false; const char* szWorkDirWmo = "./Buildings"; const char* szRawVMAPMagic = "VMAP041"; +bool LoadLocaleMPQFile(int locale) +{ + TCHAR buff[512]; + memset(buff, 0, sizeof(buff)); + _stprintf(buff, _T("%s%s/locale-%s.MPQ"), input_path, LocalesT[locale], LocalesT[locale]); + if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &LocaleMpq)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), buff); + return false; + } + + char const* prefix = NULL; + for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) + { + memset(buff, 0, sizeof(buff)); + if (Builds[i] > LAST_DBC_IN_DATA_BUILD) + { + prefix = ""; + _stprintf(buff, _T("%s%s/wow-update-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]); + } + else + { + prefix = Locales[locale]; + _stprintf(buff, _T("%swow-update-%u.MPQ"), input_path, Builds[i]); + } + + if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0)) + { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + _tprintf(_T("Cannot open patch archive %s\n"), buff); + continue; + } + } + + return true; +} + +void LoadCommonMPQFiles(uint32 build) +{ + TCHAR filename[512]; + _stprintf(filename, _T("%sworld.MPQ"), input_path); + if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), filename); + return; + } + + int count = sizeof(CONF_mpq_list) / sizeof(char*); + for (int i = 1; i < count; ++i) + { + if (build < 15211 && !strcmp("world2.MPQ", CONF_mpq_list[i])) // 4.3.2 and higher MPQ + continue; + + _stprintf(filename, _T("%s%s"), input_path, CONF_mpq_list[i]); + if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); + } + else + { + _tprintf(_T("Loaded %s\n"), filename); + + bool found = false; + int count = 0; + SFILE_FIND_DATA data; + HANDLE find = SFileFindFirstFile(WorldMpq, "*.*", &data, NULL); + if (find != NULL) + { + do + { + ++count; + if (data.dwFileFlags & MPQ_FILE_PATCH_FILE) + { + found = true; + break; + } + } + while (SFileFindNextFile(find, &data)); + } + SFileFindClose(find); + printf("Scanned %d files, found patch = %d\n", count, found); + } + } + + char const* prefix = NULL; + for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) + { + memset(filename, 0, sizeof(filename)); + if (Builds[i] > LAST_DBC_IN_DATA_BUILD) + { + prefix = ""; + _stprintf(filename, _T("%swow-update-base-%u.MPQ"), input_path, Builds[i]); + } + else + { + prefix = "base"; + _stprintf(filename, _T("%swow-update-%u.MPQ"), input_path, Builds[i]); + } + + if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open patch archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); + continue; + } + else + { + _tprintf(_T("Loaded %s\n"), filename); + + + bool found = false; + int count = 0; + SFILE_FIND_DATA data; + HANDLE find = SFileFindFirstFile(WorldMpq, "*.*", &data, NULL); + if (find != NULL) + { + do + { + ++count; + if (data.dwFileFlags & MPQ_FILE_PATCH_FILE) + { + found = true; + break; + } + } + while (SFileFindNextFile(find, &data)); + } + SFileFindClose(find); + printf("Scanned %d files, found patch = %d\n", count, found); + } + } + +} + + // Local testing functions bool FileExists(const char* file) @@ -103,7 +274,8 @@ void strToLower(char* str) void ReadLiquidTypeTableDBC() { printf("Read LiquidType.dbc file..."); - DBCFile dbc("DBFilesClient\\LiquidType.dbc"); + + DBCFile dbc(LocaleMpq, "DBFilesClient\\LiquidType.dbc"); if(!dbc.open()) { printf("Fatal error: Invalid LiquidType.dbc file format!\n"); @@ -123,21 +295,23 @@ void ReadLiquidTypeTableDBC() bool ExtractWmo() { - bool success = true; + bool success = false; //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"}; - for (ArchiveSet::const_iterator ar_itr = gOpenArchives.begin(); ar_itr != gOpenArchives.end() && success; ++ar_itr) + SFILE_FIND_DATA data; + HANDLE find = SFileFindFirstFile(WorldMpq, "*.wmo", &data, NULL); + if (find != NULL) { - vector<string> filelist; - - (*ar_itr)->GetFileListTo(filelist); - for (vector<string>::iterator fname = filelist.begin(); fname != filelist.end() && success; ++fname) + do { - if (fname->find(".wmo") != string::npos) - success = ExtractSingleWmo(*fname); + std::string str = data.cFileName; + //printf("Extracting wmo %s\n", str.c_str()); + success |= ExtractSingleWmo(str); } + while (SFileFindNextFile(find, &data)); } + SFileFindClose(find); if (success) printf("\nExtract wmo complete (No (fatal) errors)\n"); @@ -297,91 +471,10 @@ bool scan_patches(char* scanmatch, std::vector<std::string>& pArchiveNames) return(true); } -bool fillArchiveNameVector(std::vector<std::string>& pArchiveNames) -{ - if(!hasInputPathParam) - getGamePath(); - - printf("\nGame path: %s\n", input_path); - - char path[512]; - string in_path(input_path); - std::vector<std::string> locales, searchLocales; - - searchLocales.push_back("enGB"); - searchLocales.push_back("enUS"); - searchLocales.push_back("deDE"); - searchLocales.push_back("esES"); - searchLocales.push_back("frFR"); - searchLocales.push_back("koKR"); - searchLocales.push_back("zhCN"); - searchLocales.push_back("zhTW"); - searchLocales.push_back("enCN"); - searchLocales.push_back("enTW"); - searchLocales.push_back("esMX"); - searchLocales.push_back("ruRU"); - - for (std::vector<std::string>::iterator i = searchLocales.begin(); i != searchLocales.end(); ++i) - { - std::string localePath = in_path + *i; - // check if locale exists: - struct stat status; - if (stat(localePath.c_str(), &status)) - continue; - if ((status.st_mode & S_IFDIR) == 0) - continue; - printf("Found locale '%s'\n", i->c_str()); - locales.push_back(*i); - } - printf("\n"); - - // open locale expansion and common files - printf("Adding data files from locale directories.\n"); - for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i) - { - pArchiveNames.push_back(in_path + *i + "/locale-" + *i + ".MPQ"); - pArchiveNames.push_back(in_path + *i + "/expansion-locale-" + *i + ".MPQ"); - pArchiveNames.push_back(in_path + *i + "/lichking-locale-" + *i + ".MPQ"); - } - - // open expansion and common files - pArchiveNames.push_back(input_path + string("common.MPQ")); - pArchiveNames.push_back(input_path + string("common-2.MPQ")); - pArchiveNames.push_back(input_path + string("expansion.MPQ")); - pArchiveNames.push_back(input_path + string("lichking.MPQ")); - - // now, scan for the patch levels in the core dir - printf("Scanning patch levels from data directory.\n"); - sprintf(path, "%spatch", input_path); - if (!scan_patches(path, pArchiveNames)) - return(false); - - // now, scan for the patch levels in locale dirs - printf("Scanning patch levels from locale directories.\n"); - bool foundOne = false; - for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i) - { - printf("Locale: %s\n", i->c_str()); - sprintf(path, "%s%s/patch-%s", input_path, i->c_str(), i->c_str()); - if(scan_patches(path, pArchiveNames)) - foundOne = true; - } - - printf("\n"); - - if(!foundOne) - { - printf("no locale found\n"); - return false; - } - - return true; -} - bool processArgv(int argc, char ** argv, const char *versionString) { bool result = true; - hasInputPathParam = false; + bool hasInputPathParam = false; bool preciseVectorData = false; for(int i=1; i< argc; ++i) @@ -413,12 +506,18 @@ bool processArgv(int argc, char ** argv, const char *versionString) { preciseVectorData = true; } + else if(strcmp("-b",argv[i]) == 0) + { + if (i + 1 < argc) // all ok + CONF_TargetBuild = atoi(argv[i++ + 1]); + } else { result = false; break; } } + if(!result) { printf("Extract %s.\n",versionString); @@ -426,8 +525,13 @@ bool processArgv(int argc, char ** argv, const char *versionString) printf(" -s : (default) small size (data size optimization), ~500MB less vmap data.\n"); printf(" -l : large size, ~500MB more vmap data. (might contain more details)\n"); printf(" -d <path>: Path to the vector data source folder.\n"); + printf(" -b : target build (default 14545)"); printf(" -? : This message.\n"); } + + if(!hasInputPathParam) + getGamePath(); + return result; } @@ -476,21 +580,24 @@ int main(int argc, char ** argv) )) success = (errno == EEXIST); - // prepare archive name list - std::vector<std::string> archiveNames; - fillArchiveNameVector(archiveNames); - for (size_t i=0; i < archiveNames.size(); ++i) - { - MPQArchive *archive = new MPQArchive(archiveNames[i].c_str()); - if(!gOpenArchives.size() || gOpenArchives.front() != archive) - delete archive; - } + LoadCommonMPQFiles(CONF_TargetBuild); + + int FirstLocale = -1; - if(gOpenArchives.empty()) + for (int i = 0; i < LOCALES_COUNT; ++i) { - printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n",input_path); - return 1; + //Open MPQs + if (!LoadLocaleMPQFile(i)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + printf("Unable to load %s locale archives!\n", Locales[i]); + continue; + } + + printf("Detected and using locale locale: %s\n", Locales[i]); + break; } + ReadLiquidTypeTableDBC(); // extract data @@ -501,7 +608,7 @@ int main(int argc, char ** argv) //map.dbc if(success) { - DBCFile * dbc = new DBCFile("DBFilesClient\\Map.dbc"); + DBCFile * dbc = new DBCFile(LocaleMpq, "DBFilesClient\\Map.dbc"); if(!dbc->open()) { delete dbc; @@ -526,6 +633,9 @@ int main(int argc, char ** argv) ExtractGameobjectModels(); } + SFileCloseArchive(LocaleMpq); + SFileCloseArchive(WorldMpq); + printf("\n"); if(!success) { diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index e3ee545db19..2dd7396ae7d 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -30,7 +30,9 @@ char * wdtGetPlainName(char * FileName) return FileName; } -WDTFile::WDTFile(char* file_name, char* file_name1):WDT(file_name) +extern HANDLE WorldMpq; + +WDTFile::WDTFile(char* file_name, char* file_name1):WDT(WorldMpq, file_name) { filename.append(file_name1,strlen(file_name1)); } @@ -129,6 +131,6 @@ ADTFile* WDTFile::GetMap(int x, int z) char name[512]; - sprintf(name,"World\\Maps\\%s\\%s_%d_%d.adt", filename.c_str(), filename.c_str(), x, z); + sprintf(name,"World\\Maps\\%s\\%s_%d_%d_obj0.adt", filename.c_str(), filename.c_str(), x, z); return new ADTFile(name); } diff --git a/src/tools/vmap4_extractor/wdtfile.h b/src/tools/vmap4_extractor/wdtfile.h index f3d71c41791..ef3ec6db98c 100644 --- a/src/tools/vmap4_extractor/wdtfile.h +++ b/src/tools/vmap4_extractor/wdtfile.h @@ -1,7 +1,7 @@ #ifndef WDTFILE_H #define WDTFILE_H -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include "wmo.h" #include <string> #include "stdlib.h" diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 6703872111b..8bba5610c88 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -26,7 +26,7 @@ #include <fstream> #undef min #undef max -#include "mpq_libmpq04.h" +#include "mpqfile.h" using namespace std; extern uint16 *LiqType; @@ -35,9 +35,11 @@ WMORoot::WMORoot(std::string &filename) : filename(filename) { } +extern HANDLE WorldMpq; + bool WMORoot::open() { - MPQFile f(filename.c_str()); + MPQFile f(WorldMpq, filename.c_str()); if(f.isEof ()) { printf("No such file.\n"); @@ -143,7 +145,7 @@ WMOGroup::WMOGroup(std::string &filename) : filename(filename), bool WMOGroup::open() { - MPQFile f(filename.c_str()); + MPQFile f(WorldMpq, filename.c_str()); if(f.isEof ()) { printf("No such file.\n"); diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index 8c5993d91d5..7020bb90f12 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -24,6 +24,7 @@ #include <string> #include <set> #include "vec3d.h" +#include "mpqfile.h" // MOPY flags #define WMO_MATERIAL_NOCAMCOLLIDE 0x01 |